File: geoipresolver.py

package info (click to toggle)
oca-core 11.0.20180730-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 509,684 kB
  • sloc: xml: 258,806; python: 164,081; sql: 217; sh: 92; makefile: 16
file content (64 lines) | stat: -rw-r--r-- 2,024 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os.path

try:
    import GeoIP    # Legacy
except ImportError:
    GeoIP = None

try:
    import geoip2
    import geoip2.database
except ImportError:
    geoip2 = None

class GeoIPResolver(object):
    def __init__(self, fname):
        self.fname = fname
        try:
            self._db = geoip2.database.Reader(fname)
            self.version = 2
        except Exception:
            try:
                self._db = GeoIP.open(fname, GeoIP.GEOIP_STANDARD)
                self.version = 1
                assert self._db.database_info is not None
            except Exception:
                raise ValueError('Invalid GeoIP database: %r' % fname)

    def __del__(self):
        if self.version == 2:
            self._db.close()

    @classmethod
    def open(cls, fname):
        if not GeoIP and not geoip2:
            return None
        if not os.path.exists(fname):
            return None
        return GeoIPResolver(fname)

    def resolve(self, ip):
        if self.version == 1:
            return self._db.record_by_addr(ip) or {}
        elif self.version == 2:
            try:
                r = self._db.city(ip)
            except (ValueError, geoip2.errors.AddressNotFoundError):
                return {}
            # Compatibility with Legacy database.
            # Some ips cannot be located to a specific country. Legacy DB used to locate them in
            # continent instead of country. Do the same to not change behavior of existing code.
            country, attr = (r.country, 'iso_code') if r.country.geoname_id else (r.continent, 'code')
            return {
                'city': r.city.name,
                'country_code': getattr(country, attr),
                'country_name': country.name,
                'region': r.subdivisions[0].iso_code if r.subdivisions else None,
                'time_zone': r.location.time_zone,
            }

    # compat
    def record_by_addr(self, addr):
        return self.resolve(addr)