Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-geoip2 for openSUSE:Factory 
checked in at 2026-07-23 23:08:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-geoip2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-geoip2.new.2004 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-geoip2"

Thu Jul 23 23:08:51 2026 rev:25 rq:1366937 version:5.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-geoip2/python-geoip2.changes      
2026-02-02 14:55:59.964560008 +0100
+++ /work/SRC/openSUSE:Factory/.python-geoip2.new.2004/python-geoip2.changes    
2026-07-23 23:09:24.230309370 +0200
@@ -1,0 +2,19 @@
+Tue Jul 21 11:32:46 UTC 2026 - Paolo Stivanin <[email protected]>
+
+- Update to 5.3.0:
+  * The version is now retrieved from package metadata at runtime using
+    importlib.metadata. This reduces the chance of version inconsistencies
+    during releases.
+  * The async client now builds its Authorization header with
+    aiohttp.encode_basic_auth() instead of the aiohttp.BasicAuth /
+    auth= parameter, which are deprecated as of aiohttp 3.14.0. As a result,
+    the minimum required aiohttp version is now 3.14.0.
+  * A new residential attribute has been added to
+    geoip2.records.Anonymizer. This is a geoip2.records.AnonymizerFeed
+    object providing residential proxy data for the network and contains the
+    following fields: confidence, network_last_seen, and
+    provider_name. This attribute may be populated even when no other
+    anonymizer attributes are set, so the anonymizer object may now
+    contain only this attribute.
+
+-------------------------------------------------------------------

Old:
----
  python-geoip2-5.2.0.tar.gz

New:
----
  python-geoip2-5.3.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-geoip2.spec ++++++
--- /var/tmp/diff_new_pack.QP1Kst/_old  2026-07-23 23:09:24.790329035 +0200
+++ /var/tmp/diff_new_pack.QP1Kst/_new  2026-07-23 23:09:24.794329175 +0200
@@ -18,14 +18,14 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-geoip2
-Version:        5.2.0
+Version:        5.3.0
 Release:        0
 Summary:        MaxMind GeoIP2 Python API
 License:        Apache-2.0
 Group:          Development/Languages/Python
 URL:            https://github.com/maxmind/GeoIP2-python
 Source:         
https://files.pythonhosted.org/packages/source/g/geoip2/geoip2-%{version}.tar.gz#/%{name}-%{version}.tar.gz
-%if 0%{?suse_version} <= 1600
+%if 0%{?suse_version} <= 1700
 # partial reversion of 83825a8 ("Switch to uv build")
 Patch0:         pyproject-setuptools.patch
 BuildRequires:  %{python_module setuptools}

++++++ pyproject-setuptools.patch ++++++
--- /var/tmp/diff_new_pack.QP1Kst/_old  2026-07-23 23:09:24.842330861 +0200
+++ /var/tmp/diff_new_pack.QP1Kst/_new  2026-07-23 23:09:24.846331002 +0200
@@ -1,14 +1,14 @@
---- a/pyproject.toml   1970-01-01 01:00:00.000000000 +0100
-+++ b/pyproject.toml   2026-01-29 19:40:59.478833382 +0100
-@@ -43,19 +43,11 @@
+Index: geoip2-5.3.0/pyproject.toml
+===================================================================
+--- geoip2-5.3.0.orig/pyproject.toml
++++ geoip2-5.3.0/pyproject.toml
+@@ -42,19 +42,11 @@ lint = [
  ]
  
  [build-system]
--requires = ["uv_build>=0.7.19,<0.8.0"]
+-requires = ["uv_build>=0.11.26,<0.12.0"]
 -build-backend = "uv_build"
-+requires = ["setuptools"]
-+build-backend = "setuptools.build_meta"
- 
+-
 -[tool.uv.build-backend]
 -source-include = [
 -    "HISTORY.rst",
@@ -19,9 +19,12 @@
 -    "tests/*.py",
 -    "tests/data/test-data/*.mmdb"
 -]
++requires = ["setuptools"]
++build-backend = "setuptools.build_meta"
++ 
 +[tool.setuptools.package-data]
 +geoip2 = ["py.typed"]
  
  [project.urls]
- Homepage = "https://www.maxmind.com/";
+ Homepage = "https://www.maxmind.com/en/home";
 

++++++ python-geoip2-5.2.0.tar.gz -> python-geoip2-5.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/HISTORY.rst new/geoip2-5.3.0/HISTORY.rst
--- old/geoip2-5.2.0/HISTORY.rst        1970-01-01 01:00:00.000000000 +0100
+++ new/geoip2-5.3.0/HISTORY.rst        1970-01-01 01:00:00.000000000 +0100
@@ -4,6 +4,24 @@
 History
 -------
 
+5.3.0 (2026-07-16)
+++++++++++++++++++
+
+* The version is now retrieved from package metadata at runtime using
+  ``importlib.metadata``. This reduces the chance of version inconsistencies
+  during releases.
+* The async client now builds its ``Authorization`` header with
+  ``aiohttp.encode_basic_auth()`` instead of the ``aiohttp.BasicAuth`` /
+  ``auth=`` parameter, which are deprecated as of aiohttp 3.14.0. As a result,
+  the minimum required ``aiohttp`` version is now 3.14.0.
+* A new ``residential`` attribute has been added to
+  ``geoip2.records.Anonymizer``. This is a ``geoip2.records.AnonymizerFeed``
+  object providing residential proxy data for the network and contains the
+  following fields: ``confidence``, ``network_last_seen``, and
+  ``provider_name``. This attribute may be populated even when no other
+  anonymizer attributes are set, so the ``anonymizer`` object may now
+  contain only this attribute.
+
 5.2.0 (2025-11-20)
 ++++++++++++++++++
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/PKG-INFO new/geoip2-5.3.0/PKG-INFO
--- old/geoip2-5.2.0/PKG-INFO   1970-01-01 01:00:00.000000000 +0100
+++ new/geoip2-5.3.0/PKG-INFO   1970-01-01 01:00:00.000000000 +0100
@@ -1,7 +1,7 @@
 Metadata-Version: 2.4
 Name: geoip2
