Commit ·
8252fc5
1
Parent(s): 224dc14
feat - sync geoip
Browse files
src/leaderboard_analytics/geoip_database.py
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gzip
|
| 2 |
+
import shutil
|
| 3 |
+
import tempfile
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from urllib.request import urlopen
|
| 6 |
+
|
| 7 |
+
DEFAULT_GEOIP_DATABASE_URL = (
|
| 8 |
+
"https://cdn.jsdelivr.net/npm/geolite2-country/GeoLite2-Country.mmdb.gz"
|
| 9 |
+
)
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
def ensure_geoip_database(
|
| 13 |
+
database_path: str | Path,
|
| 14 |
+
source_url: str = DEFAULT_GEOIP_DATABASE_URL,
|
| 15 |
+
*,
|
| 16 |
+
auto_download: bool = True,
|
| 17 |
+
timeout: float = 30.0,
|
| 18 |
+
) -> Path:
|
| 19 |
+
target_path = Path(database_path)
|
| 20 |
+
if target_path.exists() or not auto_download:
|
| 21 |
+
return target_path
|
| 22 |
+
|
| 23 |
+
target_path.parent.mkdir(parents=True, exist_ok=True)
|
| 24 |
+
with tempfile.NamedTemporaryFile(
|
| 25 |
+
prefix=f"{target_path.name}.",
|
| 26 |
+
suffix=".tmp",
|
| 27 |
+
dir=target_path.parent,
|
| 28 |
+
delete=False,
|
| 29 |
+
) as temp_file:
|
| 30 |
+
temp_path = Path(temp_file.name)
|
| 31 |
+
with urlopen(source_url, timeout=timeout) as response:
|
| 32 |
+
with gzip.GzipFile(fileobj=response) as gzip_file:
|
| 33 |
+
shutil.copyfileobj(gzip_file, temp_file)
|
| 34 |
+
|
| 35 |
+
temp_path.replace(target_path)
|
| 36 |
+
return target_path
|
tests/test_geoip_database.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gzip
|
| 2 |
+
|
| 3 |
+
from leaderboard_analytics.geoip_database import ensure_geoip_database
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
def test_ensure_geoip_database_downloads_and_decompresses_gzip(tmp_path) -> None:
|
| 7 |
+
source = tmp_path / "GeoLite2-Country.mmdb.gz"
|
| 8 |
+
target = tmp_path / "GeoLite2-Country.mmdb"
|
| 9 |
+
expected_bytes = b"fake-mmdb-bytes"
|
| 10 |
+
|
| 11 |
+
with gzip.open(source, "wb") as gzip_file:
|
| 12 |
+
gzip_file.write(expected_bytes)
|
| 13 |
+
|
| 14 |
+
result = ensure_geoip_database(target, source.as_uri())
|
| 15 |
+
|
| 16 |
+
assert result == target
|
| 17 |
+
assert target.read_bytes() == expected_bytes
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def test_ensure_geoip_database_keeps_existing_file(tmp_path) -> None:
|
| 21 |
+
source = tmp_path / "missing.mmdb.gz"
|
| 22 |
+
target = tmp_path / "GeoLite2-Country.mmdb"
|
| 23 |
+
expected_bytes = b"existing-mmdb-bytes"
|
| 24 |
+
target.write_bytes(expected_bytes)
|
| 25 |
+
|
| 26 |
+
result = ensure_geoip_database(target, source.as_uri())
|
| 27 |
+
|
| 28 |
+
assert result == target
|
| 29 |
+
assert target.read_bytes() == expected_bytes
|