Skip to content

Commit

Permalink
Remove support for GeoIP (#54)
Browse files Browse the repository at this point in the history
* Remove support for GeoIP

This is a breaking, non-compatible change.

* Fix CI

* Update dependencies
  • Loading branch information
Schnouki authored Nov 13, 2024
1 parent 35e0131 commit c4becbb
Show file tree
Hide file tree
Showing 9 changed files with 125 additions and 794 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install poetry
poetry install -E geoip
wget -q https://github.com/maxmind/MaxMind-DB/raw/main/test-data/GeoIP2-City-Test.mmdb
poetry install
- name: Test with tox
run: poetry run tox
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Removed
- Drop support for GeoIP and `guess_timezone_by_ip()`.

## [2.2.0] - 2023-03-06
### Added
Expand Down
7 changes: 1 addition & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,7 @@ upload: tag build
poetry publish


GeoIP2-City-Test.mmdb:
rm -f GeoIP2-City-Test.mmdb
wget https://github.com/maxmind/MaxMind-DB/raw/main/test-data/GeoIP2-City-Test.mmdb


test: GeoIP2-City-Test.mmdb
test:
poetry run pytest


Expand Down
767 changes: 118 additions & 649 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,14 @@ readme = "README.md"

[tool.poetry.dependencies]
python = "^3.9"
geoip2 = {version = "^4.5.0", optional = true}

[tool.poetry.dev-dependencies]
pytest = "^7.1.2"
tox = "^3.25.0"
tox-gh-actions = "^2.9.1"
mypy = "^0.960"
types-geoip2 = "^3.0.0"
ruff = "^0.2.1"

[tool.poetry.extras]
geoip = ["geoip2"]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Expand Down
42 changes: 0 additions & 42 deletions timezones/test_timezones.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

from . import _defs, tz_rendering, tz_utils, zones

GEOIP_DATA_LOCATION = os.path.abspath(
os.path.join(__file__, "..", "..", "GeoIP2-City-Test.mmdb")
)


def assert_is_lower(offset_a, offset_b):
# Force a real sort to happen: to avoid optimizations from kicking in, make
Expand Down Expand Up @@ -44,44 +40,6 @@ def test_get_timezone():
assert tz_utils.is_valid_timezone("Europe/Moscow1") is False


@pytest.fixture
def geoip_db():
try:
import geoip2 # noqa: F401
except ImportError:
pytest.skip("geoip2 not installed")
if not os.path.exists(GEOIP_DATA_LOCATION):
pytest.skip("No GeoIP2 database")

tz_utils.GEOIP_DATA_LOCATION = GEOIP_DATA_LOCATION
yield
tz_utils.GEOIP_DATA_LOCATION = None


def test_guess_timezone_geoip(geoip_db):
assert tz_utils.guess_timezone_by_ip("000.000.000.000", only_name=True) is None
assert tz_utils.guess_timezone_by_ip("127.0.0.1", only_name=True) is None

# This uses the MaxMind test DBs; source:
# https://github.com/maxmind/MaxMind-DB/blob/main/source-data/GeoIP2-City-Test.json
assert (
tz_utils.guess_timezone_by_ip("149.101.100.0", only_name=True)
== "America/Chicago"
)
assert tz_utils.guess_timezone_by_ip("2001:230::1", only_name=True) == "Asia/Seoul"

# Addresses not in the test DB
assert tz_utils.guess_timezone_by_ip("1.2.3.4", only_name=True) is None
assert (
tz_utils.guess_timezone_by_ip("2001:2002:2003:2004::0", only_name=True) is None
)


def test_guess_timezone_no_geoip():
assert tz_utils.guess_timezone_by_ip("149.101.100.0", only_name=True) is None
assert tz_utils.guess_timezone_by_ip("2001:230::1", only_name=True) is None


def test_get_timezones():
assert len(list(zones.get_timezones(only_us=True))) == 8

Expand Down
21 changes: 2 additions & 19 deletions timezones/tz_rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,20 @@
HTML helper to render timezones. The output will be a SELECT element.
Will auto guess the user's timezone based on IP. Will auto-select the current
selected timezone.
Will auto-select the current selected timezone.
Example usage (returns HTML based on current properties)::
html_timezones = tz_rendering.html_render_timezones(
'timezone',
current_selected,
get_current_ip(),
first_entry=_('Select your timezone'),
)
:copyright: 2012 by Amir Salihefendic ( http://amix.dk/ )
:license: MIT
"""

from __future__ import annotations

import json
Expand All @@ -30,7 +29,6 @@
def html_render_timezones(
select_name: str,
current_selected: str | None = None,
user_ip: str | None = None,
first_entry: str = "Select your timezone",
force_current_selected: bool = False,
select_id: Any = None,
Expand All @@ -45,9 +43,6 @@ def html_render_timezones(
Is the name of the current timezone, e.g. "Europe/Copenhagen"
is used to auto select the current timezone option in the select element
`user_ip` (optional):
User's ip, used to auto guess the timezone
`first_entry` (optional):
What should the first option be? If `None` it won't be shown at all
Expand Down Expand Up @@ -89,18 +84,6 @@ def render_option_disabled():
result.append(render_option(timezone[1], timezone[2], True))
result.append(render_option_disabled())

# Guess user's timezone by user_ip
if user_ip:
gussed_timezone = tz_utils.guess_timezone_by_ip(user_ip)

if not gussed_timezone and default_timezone:
gussed_timezone = format_tz(default_timezone)

if gussed_timezone:
is_set = current_selected == gussed_timezone[1] or current_selected is None
result.append(render_option(gussed_timezone[1], gussed_timezone[2], is_set))
result.append(render_option_disabled())

for tz in zones.get_timezones(only_us=True):
result.append(render_option(tz[1], tz[2], current_selected == tz[1]))

Expand Down
69 changes: 1 addition & 68 deletions timezones/tz_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@
print tz_utils.get_timezone('GMT +10:00')
Example usage (guess timezone by IP, required geoip2!)::
tz_utils.GEOIP_DATA_LOCATION = '/usr/local/geo_ip/GeoIP2-City.mmdb'
assert tz_utils.guess_timezone_by_ip('201.246.115.62') == 'Chile/Continental'
Example usage (format timezone by name)::
print tz_utils.format_tz_by_name('Europe/Copenhagen')
Expand All @@ -33,6 +27,7 @@
:copyright: 2012 by Amir Salihefendic ( http://amix.dk/ )
:license: MIT
"""

from __future__ import annotations

from datetime import datetime, timedelta, tzinfo
Expand All @@ -41,58 +36,13 @@

from . import _defs

try:
import geoip2.database as geoip2_db

HAS_GEOIP2 = True
except ImportError:
HAS_GEOIP2 = False

# --- Exports ----------------------------------------------
__all__ = [
"get_timezone",
"is_valid_timezone",
"GEOIP_DATA_LOCATION",
"guess_timezone_by_ip",
"format_tz_by_name",
]

# --- Specifies the location of GeoIP GeoLiteCity.dat database ---
GEOIP_DATA_LOCATION = None


# --- Functions ----------------------------------------------
def guess_timezone_by_ip(ip: str, only_name: bool = False):
"""Given an `ip` with guess timezone using geoip2.
Returns a tuple of (tz_offets, tz_name, tz_formatted).
`None` is returned if it can't guess a timezone.
For this to work you need to set tz_utils.GEOIP_DATA_LOCATION
You can get this database from http://www.maxmind.com/app/geolitecity
Example usage::
from timezones import tz_utils
tz_utils.GEOIP_DATA_LOCATION = "/usr/local/geo_ip/GeoLiteCity.dat"
assert tz_utils.guess_timezone_by_ip("201.246.115.62") == "Chile/Continental"
"""
geo_lib = _get_geoip_lib()
if geo_lib:
try:
record = geo_lib.city(ip)
if record:
location = record.location
if location and location.time_zone:
if only_name:
return location.time_zone
else:
return format_tz_by_name(location.time_zone)
except Exception:
record = None
return None


def get_timezone(tzname: str) -> tzinfo | None:
"""
Expand Down Expand Up @@ -154,23 +104,6 @@ def get_last_datetime_without_dst(tz: tzinfo):


# --- Private ----------------------------------------------
GEO_IP = None


def _get_geoip_lib():
global GEO_IP

if not HAS_GEOIP2 or not GEOIP_DATA_LOCATION:
return None

try:
GEO_IP = geoip2_db.Reader(GEOIP_DATA_LOCATION)
except Exception:
return None

return GEO_IP


_zero = timedelta(0)


Expand Down
3 changes: 0 additions & 3 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,11 @@ python =
[testenv]
deps =
pytest
extras =
geoip
commands =
pytest {posargs}

[testenv:mypy]
deps =
mypy
types-geoip2
commands =
mypy timezones {posargs:--ignore-missing-imports}

0 comments on commit c4becbb

Please sign in to comment.