-Version: 5.2.0
-Summary: MaxMind GeoIP2 API
+Version: 5.3.0
+Summary: MaxMind GeoIP API
 Author: Gregory Oschwald
 Author-email: Gregory Oschwald <[email protected]>
 License-Expression: Apache-2.0
@@ -19,26 +19,26 @@
 Classifier: Programming Language :: Python :: 3.14
 Classifier: Topic :: Internet
 Classifier: Topic :: Internet :: Proxy Servers
-Requires-Dist: aiohttp>=3.6.2,<4.0.0
+Requires-Dist: aiohttp>=3.14.1,<4.0.0
 Requires-Dist: maxminddb>=3.0.0,<4.0.0
 Requires-Dist: requests>=2.24.0,<3.0.0
 Requires-Python: >=3.10
-Project-URL: Documentation, https://geoip2.readthedocs.org/
-Project-URL: Homepage, https://www.maxmind.com/
-Project-URL: Issue Tracker, https://github.com/maxmind/GeoIP2-python/issues
+Project-URL: Homepage, https://www.maxmind.com/en/home
+Project-URL: Documentation, https://geoip2.readthedocs.io/en/latest/
 Project-URL: Source Code, https://github.com/maxmind/GeoIP2-python
+Project-URL: Issue Tracker, https://github.com/maxmind/GeoIP2-python/issues
 Description-Content-Type: text/x-rst
 
-=========================
-MaxMind GeoIP2 Python API
-=========================
+========================
+MaxMind GeoIP Python API
+========================
 
 Description
 -----------
 
-This package provides an API for the GeoIP2 and GeoLite2 `web services
-<https://dev.maxmind.com/geoip/docs/web-services?lang=en>`_ and `databases
-<https://dev.maxmind.com/geoip/docs/databases?lang=en>`_.
+This package provides an API for the GeoIP and GeoLite `web services
+<https://dev.maxmind.com/geoip/docs/web-services/?lang=en>`_ and `databases
+<https://dev.maxmind.com/geoip/docs/databases/?lang=en>`_.
 
 Installation
 ------------
@@ -68,7 +68,7 @@
 --------------------
 
 IP geolocation is inherently imprecise. Locations are often near the center of
-the population. Any location provided by a GeoIP2 database or web service
+the population. Any location provided by a GeoIP database or web service
 should not be used to identify a particular address or household.
 
 Web Service Usage
@@ -76,10 +76,10 @@
 
 To use this API, you first construct either a ``geoip2.webservice.Client`` or
 ``geoip2.webservice.AsyncClient``, passing your MaxMind ``account_id`` and
-``license_key`` to the constructor. To use the GeoLite2 web service instead of
-the GeoIP2 web service, set the optional ``host`` keyword argument to
-``geolite.info``. To use the Sandbox GeoIP2 web service instead of the
-production GeoIP2 web service, set the optional ``host`` keyword argument to
+``license_key`` to the constructor. To use the GeoLite web service instead of
+the GeoIP web service, set the optional ``host`` keyword argument to
+``geolite.info``. To use the Sandbox GeoIP web service instead of the
+production GeoIP web service, set the optional ``host`` keyword argument to
 ``sandbox.maxmind.com``.
 
 After doing this, you may call the method corresponding to request type
@@ -101,14 +101,14 @@
     >>> # This creates a Client object that can be reused across requests.
     >>> # Replace "42" with your account ID and "license_key" with your license
     >>> # key. Set the "host" keyword argument to "geolite.info" to use the
-    >>> # GeoLite2 web service instead of the GeoIP2 web service. Set the
+    >>> # GeoLite web service instead of the GeoIP web service. Set the
     >>> # "host" keyword argument to "sandbox.maxmind.com" to use the Sandbox
-    >>> # GeoIP2 web service instead of the production GeoIP2 web service.
+    >>> # GeoIP web service instead of the production GeoIP web service.
     >>> with geoip2.webservice.Client(42, 'license_key') as client:
     >>>
     >>>     # Replace "city" with the method corresponding to the web service
     >>>     # that you are using, i.e., "country", "city", or "insights". 
Please
-    >>>     # note that Insights is not supported by the GeoLite2 web service.
+    >>>     # note that Insights is not supported by the GeoLite web service.
     >>>     response = client.city('203.0.113.0')
     >>>
     >>>     response.country.iso_code
@@ -153,14 +153,14 @@
     >>>     #
     >>>     # Replace "42" with your account ID and "license_key" with your 
license
     >>>     # key. Set the "host" keyword argument to "geolite.info" to use the
-    >>>     # GeoLite2 web service instead of the GeoIP2 web service. Set the
+    >>>     # GeoLite web service instead of the GeoIP web service. Set the
     >>>     # "host" keyword argument to "sandbox.maxmind.com" to use the 
Sandbox
-    >>>     # GeoIP2 web service instead of the production GeoIP2 web service.
+    >>>     # GeoIP web service instead of the production GeoIP web service.
     >>>     async with geoip2.webservice.AsyncClient(42, 'license_key') as 
client:
     >>>
     >>>         # Replace "city" with the method corresponding to the web 
service
     >>>         # that you are using, i.e., "country", "city", or "insights". 
