Skip to content
This repository was archived by the owner on Apr 10, 2018. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### Release 0.3.1

* New: MaxMind Netspeed database support

Not yet uploaded to PyPi

### Release 0.3.0
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,5 @@ For more information, [check out the full API documentation](http://packages.pyt
* Organization IPv4
* ISP IPv4
* Region IPv4
* ASNum IPv4 and IPv6
* ASN IPv4 and IPv6
* Netspeed IPv4
49 changes: 43 additions & 6 deletions pygeoip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ def _setup_segments(self):
* ISP_EDITION
* ASNUM_EDITION
* ASNUM_EDITION_V6
* NETSPEED_EDITION

"""
self._databaseType = const.COUNTRY_EDITION
Expand Down Expand Up @@ -420,18 +421,31 @@ def _gethostbyname(self, hostname):
else:
return socket.gethostbyname(hostname)

def _id_by_addr(self, addr):
def id_by_name(self, hostname):
"""
Looks up the index for the country which is the key for the
code and name.
Returns the database id for specified hostname.
The id might be useful as array index. 0 is unknown.

@param hostname: Hostname
@type hostname: str
@return: network byte order 32-bit integer
@rtype: int
"""
addr = self._gethostbyname(hostname)
return self.id_by_addr(addr)

def id_by_addr(self, addr):
"""
Returns the database id for specified address.
The id might be useful as array index. 0 is unknown.

@param addr: IPv4 or IPv6 address
@type addr: str
@return: network byte order 32-bit integer
@rtype: int
"""
ipv = 6 if addr.find(':') >= 0 else 4
if ipv == 4 and self._databaseType != const.COUNTRY_EDITION:
if ipv == 4 and self._databaseType not in (const.COUNTRY_EDITION, const.NETSPEED_EDITION):
raise GeoIPError('Invalid database type; expected IPv6 address')
if ipv == 6 and self._databaseType != const.COUNTRY_EDITION_V6:
raise GeoIPError('Invalid database type; expected IPv4 address')
Expand Down Expand Up @@ -460,7 +474,7 @@ def country_code_by_addr(self, addr):
"""
VALID_EDITIONS = (const.COUNTRY_EDITION, const.COUNTRY_EDITION_V6)
if self._databaseType in VALID_EDITIONS:
country_id = self._id_by_addr(addr)
country_id = self.id_by_addr(addr)
return const.COUNTRY_CODES[country_id]
elif self._databaseType in const.REGION_CITY_EDITIONS:
return self.region_by_addr(addr).get('country_code')
Expand All @@ -480,6 +494,29 @@ def country_code_by_name(self, hostname):
addr = self._gethostbyname(hostname)
return self.country_code_by_addr(addr)

def netspeed_by_addr(self, addr):
"""
Returns NetSpeed name from address.

@param hostname: IP address
@type hostname: str
@return: netspeed name
@rtype: str
"""
return const.NETSPEED_NAMES[self.id_by_addr(addr)]

def netspeed_by_name(self, hostname):
"""
Returns NetSpeed name from hostname.

@param hostname: Hostname
@type hostname: str
@return: netspeed name
@rtype: str
"""
addr = self._gethostbyname(hostname)
return self.netspeed_by_addr(addr)

def country_name_by_addr(self, addr):
"""
Returns full country name for specified IP address.
Expand All @@ -492,7 +529,7 @@ def country_name_by_addr(self, addr):
"""
VALID_EDITIONS = (const.COUNTRY_EDITION, const.COUNTRY_EDITION_V6)
if self._databaseType in VALID_EDITIONS:
country_id = self._id_by_addr(addr)
country_id = self.id_by_addr(addr)
return const.COUNTRY_NAMES[country_id]
elif self._databaseType in const.CITY_EDITIONS:
return self.record_by_addr(addr).get('country_name')
Expand Down
8 changes: 7 additions & 1 deletion pygeoip/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@
'NA', 'NA', 'AF'
)

NETSPEED_NAMES = (
'Unknown', 'Dial-up', 'Cable', 'Corporate'
)

# storage / caching flags
STANDARD = 0
MEMORY_CACHE = 1
Expand All @@ -408,9 +412,11 @@
ISP_EDITION = 4
ASNUM_EDITION = 9
ASNUM_EDITION_V6 = 21
NETSPEED_EDITION = 10
# Not yet supported databases
PROXY_EDITION = 8
NETSPEED_EDITION = 11
NETSPEED_EDITION_REV1 = 32
NETSPEED_EDITION_REV1_V6 = 33

# Collection of databases
IPV6_EDITIONS = (COUNTRY_EDITION_V6, ASNUM_EDITION_V6, CITY_EDITION_REV1_V6)
Expand Down
1 change: 1 addition & 0 deletions tests/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
ORG_DB_PATH = path.join(DATA_DIR, 'GeoIPOrg.dat')
ASNUM_DB_PATH = path.join(DATA_DIR, 'GeoIPASNum.dat')
ISP_DB_PATH = path.join(DATA_DIR, 'GeoIPISP.dat')
NETSPEED_DB_PATH = path.join(DATA_DIR, 'GeoIPNetSpeedRev0.dat')
CORRUPT_DB_PATH = path.join(DATA_DIR, '../config.py')
24 changes: 24 additions & 0 deletions tests/test_netspeed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
import unittest

import pygeoip
from tests.config import NETSPEED_DB_PATH


class TestGeoIPOrgFunctions(unittest.TestCase):
def setUp(self):
self.ip = '17.172.224.47'
self.hostname = 'apple.com'
self.gi = pygeoip.GeoIP(NETSPEED_DB_PATH)

def testNetSpeedByAddr(self):
netspeed = self.gi.id_by_addr(self.ip)
self.assertEqual(netspeed, 3)

def testNetSpeedByAddrWrapper(self):
netspeed = self.gi.netspeed_by_addr(self.ip)
self.assertEqual(netspeed, 'Corporate')

def testNetSpeedByNameWrapper(self):
netspeed = self.gi.netspeed_by_name(self.hostname)
self.assertEqual(netspeed, 'Corporate')