diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3b0e30..a47412f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: push: pull_request: schedule: - - cron: '11 22 2 * *' + - cron: "11 22 2 * *" jobs: tox: @@ -13,6 +13,7 @@ jobs: fail-fast: false matrix: py: + - "3.12" - "3.11" - "3.10" - "3.9" diff --git a/opencage/__init__.py b/opencage/__init__.py index 078e440..d40fc7c 100644 --- a/opencage/__init__.py +++ b/opencage/__init__.py @@ -1,5 +1,6 @@ """ Base module for OpenCage stuff. """ +from .version import __version__ + __author__ = "OpenCage GmbH" __email__ = 'support@opencagedata.com' -__version__ = '2.3.1' diff --git a/opencage/geocoder.py b/opencage/geocoder.py index 5913f2d..ec6c4cd 100644 --- a/opencage/geocoder.py +++ b/opencage/geocoder.py @@ -5,8 +5,10 @@ import collections import os +import sys import requests import backoff +from .version import __version__ try: import aiohttp @@ -259,9 +261,9 @@ async def reverse_geocode_async(self, lat, lng, **kwargs): def _opencage_request(self, params): if self.session: - response = self.session.get(self.url, params=params) + response = self.session.get(self.url, params=params, headers=self._opencage_headers('aiohttp')) else: - response = requests.get(self.url, params=params) # pylint: disable=missing-timeout + response = requests.get(self.url, params=params, headers=self._opencage_headers('requests')) # pylint: disable=missing-timeout try: response_json = response.json() @@ -290,6 +292,21 @@ def _opencage_request(self, params): return response_json + def _opencage_headers(self, client): + if client == 'requests': + client_version = requests.__version__ + elif client == 'aiohttp': + client_version = aiohttp.__version__ + + return { + 'User-Agent': 'opencage-python/%s Python/%s %s/%s' % ( + __version__, + '.'.join(str(x) for x in sys.version_info[0:3]), + client, + client_version + ) + } + async def _opencage_async_request(self, params): try: async with self.session.get(self.url, params=params, ssl=self.sslcontext) as response: diff --git a/opencage/version.py b/opencage/version.py new file mode 100644 index 0000000..1c4ddd3 --- /dev/null +++ b/opencage/version.py @@ -0,0 +1 @@ +__version__ = '2.3.1' diff --git a/test/test_headers.py b/test/test_headers.py new file mode 100644 index 0000000..6bbff19 --- /dev/null +++ b/test/test_headers.py @@ -0,0 +1,30 @@ +# encoding: utf-8 + +from pathlib import Path + +import os +import re +import httpretty + +from httpretty import httprettified +from opencage.geocoder import OpenCageGeocode + +# reduce maximum backoff retry time from 120s to 1s +os.environ['BACKOFF_MAX_TIME'] = '1' + +geocoder = OpenCageGeocode('abcde') + +user_agent_format = re.compile(r'^opencage-python/[\d\.]+ Python/[\d\.]+ (requests|aiohttp)/[\d\.]+$') + +@httprettified +def test_sync(): + httpretty.register_uri( + httpretty.GET, + geocoder.url, + body=Path('test/fixtures/uk_postcode.json').read_text(encoding="utf-8") + ) + + geocoder.geocode("EC1M 5RF") + user_agent = httpretty.last_request().headers['User-Agent'] + + assert user_agent_format.match(user_agent) is not None diff --git a/tox.ini b/tox.ini index c8124c2..bd9ee7e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,9 @@ [tox] -envlist = py37,py38,py39,py310,py311,lint +envlist = py37,py38,py39,py310,py311,py312,lint [gh] python = + 3.12 = py312 3.11 = py311 3.10 = py310 3.9 = py39