Please
-    >>>         # note that Insights is not supported by the GeoLite2 web 
service.
+    >>>         # note that Insights is not supported by the GeoLite web 
service.
     >>>         response = await client.city('203.0.113.0')
     >>>
     >>>         response.country.iso_code
@@ -195,7 +195,7 @@
 -----------------------------
 
 For details on the possible errors returned by the web service itself, see
-https://dev.maxmind.com/geoip/docs/web-services?lang=en for the GeoIP2 web
+https://dev.maxmind.com/geoip/docs/web-services/?lang=en for the GeoIP web
 service docs.
 
 If the web service returns an explicit error document, this is thrown as a
@@ -546,7 +546,8 @@
 -----------------------
 
 If the problem you find is that an IP address is incorrectly mapped, please
-`submit your correction to MaxMind <https://www.maxmind.com/en/correction>`_.
+`submit your correction to MaxMind
+<https://www.maxmind.com/en/geoip-data-correction-request>`_.
 
 If you find some other sort of mistake, like an incorrect spelling, please
 check the `GeoNames site <https://www.geonames.org/>`_ first. Once you've
@@ -557,20 +558,12 @@
 
 If you are a paying MaxMind customer and you're not sure where to submit a
 correction, please `contact MaxMind support
-<https://www.maxmind.com/en/support>`_ for help.
-
-Requirements
-------------
-
-Python 3.9 or greater is required. Older versions are not supported.
-
-The Requests HTTP library is also required. See
-<https://pypi.org/project/requests/> for details.
+<https://support.maxmind.com/knowledge-base>`_ for help.
 
 Versioning
 ----------
 
-The GeoIP2 Python API uses `Semantic Versioning <https://semver.org/>`_.
+The GeoIP Python API uses `Semantic Versioning <https://semver.org/>`_.
 
 Support
 -------
@@ -580,4 +573,4 @@
 
 If you are having an issue with a MaxMind service that is not specific to the
 client API, please contact `MaxMind support
-<https://www.maxmind.com/en/support>`_ for assistance.
+<https://support.maxmind.com/knowledge-base>`_ for assistance.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/README.rst new/geoip2-5.3.0/README.rst
--- old/geoip2-5.2.0/README.rst 1970-01-01 01:00:00.000000000 +0100
+++ new/geoip2-5.3.0/README.rst 1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +1,13 @@
-=========================
-MaxMind GeoIP2 Python API
-=========================
+========================
+MaxMind GeoIP Python API
+========================
 
 Description
 -----------
 
-This package provides an API for the GeoIP2 and GeoLite2 `web services
-<https://dev.maxmind.com/geoip/docs/web-services?lang=en>`_ and `databases
-<https://dev.maxmind.com/geoip/docs/databases?lang=en>`_.
+This package provides an API for the GeoIP and GeoLite `web services
+<https://dev.maxmind.com/geoip/docs/web-services/?lang=en>`_ and `databases
+<https://dev.maxmind.com/geoip/docs/databases/?lang=en>`_.
 
 Installation
 ------------
@@ -37,7 +37,7 @@
 --------------------
 
 IP geolocation is inherently imprecise. Locations are often near the center of
-the population. Any location provided by a GeoIP2 database or web service
+the population. Any location provided by a GeoIP database or web service
 should not be used to identify a particular address or household.
 
 Web Service Usage
@@ -45,10 +45,10 @@
 
 To use this API, you first construct either a ``geoip2.webservice.Client`` or
 ``geoip2.webservice.AsyncClient``, passing your MaxMind ``account_id`` and
-``license_key`` to the constructor. To use the GeoLite2 web service instead of
-the GeoIP2 web service, set the optional ``host`` keyword argument to
-``geolite.info``. To use the Sandbox GeoIP2 web service instead of the
-production GeoIP2 web service, set the optional ``host`` keyword argument to
+``license_key`` to the constructor. To use the GeoLite web service instead of
+the GeoIP web service, set the optional ``host`` keyword argument to
+``geolite.info``. To use the Sandbox GeoIP web service instead of the
+production GeoIP web service, set the optional ``host`` keyword argument to
 ``sandbox.maxmind.com``.
 
 After doing this, you may call the method corresponding to request type
@@ -70,14 +70,14 @@
     >>> # This creates a Client object that can be reused across requests.
     >>> # Replace "42" with your account ID and "license_key" with your license
     >>> # key. Set the "host" keyword argument to "geolite.info" to use the
-    >>> # GeoLite2 web service instead of the GeoIP2 web service. Set the
+    >>> # GeoLite web service instead of the GeoIP web service. Set the
     >>> # "host" keyword argument to "sandbox.maxmind.com" to use the Sandbox
-    >>> # GeoIP2 web service instead of the production GeoIP2 web service.
+    >>> # GeoIP web service instead of the production GeoIP web service.
     >>> with geoip2.webservice.Client(42, 'license_key') as client:
     >>>
     >>>     # Replace "city" with the method corresponding to the web service
     >>>     # that you are using, i.e., "country", "city", or "insights". 
Please
-    >>>     # note that Insights is not supported by the GeoLite2 web service.
+    >>>     # note that Insights is not supported by the GeoLite web service.
     >>>     response = client.city('203.0.113.0')
     >>>
     >>>     response.country.iso_code
@@ -122,14 +122,14 @@
     >>>     #
     >>>     # Replace "42" with your account ID and "license_key" with your 
license
     >>>     # key. Set the "host" keyword argument to "geolite.info" to use the
-    >>>     # GeoLite2 web service instead of the GeoIP2 web service. Set the
+    >>>     # GeoLite web service instead of the GeoIP web service. Set the
     >>>     # "host" keyword argument to "sandbox.maxmind.com" to use the 
