Skip to content

Commit 1deb3b4

Browse files
committed
Make aiohttp and requests optional dependencies
Closes #104 (supersedes it) Fixes #101
1 parent 65b6866 commit 1deb3b4

4 files changed

Lines changed: 41 additions & 14 deletions

File tree

README.rst

Lines changed: 2 additions & 0 deletions
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 install from PyPI, you may also use ``pip`` from the
2224
source directory:

pyproject.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ env_list = [
103103
]
104104
skip_missing_interpreters = false
105105

106+
[project.optional-dependencies]
107+
aiohttp = [
108+
"aiohttp>=3.6.2,<4.0.0",
109+
]
110+
requests = [
111+
"requests>=2.24.0,<3.0.0",
112+
]
113+
106114
[tool.tox.env_run_base]
107115
runner = "uv-venv-lock-runner"
108116
dependency_groups = [
@@ -115,6 +123,10 @@ commands = [
115123
[tool.tox.env.lint]
116124
description = "Code linting"
117125
python = "3.14"
126+
extras = [
127+
"aiohttp",
128+
"requests",
129+
]
118130
dependency_groups = [
119131
"dev",
120132
"lint",

src/geoip2/webservice.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,18 @@
2727
import json
2828
from typing import TYPE_CHECKING, cast
2929

30-
import aiohttp
31-
import aiohttp.http
32-
import requests
33-
import requests.utils
30+
try:
31+
import aiohttp
32+
import aiohttp.http
33+
except ImportError:
34+
aiohttp = None # type: ignore[assignment]
35+
36+
try:
37+
import requests
38+
import requests.utils
39+
except ImportError:
40+
requests = None # type: ignore[assignment]
41+
3442

3543
import geoip2
3644
import geoip2.models
@@ -52,14 +60,6 @@
5260
from geoip2.models import City, Country, Insights
5361
from geoip2.types import IPAddress
5462

55-
_AIOHTTP_UA = (
56-
f"GeoIP2-Python-Client/{geoip2.__version__} {aiohttp.http.SERVER_SOFTWARE}"
57-
)
58-
59-
_REQUEST_UA = (
60-
f"GeoIP2-Python-Client/{geoip2.__version__} {requests.utils.default_user_agent()}"
61-
)
62-
6363

6464
class BaseClient:
6565
"""Base class for AsyncClient and Client."""
@@ -352,15 +352,23 @@ async def insights(self, ip_address: IPAddress = "me") -> Insights:
352352
)
353353

354354
async def _session(self) -> aiohttp.ClientSession:
355+
if aiohttp is None:
356+
msg = "aiohttp is required for async mode; install `GeoIP2[aiohttp]`"
357+
raise ImportError(msg)
358+
355359
if not hasattr(self, "_existing_session"):
360+
user_agent = (
361+
f"GeoIP2-Python-Client/{geoip2.__version__} "
362+
f"{aiohttp.http.SERVER_SOFTWARE}"
363+
)
356364
self._existing_session = aiohttp.ClientSession(
357365
headers={
358366
"Accept": "application/json",
359367
"Authorization": aiohttp.encode_basic_auth(
360368
self._account_id,
361369
self._license_key,
362370
),
363-
"User-Agent": _AIOHTTP_UA,
371+
"User-Agent": user_agent,
364372
},
365373
timeout=aiohttp.ClientTimeout(total=self._timeout),
366374
)
@@ -474,7 +482,10 @@ def __init__( # noqa: PLR0913
474482
self._session = requests.Session()
475483
self._session.auth = (self._account_id, self._license_key)
476484
self._session.headers["Accept"] = "application/json"
477-
self._session.headers["User-Agent"] = _REQUEST_UA
485+
self._session.headers["User-Agent"] = (
486+
f"GeoIP2-Python-Client/{geoip2.__version__}"
487+
f" {requests.utils.default_user_agent()}"
488+
)
478489
if proxy is None:
479490
self._proxies = None
480491
else:

tests/webservice_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@ class TestClient(TestBaseClient):
403403
client: Client
404404

405405
def setUp(self) -> None:
406+
pytest.importorskip("requests")
406407
self.client_class = Client
407408
self.client = Client(42, "abcdef123456")
408409
self.client._base_uri = self.httpserver.url_for("/geoip/v2.1") # noqa: SLF001
@@ -416,6 +417,7 @@ class TestAsyncClient(TestBaseClient):
416417
client: AsyncClient
417418

418419
def setUp(self) -> None:
420+
pytest.importorskip("aiohttp")
419421
self._loop = asyncio.new_event_loop()
420422
self.client_class = AsyncClient
421423
self.client = AsyncClient(42, "abcdef123456")

0 commit comments

Comments
 (0)