Skip to content

Commit 14621a6

Browse files
authored
Merge pull request #188 from maxmind/greg/eng-841-easy-way-to-serialize-python-minfraud-model-objects-to-json
Allow locales to be a sequence
2 parents 12a86f0 + 42fc5e9 commit 14621a6

13 files changed

+31
-30
lines changed

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
matrix:
1414
platform: [ubuntu-latest, macos-latest, windows-latest]
15-
python-version: [3.8, 3.9, "3.10", 3.11, 3.12, 3.13]
15+
python-version: [3.9, "3.10", 3.11, 3.12, 3.13]
1616

1717
name: Python ${{ matrix.python-version }} on ${{ matrix.platform }}
1818
runs-on: ${{ matrix.platform }}

HISTORY.rst

+4
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ History
77
4.9.0
88
++++++++++++++++++
99

10+
* IMPORTANT: Python 3.9 or greater is required. If you are using an older
11+
version, please use an earlier release.
1012
* ``metro_code`` on ``geoip2.record.Location`` has been deprecated. The
1113
code values are no longer being maintained.
14+
* The type hinting for the optional ``locales`` keyword argument now allows
15+
any sequence of strings rather than only list of strings.
1216

1317
4.8.1 (2024-11-18)
1418
++++++++++++++++++

README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ correction, please `contact MaxMind support
495495
Requirements
496496
------------
497497

498-
Python 3.8 or greater is required. Older versions are not supported.
498+
Python 3.9 or greater is required. Older versions are not supported.
499499

500500
The Requests HTTP library is also required. See
501501
<https://pypi.org/project/requests/> for details.

docs/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949

5050
# General information about the project.
5151
project = "geoip2"
52-
copyright = "2013-2024, MaxMind, Inc."
52+
copyright = "2013-2025, MaxMind, Inc."
5353

5454
# The version info for the project you're documenting, acts as replacement for
5555
# |version| and |release|, also used in various other places throughout the

docs/index.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ Indices and tables
3838
* :ref:`modindex`
3939
* :ref:`search`
4040

41-
:copyright: (c) 2013-2024 by MaxMind, Inc.
41+
:copyright: (c) 2013-2025 by MaxMind, Inc.
4242
:license: Apache License, Version 2.0
4343

geoip2/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
__version__ = "4.8.1"
55
__author__ = "Gregory Oschwald"
66
__license__ = "Apache License, Version 2.0"
7-
__copyright__ = "Copyright (c) 2013-2024 MaxMind, Inc."
7+
__copyright__ = "Copyright (c) 2013-2025 MaxMind, Inc."

geoip2/database.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import inspect
99
import os
10-
from typing import Any, AnyStr, cast, IO, List, Optional, Type, Union
10+
from typing import Any, AnyStr, cast, IO, Optional, Sequence, Type, Union
1111

1212
import maxminddb
1313

@@ -72,7 +72,7 @@ class Reader:
7272
def __init__(
7373
self,
7474
fileish: Union[AnyStr, int, os.PathLike, IO],
75-
locales: Optional[List[str]] = None,
75+
locales: Optional[Sequence[str]] = None,
7676
mode: int = MODE_AUTO,
7777
) -> None:
7878
"""Create GeoIP2 Reader.

geoip2/models.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# pylint: disable=too-many-instance-attributes,too-few-public-methods
1515
import ipaddress
1616
from abc import ABCMeta
17-
from typing import Any, cast, Dict, List, Optional, Union
17+
from typing import Any, cast, Dict, Optional, Sequence, Union
1818

1919
import geoip2.records
2020
from geoip2.mixins import SimpleEquality
@@ -76,7 +76,7 @@ class Country(SimpleEquality):
7676
traits: geoip2.records.Traits
7777

7878
def __init__(
79-
self, raw_response: Dict[str, Any], locales: Optional[List[str]] = None
79+
self, raw_response: Dict[str, Any], locales: Optional[Sequence[str]] = None
8080
) -> None:
8181
if locales is None:
8282
locales = ["en"]
@@ -182,7 +182,7 @@ class City(Country):
182182
subdivisions: geoip2.records.Subdivisions
183183

184184
def __init__(
185-
self, raw_response: Dict[str, Any], locales: Optional[List[str]] = None
185+
self, raw_response: Dict[str, Any], locales: Optional[Sequence[str]] = None
186186
) -> None:
187187
super().__init__(raw_response, locales)
188188
self.city = geoip2.records.City(locales, **raw_response.get("city", {}))

geoip2/records.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
# pylint:disable=R0903
1313
from abc import ABCMeta
14-
from typing import Dict, List, Optional, Type, Union
14+
from typing import Dict, Optional, Type, Sequence, Union
1515

1616
from geoip2.mixins import SimpleEquality
1717

@@ -28,11 +28,11 @@ class PlaceRecord(Record, metaclass=ABCMeta):
2828
"""All records with :py:attr:`names` subclass :py:class:`PlaceRecord`."""
2929

3030
names: Dict[str, str]
31-
_locales: List[str]
31+
_locales: Sequence[str]
3232

3333
def __init__(
3434
self,
35-
locales: Optional[List[str]] = None,
35+
locales: Optional[Sequence[str]] = None,
3636
names: Optional[Dict[str, str]] = None,
3737
) -> None:
3838
if locales is None:
@@ -93,7 +93,7 @@ class City(PlaceRecord):
9393

9494
def __init__(
9595
self,
96-
locales: Optional[List[str]] = None,
96+
locales: Optional[Sequence[str]] = None,
9797
confidence: Optional[int] = None,
9898
geoname_id: Optional[int] = None,
9999
names: Optional[Dict[str, str]] = None,
@@ -147,7 +147,7 @@ class Continent(PlaceRecord):
147147

148148
def __init__(
149149
self,
150-
locales: Optional[List[str]] = None,
150+
locales: Optional[Sequence[str]] = None,
151151
code: Optional[str] = None,
152152
geoname_id: Optional[int] = None,
153153
names: Optional[Dict[str, str]] = None,
@@ -217,7 +217,7 @@ class Country(PlaceRecord):
217217

218218
def __init__(
219219
self,
220-
locales: Optional[List[str]] = None,
220+
locales: Optional[Sequence[str]] = None,
221221
confidence: Optional[int] = None,
222222
geoname_id: Optional[int] = None,
223223
is_in_european_union: bool = False,
@@ -298,7 +298,7 @@ class RepresentedCountry(Country):
298298

299299
def __init__(
300300
self,
301-
locales: Optional[List[str]] = None,
301+
locales: Optional[Sequence[str]] = None,
302302
confidence: Optional[int] = None,
303303
geoname_id: Optional[int] = None,
304304
is_in_european_union: bool = False,
@@ -519,7 +519,7 @@ class Subdivision(PlaceRecord):
519519

520520
def __init__(
521521
self,
522-
locales: Optional[List[str]] = None,
522+
locales: Optional[Sequence[str]] = None,
523523
confidence: Optional[int] = None,
524524
geoname_id: Optional[int] = None,
525525
iso_code: Optional[str] = None,
@@ -545,14 +545,14 @@ class Subdivisions(tuple):
545545
"""
546546

547547
def __new__(
548-
cls: Type["Subdivisions"], locales: Optional[List[str]], *subdivisions
548+
cls: Type["Subdivisions"], locales: Optional[Sequence[str]], *subdivisions
549549
) -> "Subdivisions":
550550
subobjs = tuple(Subdivision(locales, **x) for x in subdivisions)
551551
obj = super().__new__(cls, subobjs) # type: ignore
552552
return obj
553553

554554
def __init__(
555-
self, locales: Optional[List[str]], *subdivisions # pylint:disable=W0613
555+
self, locales: Optional[Sequence[str]], *subdivisions # pylint:disable=W0613
556556
) -> None:
557557
self._locales = locales
558558
super().__init__()

geoip2/webservice.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
import ipaddress
2929
import json
30-
from typing import Any, Dict, cast, List, Optional, Type, Union
30+
from typing import Any, Dict, cast, Optional, Sequence, Type, Union
3131

3232
import aiohttp
3333
import aiohttp.http
@@ -61,15 +61,15 @@ class BaseClient: # pylint: disable=missing-class-docstring, too-few-public-met
6161
_account_id: str
6262
_host: str
6363
_license_key: str
64-
_locales: List[str]
64+
_locales: Sequence[str]
6565
_timeout: float
6666

6767
def __init__(
6868
self,
6969
account_id: int,
7070
license_key: str,
7171
host: str,
72-
locales: Optional[List[str]],
72+
locales: Optional[Sequence[str]],
7373
timeout: float,
7474
) -> None:
7575
"""Construct a Client."""
@@ -265,7 +265,7 @@ def __init__( # pylint: disable=too-many-arguments,too-many-positional-argument
265265
account_id: int,
266266
license_key: str,
267267
host: str = "geoip.maxmind.com",
268-
locales: Optional[List[str]] = None,
268+
locales: Optional[Sequence[str]] = None,
269269
timeout: float = 60,
270270
proxy: Optional[str] = None,
271271
) -> None:
@@ -428,7 +428,7 @@ def __init__( # pylint: disable=too-many-arguments,too-many-positional-argument
428428
account_id: int,
429429
license_key: str,
430430
host: str = "geoip.maxmind.com",
431-
locales: Optional[List[str]] = None,
431+
locales: Optional[Sequence[str]] = None,
432432
timeout: float = 60,
433433
proxy: Optional[str] = None,
434434
) -> None:

pyproject.toml

+1-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ dependencies = [
1414
"maxminddb>=2.5.1,<3.0.0",
1515
"requests>=2.24.0,<3.0.0",
1616
]
17-
requires-python = ">=3.8"
17+
requires-python = ">=3.9"
1818
readme = "README.rst"
1919
license = {text = "Apache License, Version 2.0"}
2020
classifiers = [
@@ -25,7 +25,6 @@ classifiers = [
2525
"License :: OSI Approved :: Apache Software License",
2626
"Programming Language :: Python",
2727
"Programming Language :: Python :: 3",
28-
"Programming Language :: Python :: 3.8",
2928
"Programming Language :: Python :: 3.9",
3029
"Programming Language :: Python :: 3.10",
3130
"Programming Language :: Python :: 3.11",

setup.cfg

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ geoip2 = py.typed
99
disable = duplicate-code
1010

1111
[tox:tox]
12-
envlist = {py38,py39,py310,py311,py312,py313}-test,py313-{black,lint,flake8,mypy}
12+
envlist = {py39,py310,py311,py312,py313}-test,py313-{black,lint,flake8,mypy}
1313

1414
[gh-actions]
1515
python =
16-
3.8: py38
1716
3.9: py39
1817
3.10: py310
1918
3.11: py311

tests/webservice_test.py

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import asyncio
55
import copy
66
import ipaddress
7-
import json
87
import sys
98
from typing import cast, Dict
109
import unittest

0 commit comments

Comments
 (0)