Sandbox
-    >>>     # GeoIP2 web service instead of the production GeoIP2 web service.
+    >>>     # GeoIP web service instead of the production GeoIP web service.
     >>>     async with geoip2.webservice.AsyncClient(42, 'license_key') as 
client:
     >>>
     >>>         # Replace "city" with the method corresponding to the web 
service
     >>>         # that you are using, i.e., "country", "city", or "insights". 
Please
-    >>>         # note that Insights is not supported by the GeoLite2 web 
service.
+    >>>         # note that Insights is not supported by the GeoLite web 
service.
     >>>         response = await client.city('203.0.113.0')
     >>>
     >>>         response.country.iso_code
@@ -164,7 +164,7 @@
 -----------------------------
 
 For details on the possible errors returned by the web service itself, see
-https://dev.maxmind.com/geoip/docs/web-services?lang=en for the GeoIP2 web
+https://dev.maxmind.com/geoip/docs/web-services/?lang=en for the GeoIP web
 service docs.
 
 If the web service returns an explicit error document, this is thrown as a
@@ -515,7 +515,8 @@
 -----------------------
 
 If the problem you find is that an IP address is incorrectly mapped, please
-`submit your correction to MaxMind <https://www.maxmind.com/en/correction>`_.
+`submit your correction to MaxMind
+<https://www.maxmind.com/en/geoip-data-correction-request>`_.
 
 If you find some other sort of mistake, like an incorrect spelling, please
 check the `GeoNames site <https://www.geonames.org/>`_ first. Once you've
@@ -526,20 +527,12 @@
 
 If you are a paying MaxMind customer and you're not sure where to submit a
 correction, please `contact MaxMind support
-<https://www.maxmind.com/en/support>`_ for help.
-
-Requirements
-------------
-
-Python 3.9 or greater is required. Older versions are not supported.
-
-The Requests HTTP library is also required. See
-<https://pypi.org/project/requests/> for details.
+<https://support.maxmind.com/knowledge-base>`_ for help.
 
 Versioning
 ----------
 
-The GeoIP2 Python API uses `Semantic Versioning <https://semver.org/>`_.
+The GeoIP Python API uses `Semantic Versioning <https://semver.org/>`_.
 
 Support
 -------
@@ -549,4 +542,4 @@
 
 If you are having an issue with a MaxMind service that is not specific to the
 client API, please contact `MaxMind support
-<https://www.maxmind.com/en/support>`_ for assistance.
+<https://support.maxmind.com/knowledge-base>`_ for assistance.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/pyproject.toml 
new/geoip2-5.3.0/pyproject.toml
--- old/geoip2-5.2.0/pyproject.toml     1970-01-01 01:00:00.000000000 +0100
+++ new/geoip2-5.3.0/pyproject.toml     1970-01-01 01:00:00.000000000 +0100
@@ -1,12 +1,12 @@
 [project]
 name = "geoip2"
-version = "5.2.0"
-description = "MaxMind GeoIP2 API"
+version = "5.3.0"
+description = "MaxMind GeoIP API"
 authors = [
     {name = "Gregory Oschwald", email = "[email protected]"},
 ]
 dependencies = [
-    "aiohttp>=3.6.2,<4.0.0",
+    "aiohttp>=3.14.1,<4.0.0",
     "maxminddb>=3.0.0,<4.0.0",
     "requests>=2.24.0,<3.0.0",
 ]
@@ -32,18 +32,17 @@
 
 [dependency-groups]
 dev = [
-    "pytest>=8.3.5",
+    "pytest>=9.1.1",
     "pytest-httpserver>=1.0.10",
     "tox-uv>=1.29.0",
-    "types-requests>=2.32.0.20250328",
 ]
 lint = [
     "mypy>=1.15.0",
-    "ruff>=0.11.6",
+    "ruff>=0.15.20",
 ]
 
 [build-system]
-requires = ["uv_build>=0.7.19,<0.8.0"]
+requires = ["uv_build>=0.11.26,<0.12.0"]
 build-backend = "uv_build"
 
 [tool.uv.build-backend]
@@ -58,8 +57,8 @@
 ]
 
 [project.urls]
-Homepage = "https://www.maxmind.com/";
-Documentation = "https://geoip2.readthedocs.org/";
+Homepage = "https://www.maxmind.com/en/home";
+Documentation = "https://geoip2.readthedocs.io/en/latest/";
 "Source Code" = "https://github.com/maxmind/GeoIP2-python";
 "Issue Tracker" = "https://github.com/maxmind/GeoIP2-python/issues";
 
@@ -88,7 +87,7 @@
 
 [tool.ruff.lint.per-file-ignores]
 "docs/*" = ["ALL"]
-"src/geoip2/{models,records}.py" = [ "ANN401", "D107", "PLR0913" ]
+"src/geoip2/{models,records}.py" = [ "D107", "PLR0913" ]
 # FBT003: We use assertIs with boolean literals to verify values are actual
 # booleans (True/False), not just truthy/falsy values
 "tests/*" = ["ANN201", "D", "FBT003"]
@@ -105,6 +104,7 @@
 skip_missing_interpreters = false
 
 [tool.tox.env_run_base]
