Skip to content

Commit ff4972e

Browse files
committed
Make aiohttp and requests optional dependencies
Closes maxmind#104 (supersedes it) Fixes maxmind#101
1 parent e087376 commit ff4972e

File tree

5 files changed

+47
-18
lines changed

5 files changed

+47
-18
lines changed

README.rst

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ To install the ``geoip2`` module, type:
1717
.. code-block:: bash
1818
1919
$ pip install geoip2
20+
$ pip install geoip2[aiohttp] # Install aiohttp as well
21+
$ pip install geoip2[requests] # Install requests as well
2022
2123
If you are not able to use pip, you may also use easy_install from the
2224
source directory:

geoip2/webservice.py

+28-14
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,24 @@
2525
2626
"""
2727

28+
from __future__ import annotations
29+
2830
import ipaddress
2931
import json
3032
from typing import Any, Dict, cast, List, Optional, Type, Union
3133

32-
import aiohttp
33-
import aiohttp.http
34-
import requests
35-
import requests.utils
34+
try:
35+
import aiohttp
36+
import aiohttp.http
37+
except ImportError:
38+
aiohttp = None # type: ignore[assignment]
39+
40+
try:
41+
import requests
42+
import requests.utils
43+
except ImportError:
44+
requests = None # type: ignore[assignment]
45+
3646

3747
import geoip2
3848
import geoip2.models
@@ -48,14 +58,6 @@
4858
from geoip2.models import City, Country, Insights
4959
from geoip2.types import IPAddress
5060

51-
_AIOHTTP_UA = (
52-
f"GeoIP2-Python-Client/{geoip2.__version__} {aiohttp.http.SERVER_SOFTWARE}"
53-
)
54-
55-
_REQUEST_UA = (
56-
f"GeoIP2-Python-Client/{geoip2.__version__} {requests.utils.default_user_agent()}"
57-
)
58-
5961

6062
class BaseClient: # pylint: disable=missing-class-docstring, too-few-public-methods
6163
_account_id: str
@@ -326,10 +328,19 @@ async def insights(self, ip_address: IPAddress = "me") -> Insights:
326328
)
327329

328330
async def _session(self) -> aiohttp.ClientSession:
331+
if aiohttp is None:
332+
raise ImportError(
333+
"aiohttp is required for async mode; install `GeoIP2[aiohttp]`"
334+
)
335+
329336
if not hasattr(self, "_existing_session"):
337+
user_agent = (
338+
f"GeoIP2-Python-Client/{geoip2.__version__} "
339+
f"{aiohttp.http.SERVER_SOFTWARE}"
340+
)
330341
self._existing_session = aiohttp.ClientSession(
331342
auth=aiohttp.BasicAuth(self._account_id, self._license_key),
332-
headers={"Accept": "application/json", "User-Agent": _AIOHTTP_UA},
343+
headers={"Accept": "application/json", "User-Agent": user_agent},
333344
timeout=aiohttp.ClientTimeout(total=self._timeout),
334345
)
335346

@@ -436,7 +447,10 @@ def __init__( # pylint: disable=too-many-arguments
436447
self._session = requests.Session()
437448
self._session.auth = (self._account_id, self._license_key)
438449
self._session.headers["Accept"] = "application/json"
439-
self._session.headers["User-Agent"] = _REQUEST_UA
450+
self._session.headers["User-Agent"] = (
451+
f"GeoIP2-Python-Client/{geoip2.__version__}"
452+
f" {requests.utils.default_user_agent()}"
453+
)
440454
if proxy is None:
441455
self._proxies = None
442456
else:

pyproject.toml

+6-2
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@ authors = [
1010
{name = "Gregory Oschwald", email = "goschwald@maxmind.com"},
1111
]
1212
dependencies = [
13-
"aiohttp>=3.6.2,<4.0.0",
1413
"maxminddb>=2.5.1,<3.0.0",
15-
"requests>=2.24.0,<3.0.0",
1614
]
1715
requires-python = ">=3.8"
1816
readme = "README.rst"
@@ -38,6 +36,12 @@ classifiers = [
3836
test = [
3937
"pytest-httpserver>=1.0.10",
4038
]
39+
aiohttp = [
40+
"aiohttp>=3.6.2,<4.0.0",
41+
]
42+
requests = [
43+
"requests>=2.24.0,<3.0.0",
44+
]
4145

4246
[tool.setuptools.package-data]
4347
geoip2 = ["py.typed"]

setup.cfg

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

1111
[tox:tox]
12-
envlist = {py38,py39,py310,py311,py312}-test,py312-{black,lint,flake8,mypy}
12+
envlist =
13+
{py38,py39,py310,py311,py312}-test{,-all}
14+
py312-{black,lint,flake8,mypy}
1315

1416
[gh-actions]
1517
python =
@@ -19,11 +21,13 @@ python =
1921
3.11: py311
2022
3.12: py312,black,lint,flake8,mypy
2123

22-
[testenv:{py38,py39,py310,py311,py312}-test]
24+
[testenv:{py38,py39,py310,py311,py312}-test{,-all}]
2325
deps =
2426
pytest-httpserver
2527
pytest
2628
commands = pytest tests
29+
extras =
30+
all: aiohttp, requests
2731

2832
[testenv:py312-black]
2933
deps = black
@@ -45,3 +49,6 @@ deps =
4549
types-requests
4650
voluptuous-stubs
4751
commands = mypy geoip2 tests
52+
extras =
53+
aiohttp
54+
requests

tests/webservice_test.py

+2
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ def test_missing_constructor_args(self):
355355

356356
class TestClient(TestBaseClient):
357357
def setUp(self):
358+
pytest.importorskip("requests")
358359
self.client_class = Client
359360
self.client = Client(42, "abcdef123456")
360361
self.client._base_uri = self.httpserver.url_for("/geoip/v2.1")
@@ -365,6 +366,7 @@ def run_client(self, v):
365366

366367
class TestAsyncClient(TestBaseClient):
367368
def setUp(self):
369+
pytest.importorskip("aiohttp")
368370
self._loop = asyncio.new_event_loop()
369371
self.client_class = AsyncClient
370372
self.client = AsyncClient(42, "abcdef123456")

0 commit comments

Comments
 (0)