Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
dan-mm committed Dec 5, 2023
2 parents 9d41e7c + 0ee2b8c commit 7188219
Show file tree
Hide file tree
Showing 10 changed files with 82 additions and 56 deletions.
54 changes: 49 additions & 5 deletions django/contrib/gis/geoip2/base.py → django/contrib/gis/geoip2.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,35 @@
"""
This module houses the GeoIP2 object, a wrapper for the MaxMind GeoIP2(R)
Python API (https://geoip2.readthedocs.io/). This is an alternative to the
Python GeoIP2 interface provided by MaxMind.
GeoIP(R) is a registered trademark of MaxMind, Inc.
For IP-based geolocation, this module requires the GeoLite2 Country and City
datasets, in binary format (CSV will not work!). The datasets may be
downloaded from MaxMind at https://dev.maxmind.com/geoip/geoip2/geolite2/.
Grab GeoLite2-Country.mmdb.gz and GeoLite2-City.mmdb.gz, and unzip them in the
directory corresponding to settings.GEOIP_PATH.
"""

import socket
import warnings

import geoip2.database

from django.conf import settings
from django.core.exceptions import ValidationError
from django.core.validators import validate_ipv46_address
from django.utils._os import to_path
from django.utils.deprecation import RemovedInDjango60Warning

from .resources import City, Country
__all__ = ["HAS_GEOIP2"]

try:
import geoip2.database
except ImportError:
HAS_GEOIP2 = False
else:
HAS_GEOIP2 = True
__all__ += ["GeoIP2", "GeoIP2Exception"]

# Creating the settings dictionary with any settings, if needed.
GEOIP_SETTINGS = {
Expand Down Expand Up @@ -182,7 +202,22 @@ def city(self, query):
may be undefined (None).
"""
enc_query = self._check_query(query, city=True)
return City(self._city.city(enc_query))
response = self._city.city(enc_query)
region = response.subdivisions[0] if response.subdivisions else None
return {
"city": response.city.name,
"continent_code": response.continent.code,
"continent_name": response.continent.name,
"country_code": response.country.iso_code,
"country_name": response.country.name,
"dma_code": response.location.metro_code,
"is_in_european_union": response.country.is_in_european_union,
"latitude": response.location.latitude,
"longitude": response.location.longitude,
"postal_code": response.postal.code,
"region": region.iso_code if region else None,
"time_zone": response.location.time_zone,
}

def country_code(self, query):
"Return the country code for the given IP Address or FQDN."
Expand All @@ -200,7 +235,11 @@ def country(self, query):
"""
# Returning the country code and name
enc_query = self._check_query(query, city_or_country=True)
return Country(self._country_or_city(enc_query))
response = self._country_or_city(enc_query)
return {
"country_code": response.country.iso_code,
"country_name": response.country.name,
}

def coords(self, query, ordering=("longitude", "latitude")):
warnings.warn(
Expand Down Expand Up @@ -230,4 +269,9 @@ def geos(self, query):

@classmethod
def open(cls, full_path, cache):
warnings.warn(
"GeoIP2.open() is deprecated. Use GeoIP2() instead.",
RemovedInDjango60Warning,
stacklevel=2,
)
return GeoIP2(full_path, cache)
24 changes: 0 additions & 24 deletions django/contrib/gis/geoip2/__init__.py

This file was deleted.

22 changes: 0 additions & 22 deletions django/contrib/gis/geoip2/resources.py

This file was deleted.

2 changes: 2 additions & 0 deletions docs/internals/deprecation.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ details on these changes.

* The ``django.contrib.gis.geoip2.GeoIP2.coords()`` method will be removed.

* The ``django.contrib.gis.geoip2.GeoIP2.open()`` method will be removed.

.. _deprecation-removed-in-5.1:

5.1
Expand Down
4 changes: 4 additions & 0 deletions docs/ref/contrib/gis/geoip2.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ Instantiating
This classmethod instantiates the GeoIP object from the given database path
and given cache setting.

.. deprecated:: 5.1

Use the :class:`GeoIP2()` constructor instead.

Querying
--------

Expand Down
12 changes: 12 additions & 0 deletions docs/releases/4.2.9.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
==========================
Django 4.2.9 release notes
==========================

*Expected January 2, 2024*

Django 4.2.9 fixes a bug in 4.2.8.

Bugfixes
========

* ...
2 changes: 1 addition & 1 deletion docs/releases/5.0.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Django 5.0.1 release notes
==========================

*Expected January 4, 2024*
*Expected January 2, 2024*

Django 5.0.1 fixes several bugs in 5.0.

Expand Down
3 changes: 3 additions & 0 deletions docs/releases/5.1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,9 @@ Miscellaneous
* The ``django.contrib.gis.geoip2.GeoIP2.coords()`` method is deprecated. Use
``django.contrib.gis.geoip2.GeoIP2.lon_lat()`` instead.

* The ``django.contrib.gis.geoip2.GeoIP2.open()`` method is deprecated. Use the
:class:`~django.contrib.gis.geoip2.GeoIP2` constructor instead.

Features removed in 5.1
=======================

Expand Down
1 change: 1 addition & 0 deletions docs/releases/index.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree::
:maxdepth: 1

4.2.9
4.2.8
4.2.7
4.2.6
Expand Down
14 changes: 10 additions & 4 deletions tests/gis_tests/test_geoip2.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,13 @@ def test01_init(self):
g1 = GeoIP2() # Everything inferred from GeoIP path
path = settings.GEOIP_PATH
g2 = GeoIP2(path, 0) # Passing in data path explicitly.
g3 = GeoIP2.open(path, 0) # MaxMind Python API syntax.
# path accepts str and pathlib.Path.
if isinstance(path, str):
g4 = GeoIP2(pathlib.Path(path))
g3 = GeoIP2(pathlib.Path(path))
else:
g4 = GeoIP2(str(path))
g3 = GeoIP2(str(path))

for g in (g1, g2, g3, g4):
for g in (g1, g2, g3):
self.assertTrue(g._country)
self.assertTrue(g._city)

Expand Down Expand Up @@ -198,3 +197,10 @@ def test_coords_deprecation_warning(self):
e1, e2 = g.coords(self.fqdn)
self.assertIsInstance(e1, float)
self.assertIsInstance(e2, float)

def test_open_deprecation_warning(self):
msg = "GeoIP2.open() is deprecated. Use GeoIP2() instead."
with self.assertWarnsMessage(RemovedInDjango60Warning, msg):
g = GeoIP2.open(settings.GEOIP_PATH, 0)
self.assertTrue(g._country)
self.assertTrue(g._city)

0 comments on commit 7188219

Please sign in to comment.