+runner = "uv-venv-lock-runner"
 dependency_groups = [
   "dev",
 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/src/geoip2/__init__.py 
new/geoip2-5.3.0/src/geoip2/__init__.py
--- old/geoip2-5.2.0/src/geoip2/__init__.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/src/geoip2/__init__.py     1970-01-01 01:00:00.000000000 
+0100
@@ -1,7 +1,5 @@
 """geoip2 client library."""
 
-__title__ = "geoip2"
-__version__ = "5.2.0"
-__author__ = "Gregory Oschwald"
-__license__ = "Apache License, Version 2.0"
-__copyright__ = "Copyright (c) 2013-2025 MaxMind, Inc."
+from importlib.metadata import version
+
+__version__ = version("geoip2")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/src/geoip2/database.py 
new/geoip2-5.3.0/src/geoip2/database.py
--- old/geoip2-5.2.0/src/geoip2/database.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/src/geoip2/database.py     1970-01-01 01:00:00.000000000 
+0100
@@ -51,9 +51,9 @@
 
 
 class Reader:
-    """GeoIP2 database Reader object.
+    """GeoIP database Reader object.
 
-    Instances of this class provide a reader for the GeoIP2 database format.
+    Instances of this class provide a reader for the GeoIP database format.
     IP addresses can be looked up using the ``country`` and ``city`` methods.
 
     The basic API for this class is the same for every database. First, you
@@ -81,9 +81,9 @@
         locales: Sequence[str] | None = None,
         mode: int = MODE_AUTO,
     ) -> None:
-        """Create GeoIP2 Reader.
+        """Create GeoIP Reader.
 
-        :param fileish: A path to the GeoIP2 database or an existing file
+        :param fileish: A path to the GeoIP database or an existing file
           descriptor pointing to the database. Note that a file descriptor
           is only valid when mode is MODE_FD.
         :param locales: This is list of locale codes. This argument will be
@@ -94,7 +94,7 @@
           multiple names (country, city, etc.), its name property will return
           the name in the first locale that has one.
 
-          Note that the only locale which is always present in the GeoIP2
+          Note that the only locale which is always present in the GeoIP
           data is "en". If you do not include this locale, the name property
           may end up returning None even when the record has an English name.
 
@@ -314,5 +314,5 @@
         return self._db_reader.metadata()
 
     def close(self) -> None:
-        """Close the GeoIP2 database."""
+        """Close the GeoIP database."""
         self._db_reader.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/src/geoip2/models.py 
new/geoip2-5.3.0/src/geoip2/models.py
--- old/geoip2-5.2.0/src/geoip2/models.py       1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/src/geoip2/models.py       1970-01-01 01:00:00.000000000 
+0100
@@ -1,8 +1,8 @@
-"""The models for response from th GeoIP2 web service and databases.
+"""The models for response from the GeoIP web service and databases.
 
 The only difference between the City and Insights model classes is which
 fields in each record may be populated. See
-https://dev.maxmind.com/geoip/docs/web-services?lang=en for more details.
+https://dev.maxmind.com/geoip/docs/web-services/?lang=en for more details.
 """
 
 from __future__ import annotations
@@ -63,7 +63,7 @@
         registered_country: dict[str, Any] | None = None,
         represented_country: dict[str, Any] | None = None,
         traits: dict[str, Any] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self._locales = locales
         self.continent = geoip2.records.Continent(locales, **(continent or {}))
@@ -127,7 +127,7 @@
         represented_country: dict[str, Any] | None = None,
         subdivisions: list[dict[str, Any]] | None = None,
         traits: dict[str, Any] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(
             locales,
@@ -147,7 +147,7 @@
 
 
 class Insights(City):
-    """Model for the GeoIP2 Insights web service."""
+    """Model for the GeoIP Insights web service."""
 
     anonymizer: geoip2.records.Anonymizer
     """Anonymizer object for the requested IP address. This object contains
@@ -171,7 +171,7 @@
         represented_country: dict[str, Any] | None = None,
         subdivisions: list[dict[str, Any]] | None = None,
         traits: dict[str, Any] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(
             locales,
@@ -192,7 +192,7 @@
 
 
 class Enterprise(City):
-    """Model for the GeoIP2 Enterprise database."""
+    """Model for the GeoIP Enterprise database."""
 
 
 class SimpleModel(Model, metaclass=ABCMeta):
@@ -259,7 +259,7 @@
 
 
 class AnonymousIP(SimpleModel):
-    """Model class for the GeoIP2 Anonymous IP."""
+    """Model class for the GeoIP Anonymous IP."""
 
     is_anonymous: bool
     """This is true if the IP address belongs to any sort of anonymous 
network."""
@@ -301,7 +301,7 @@
         is_tor_exit_node: bool = False,
         network: str | None = None,
         prefix_len: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(ip_address, network, prefix_len)
         self.is_anonymous = is_anonymous
@@ -345,7 +345,7 @@
         network_last_seen: str | None = None,
         prefix_len: int | None = None,
         provider_name: str | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(
             is_anonymous=is_anonymous,
@@ -365,7 +365,7 @@
 
 
 class ASN(SimpleModel):
-    """Model class for the GeoLite2 ASN."""
+    """Model class for the GeoLite ASN."""
 
     autonomous_system_number: int | None
     """The autonomous system number associated with the IP address."""
@@ -383,7 +383,7 @@
         autonomous_system_organization: str | None = None,
         network: str | None = None,
         prefix_len: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(ip_address, network, prefix_len)
         self.autonomous_system_number = autonomous_system_number
@@ -391,7 +391,7 @@
 
 
 class ConnectionType(SimpleModel):
-    """Model class for the GeoIP2 Connection-Type."""
+    """Model class for the GeoIP Connection-Type."""
 
     connection_type: str | None
     """The connection type may take the following values:
@@ -412,14 +412,14 @@
         connection_type: str | None = None,
         network: str | None = None,
         prefix_len: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(ip_address, network, prefix_len)
         self.connection_type = connection_type
 
 
 class Domain(SimpleModel):
-    """Model class for the GeoIP2 Domain."""
+    """Model class for the GeoIP Domain."""
 
     domain: str | None
     """The domain associated with the IP address."""
@@ -431,14 +431,14 @@
         domain: str | None = None,
         network: str | None = None,
         prefix_len: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(ip_address, network, prefix_len)
         self.domain = domain
 
 
 class ISP(ASN):
-    """Model class for the GeoIP2 ISP."""
+    """Model class for the GeoIP ISP."""
 
     isp: str | None
     """The name of the ISP associated with the IP address."""
@@ -470,7 +470,7 @@
         organization: str | None = None,
         network: str | None = None,
         prefix_len: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         super().__init__(
             autonomous_system_number=autonomous_system_number,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/src/geoip2/records.py 
new/geoip2-5.3.0/src/geoip2/records.py
--- old/geoip2-5.2.0/src/geoip2/records.py      1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/src/geoip2/records.py      1970-01-01 01:00:00.000000000 
+0100
@@ -74,7 +74,7 @@
         confidence: int | None = None,
         geoname_id: int | None = None,
         names: dict[str, str] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.confidence = confidence
         self.geoname_id = geoname_id
@@ -102,7 +102,7 @@
         code: str | None = None,
         geoname_id: int | None = None,
         names: dict[str, str] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.code = code
         self.geoname_id = geoname_id
@@ -139,7 +139,7 @@
         is_in_european_union: bool = False,
         iso_code: str | None = None,
         names: dict[str, str] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.confidence = confidence
         self.geoname_id = geoname_id
@@ -172,7 +172,7 @@
         iso_code: str | None = None,
         names: dict[str, str] | None = None,
         type: str | None = None,  # noqa: A002
-        **_: Any,
+        **_: object,
     ) -> None:
         self.type = type
         super().__init__(
@@ -239,7 +239,7 @@
         metro_code: int | None = None,
         population_density: int | None = None,
         time_zone: str | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.average_income = average_income
         self.accuracy_radius = accuracy_radius
@@ -258,15 +258,63 @@
     calling.
     """
 
-    def __init__(self, *, queries_remaining: int | None = None, **_: Any) -> 
None:
+    def __init__(self, *, queries_remaining: int | None = None, **_: object) 
-> None:
         self.queries_remaining = queries_remaining
 
 
+class AnonymizerFeed(Record):
+    """Contains data for one type of anonymizer detection.
+
+    This class contains data for one type of anonymizer detection,
+    currently residential proxies. Additional feeds may be added in the
+    future.
+
+    This record is returned by ``insights`` as the ``residential`` attribute
+    of :py:class:`Anonymizer`.
+    """
+
+    confidence: int | None
+    """A score ranging from 1 to 99 that represents our percent confidence
+    that the network is currently part of this anonymizer feed. This
+    attribute is only available from the Insights end point.
+    """
+
+    network_last_seen: datetime.date | None
+    """The last day that the network was sighted in our analysis of this
+    anonymizer feed. This attribute is only available from the Insights end
+    point.
+    """
+
+    provider_name: str | None
+    """The name of the provider associated with the network in this
+    anonymizer feed. This attribute is only available from the Insights end
+    point.
+    """
+
+    def __init__(
+        self,
+        *,
+        confidence: int | None = None,
+        network_last_seen: str | None = None,
+        provider_name: str | None = None,
+        **_: object,
+    ) -> None:
+        self.confidence = confidence
+        self.network_last_seen = (
+            datetime.date.fromisoformat(network_last_seen)
+            if network_last_seen
+            else None
+        )
+        self.provider_name = provider_name
+
+
 class Anonymizer(Record):
     """Contains data for the anonymizer record associated with an IP address.
 
     This class contains the anonymizer data associated with an IP address.
 
+    Note that this object may contain only the ``residential`` attribute.
+
     This record is returned by ``insights``.
     """
 
@@ -288,6 +336,12 @@
     point.
     """
 
+    residential: AnonymizerFeed
+    """Residential proxy data for the network associated with the IP address.
+    This may be populated even when no other anonymizer attributes are set.
+    This attribute is only available from the Insights end point.
+    """
+
     is_anonymous: bool
     """This is true if the IP address belongs to any sort of anonymous network.
     This attribute is only available from the Insights end point.
@@ -337,7 +391,8 @@
         is_tor_exit_node: bool = False,
         network_last_seen: str | None = None,
         provider_name: str | None = None,
-        **_: Any,
+        residential: dict[str, Any] | None = None,
+        **_: object,
     ) -> None:
         self.confidence = confidence
         self.is_anonymous = is_anonymous
@@ -352,6 +407,7 @@
             else None
         )
         self.provider_name = provider_name
+        self.residential = AnonymizerFeed(**(residential or {}))
 
 
 class Postal(Record):
@@ -378,7 +434,7 @@
         *,
         code: str | None = None,
         confidence: int | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.code = code
         self.confidence = confidence
@@ -412,7 +468,7 @@
         geoname_id: int | None = None,
         iso_code: str | None = None,
         names: dict[str, str] | None = None,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.confidence = confidence
         self.geoname_id = geoname_id
@@ -527,6 +583,11 @@
     responsive to traffic on your network. If you need realtime IP risk scoring
     based on behavioral signals on your own network, please use minFraud.
 
+    We do not provide an IP risk snapshot for low-risk networks. If this field
+    is not populated, we either do not have signals for the network or the
+    signals we have show that the network is low-risk. If you would like to get
+    signals for low-risk networks, please use the minFraud web services.
+
     This attribute is only available from the Insights end point.
     """
     _ip_address: IPAddress | None
@@ -541,8 +602,8 @@
     """This is true if the IP is an anonymous proxy.
 
     .. deprecated:: 2.2.0
-       Use our `GeoIP2 Anonymous IP database
-       <https://www.maxmind.com/en/geoip2-anonymous-ip-database GeoIP2>`_
+       Use our `GeoIP Anonymous IP database
+       <https://www.maxmind.com/en/geoip-anonymous-ip-database>`_
        instead.
     """
     is_anonymous_vpn: bool
@@ -561,8 +622,8 @@
     is_anycast: bool
     """This returns true if the IP address belongs to an
     `anycast network <https://en.wikipedia.org/wiki/Anycast>`_.
-    This is available for the GeoIP2 Country, City Plus, and Insights
-    web services and the GeoIP2 Country, City, and Enterprise databases.
+    This is available for the GeoIP Country, City Plus, and Insights
+    web services and the GeoIP Country, City, and Enterprise databases.
     """
     is_hosting_provider: bool
     """This is true if the IP address belongs to a hosting or VPN provider
@@ -703,7 +764,7 @@
         mobile_country_code: str | None = None,
         mobile_network_code: str | None = None,
         is_anycast: bool = False,
-        **_: Any,
+        **_: object,
     ) -> None:
         self.autonomous_system_number = autonomous_system_number
         self.autonomous_system_organization = autonomous_system_organization
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/src/geoip2/webservice.py 
new/geoip2-5.3.0/src/geoip2/webservice.py
--- old/geoip2-5.2.0/src/geoip2/webservice.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/src/geoip2/webservice.py   1970-01-01 01:00:00.000000000 
+0100
@@ -1,4 +1,4 @@
-"""Client for GeoIP2 and GeoLite2 web services.
+"""Client for GeoIP and GeoLite web services.
 
 The web services are Country, City Plus, and Insights. Each service returns a
 different set of data about an IP address, with Country returning the least
@@ -230,22 +230,22 @@
 
 
 class AsyncClient(BaseClient):
-    """An async GeoIP2 client.
+    """An async GeoIP client.
 
     It accepts the following required arguments:
 
     :param account_id: Your MaxMind account ID.
     :param license_key: Your MaxMind license key.
 
-    Go to https://www.maxmind.com/en/my_license_key to see your MaxMind
-    account ID and license key.
+    Go to https://www.maxmind.com/en/accounts/current/license-key to see
+    your MaxMind account ID and license key.
 
     The following keyword arguments are also accepted:
 
     :param host: The hostname to make a request against. This defaults to
-      "geoip.maxmind.com". To use the GeoLite2 web service instead of the
-      GeoIP2 web service, set this to "geolite.info". To use the Sandbox
-      GeoIP2 web service instead of the production GeoIP2 web service, set
+      "geoip.maxmind.com". To use the GeoLite web service instead of the
+      GeoIP web service, set this to "geolite.info". To use the Sandbox
+      GeoIP web service instead of the production GeoIP web service, set
       this to "sandbox.maxmind.com". The sandbox allows you to experiment
       with the API without affecting your production data.
     :param locales: This is list of locale codes. This argument will be
@@ -256,7 +256,7 @@
       multiple names (country, city, etc.), its name property will return
       the name in the first locale that has one.
 
-      Note that the only locale which is always present in the GeoIP2
+      Note that the only locale which is always present in the GeoIP
       data is "en". If you do not include this locale, the name property
       may end up returning None even when the record has an English name.
 
@@ -319,7 +319,7 @@
         )
 
     async def country(self, ip_address: IPAddress = "me") -> Country:
-        """Call the GeoIP2 Country endpoint with the specified IP.
+        """Call the GeoIP Country endpoint with the specified IP.
 
         :param ip_address: IPv4 or IPv6 address as a string. If no address
           is provided, the address that the web service is called from will
@@ -336,7 +336,7 @@
     async def insights(self, ip_address: IPAddress = "me") -> Insights:
         """Call the Insights endpoint with the specified IP.
 
-        Insights is only supported by the GeoIP2 web service. The GeoLite2 web
+        Insights is only supported by the GeoIP web service. The GeoLite web
         service does not support it.
 
         :param ip_address: IPv4 or IPv6 address as a string. If no address
@@ -354,8 +354,14 @@
     async def _session(self) -> aiohttp.ClientSession:
         if not hasattr(self, "_existing_session"):
             self._existing_session = aiohttp.ClientSession(
-                auth=aiohttp.BasicAuth(self._account_id, self._license_key),
-                headers={"Accept": "application/json", "User-Agent": 
_AIOHTTP_UA},
+                headers={
+                    "Accept": "application/json",
+                    "Authorization": aiohttp.encode_basic_auth(
+                        self._account_id,
+                        self._license_key,
+                    ),
+                    "User-Agent": _AIOHTTP_UA,
+                },
                 timeout=aiohttp.ClientTimeout(total=self._timeout),
             )
 
@@ -399,22 +405,22 @@
 
 
 class Client(BaseClient):
-    """A synchronous GeoIP2 client.
+    """A synchronous GeoIP client.
 
     It accepts the following required arguments:
 
     :param account_id: Your MaxMind account ID.
     :param license_key: Your MaxMind license key.
 
-    Go to https://www.maxmind.com/en/my_license_key to see your MaxMind
-    account ID and license key.
+    Go to https://www.maxmind.com/en/accounts/current/license-key to see
+    your MaxMind account ID and license key.
 
     The following keyword arguments are also accepted:
 
     :param host: The hostname to make a request against. This defaults to
-      "geoip.maxmind.com". To use the GeoLite2 web service instead of the
-      GeoIP2 web service, set this to "geolite.info". To use the Sandbox
-      GeoIP2 web service instead of the production GeoIP2 web service, set
+      "geoip.maxmind.com". To use the GeoLite web service instead of the
+      GeoIP web service, set this to "geolite.info". To use the Sandbox
+      GeoIP web service instead of the production GeoIP web service, set
       this to "sandbox.maxmind.com". The sandbox allows you to experiment
       with the API without affecting your production data.
     :param locales: This is list of locale codes. This argument will be
@@ -425,7 +431,7 @@
       multiple names (country, city, etc.), its name property will return
       the name in the first locale that has one.
 
-      Note that the only locale which is always present in the GeoIP2
+      Note that the only locale which is always present in the GeoIP
       data is "en". If you do not include this locale, the name property
       may end up returning None even when the record has an English name.
 
@@ -487,7 +493,7 @@
         return cast("City", self._response_for("city", geoip2.models.City, 
ip_address))
 
     def country(self, ip_address: IPAddress = "me") -> Country:
-        """Call the GeoIP2 Country endpoint with the specified IP.
+        """Call the GeoIP Country endpoint with the specified IP.
 
         :param ip_address: IPv4 or IPv6 address as a string. If no address
           is provided, the address that the web service is called from will
@@ -504,7 +510,7 @@
     def insights(self, ip_address: IPAddress = "me") -> Insights:
         """Call the Insights endpoint with the specified IP.
 
-        Insights is only supported by the GeoIP2 web service. The GeoLite2 web
+        Insights is only supported by the GeoIP web service. The GeoLite web
         service does not support it.
 
         :param ip_address: IPv4 or IPv6 address as a string. If no address
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/geoip2-5.2.0/tests/models_test.py 
new/geoip2-5.3.0/tests/models_test.py
--- old/geoip2-5.2.0/tests/models_test.py       1970-01-01 01:00:00.000000000 
+0100
+++ new/geoip2-5.3.0/tests/models_test.py       1970-01-01 01:00:00.000000000 
+0100
@@ -1,3 +1,4 @@
+import datetime
 import ipaddress
 import sys
 import unittest
@@ -24,6 +25,11 @@
                 "is_tor_exit_node": True,
                 "network_last_seen": "2025-04-14",
                 "provider_name": "FooBar VPN",
+                "residential": {
+                    "confidence": 82,
+                    "network_last_seen": "2026-05-11",
+                    "provider_name": "quickshift",
+                },
             },
             "city": {
                 "confidence": 76,
@@ -262,10 +268,32 @@
         self.assertIs(model.anonymizer.is_tor_exit_node, True)
         self.assertEqual(
             model.anonymizer.network_last_seen,
-            __import__("datetime").date(2025, 4, 14),
+            datetime.date(2025, 4, 14),
         )
         self.assertEqual(model.anonymizer.provider_name, "FooBar VPN")
 
+        # Test anonymizer.residential object
+        self.assertEqual(
+            type(model.anonymizer.residential),
+            geoip2.records.AnonymizerFeed,
+            "geoip2.records.AnonymizerFeed object",
+        )
+        self.assertEqual(model.anonymizer.residential.confidence, 82)
+        self.assertEqual(
+            model.anonymizer.residential.network_last_seen,
+            datetime.date(2026, 5, 11),
+        )
+        self.assertEqual(model.anonymizer.residential.provider_name, 
"quickshift")
+        self.assertEqual(
+            model.anonymizer.to_dict()["residential"],
+            {
+                "confidence": 82,
+                "network_last_seen": "2026-05-11",
+                "provider_name": "quickshift",
+            },
+            "residential is serialized by to_dict",
+        )
+
     def test_insights_min(self) -> None:
         model = geoip2.models.Insights(["en"], traits={"ip_address": 
"5.6.7.8"})
         self.assertEqual(
@@ -324,6 +352,59 @@
         self.assertIsNone(model.anonymizer.provider_name)
         self.assertFalse(model.anonymizer.is_anonymous)
         self.assertFalse(model.anonymizer.is_anonymous_vpn)
+        # Test that anonymizer.residential defaults correctly
+        self.assertEqual(
+            type(model.anonymizer.residential),
+            geoip2.records.AnonymizerFeed,
+            "geoip2.records.AnonymizerFeed object",
+        )
+        self.assertIsNone(model.anonymizer.residential.confidence)
+        self.assertIsNone(model.anonymizer.residential.network_last_seen)
+        self.assertIsNone(model.anonymizer.residential.provider_name)
+        self.assertEqual(
+            model.to_dict(),
+            {"traits": {"ip_address": "5.6.7.8"}},
+            "empty anonymizer is not serialized by to_dict",
+        )
+
+    def test_insights_anonymizer_residential_only(self) -> None:
+        # The residential attribute may be populated even when no other
+        # anonymizer attributes are set, so the anonymizer object may
+        # contain only the residential attribute.
+        model = geoip2.models.Insights(
+            ["en"],
+            anonymizer={
+                "residential": {
+                    "confidence": 82,
+                    "network_last_seen": "2026-05-11",
+                    "provider_name": "quickshift",
+                },
+            },
+            traits={"ip_address": "5.6.7.8"},
+        )
+        self.assertIsNone(model.anonymizer.confidence)
+        self.assertIsNone(model.anonymizer.provider_name)
+        self.assertFalse(model.anonymizer.is_anonymous)
+        self.assertEqual(model.anonymizer.residential.confidence, 82)
+        self.assertEqual(
+            model.anonymizer.residential.network_last_seen,
+            datetime.date(2026, 5, 11),
+        )
+        self.assertEqual(model.anonymizer.residential.provider_name, 
"quickshift")
+        self.assertEqual(
+            model.to_dict(),
+            {
+                "anonymizer": {
+                    "residential": {
+                        "confidence": 82,
+                        "network_last_seen": "2026-05-11",
+                        "provider_name": "quickshift",
+                    },
+                },
+                "traits": {"ip_address": "5.6.7.8"},
+            },
+            "anonymizer contains only residential in to_dict output",
+        )
 
     def test_city_full(self) -> None:
         raw = {

Reply via email to