Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Refactored the lib to retrieve cities and zipcodes separately, added …

…zipcode import and data
  • Loading branch information...
commit 26897a014b72e741db5fa743b5d1f1dc0d1c34ad 1 parent 6e133ef
dvir volk authored
3  .gitignore
View
@@ -0,0 +1,3 @@
+data/*.csv
+*.pyc
+*.pyo
8 README.md
View
@@ -4,7 +4,7 @@ Geodis - a Redis based geo resolving library
Geodis is a simple python module that allows you to import locations
(currently only cities) and geographical IP ranges into Redis, a fast in-memory NoSQL database.
-It is able to resolve either lat,lon coordinates into city, region and country (based on the closest match),
+It is able to resolve either lat,lon coordinates into zipcode (in the us), city, region and country (based on the closest match),
and/or resolve IP addresses into the same location objects.
Geodis is fast - a single thread, signle process python program can resolve about 1500 locations per second on
@@ -17,12 +17,12 @@ USAGE
>>> import geodis
>>> conn = redis.Redis()
- #getting a location by lat,lon
- >>> print geodis.Location.getByLatLon(31.78,35.21, conn)
+ #getting a city by lat,lon
+ >>> print geodis.City.getByLatLon(31.78,35.21, conn)
Location: {'name': 'West Jerusalem', 'country': 'Israel', 'lon': '35.21961', 'zipcode': '', 'state': 'Jerusalem District', 'lat': '31.78199'}
#getting a location by ip
- >>> print geodis.IPRange.getLocation('62.219.0.221', conn)
+ >>> print geodis.IPRange.getCity('62.219.0.221', conn)
Location: {'name': 'West Jerusalem', 'country': 'Israel', 'lon': '35.21961', 'zipcode': '', 'state': 'Jerusalem District', 'lat': '31.78199'}
2  src/__init__.py
View
@@ -25,4 +25,4 @@
#or implied, of Do@.
from iprange import IPRange
-from location import Location
+from city import City
51 src/city.py
View
@@ -0,0 +1,51 @@
+#Copyright 2011 Do@. All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without modification, are
+#permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+#THIS SOFTWARE IS PROVIDED BY Do@ ``AS IS'' AND ANY EXPRESS OR IMPLIED
+#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#The views and conclusions contained in the software and documentation are those of the
+#authors and should not be interpreted as representing official policies, either expressed
+#or implied, of Do@.
+
+from countries import countries
+import geohash
+
+from location import Location
+
+class City(Location):
+ """
+ Wrapper for a city location object
+ """
+
+ #what we want to save for a city
+ __spec__ = Location.__spec__ + ['country', 'state']
+
+ #key is identical to what we want to save
+ __keyspec__ = None
+
+ def __init__(self, **kwargs):
+
+ super(City, self).__init__(**kwargs)
+
+ self.country = countries.get( kwargs.get('country', None), kwargs.get('country', '')).strip()
+ self.state = kwargs.get('state', '').strip()
+
+
+
28 src/geodis.py
View
@@ -33,19 +33,21 @@
from provider.geonames import GeonamesImporter
from provider.ip2location import IP2LocationImporter
+from provider.zipcodes import ZIPImporter
from iprange import IPRange
-from location import Location
+from city import City
__author__="dvirsky"
__date__ ="$Mar 25, 2011 4:44:22 PM$"
redis_host = 'localhost'
redis_port = 6379
+redis_db = 0
def importGeonames(fileName):
global redis_host, redis_port
- importer = GeonamesImporter(fileName, redis_host, redis_port)
+ importer = GeonamesImporter(fileName, redis_host, redis_port, redis_db)
if not importer.runImport():
print "Could not import geonames database..."
sys.exit(1)
@@ -56,7 +58,16 @@ def importGeonames(fileName):
def importIP2Location(fileName):
global redis_host, redis_port
- importer = IP2LocationImporter(fileName, redis_host, redis_port)
+ importer = IP2LocationImporter(fileName, redis_host, redis_port, redis_db)
+ if not importer.runImport():
+ print "Could not import geonames database..."
+ sys.exit(1)
+
+
+def importZIPCode(fileName):
+
+ global redis_host, redis_port
+ importer = ZIPImporter(fileName, redis_host, redis_port, redis_db)
if not importer.runImport():
print "Could not import geonames database..."
sys.exit(1)
@@ -65,13 +76,13 @@ def importIP2Location(fileName):
def resolveIP(ip):
r = redis.Redis(host = redis_host, port = redis_port)
- loc = IPRange.getLocation(ip, r)
+ loc = IPRange.getCity(ip, r)
print loc
def resolveCoords(lat, lon):
r = redis.Redis(host = redis_host, port = redis_port)
- loc = Location.getByLatLon(lat, lon, r)
+ loc = City.getByLatLon(lat, lon, r)
print loc
@@ -91,6 +102,9 @@ def resolveCoords(lat, lon):
parser.add_option("-i", "--import_ip2coutnry", dest="import_ip2location",
action='store_true', default=False,
help='Import ip ranges from ip2country.com dumps')
+ parser.add_option("-z", "--import_zipcodes", dest="import_zipcodes",
+ action='store_true', default=False,
+ help='Import zipcodes')
parser.add_option("-f", "--file", dest="import_file",
help="Location of the file we want to import", metavar="FILE")
@@ -98,6 +112,7 @@ def resolveCoords(lat, lon):
parser.add_option("-p", "--resolve_ip", dest="resolve_ip", default = None,
help="resolve an ip address to location", metavar="IP_ADDR")
+
parser.add_option("-l", "--resolve_latlon", dest="resolve_latlon", default = None,
help="resolve an lat,lon pair into location", metavar="LAT,LON")
@@ -108,6 +123,9 @@ def resolveCoords(lat, lon):
elif options.import_ip2location:
importIP2Location(options.import_file)
+
+ elif options.import_zipcodes:
+ importZIPCode(options.import_file)
elif options.resolve_ip:
resolveIP(options.resolve_ip)
71 src/iprange.py
View
@@ -23,23 +23,29 @@
#The views and conclusions contained in the software and documentation are those of the
#authors and should not be interpreted as representing official policies, either expressed
#or implied, of Do@.
-import socket, struct
-from location import Location
+
+
+import socket, struct, re
+from city import City
+from zipcode import ZIPCode
import geohash
import struct
class IPRange(object):
_indexKey = 'iprange:locations'
- def __init__(self, rangeMin, rangeMax, lat, lon):
+ def __init__(self, rangeMin, rangeMax, lat, lon, zipcode = ''):
self.rangeMin = rangeMin
self.rangeMax = rangeMax
+ self.lat = lat
+ self.lon = lon
+ self.zipcode = zipcode
#encode a numeric geohash key
- self.geoKey = geohash.encode_uint64(lat, lon)
+ self.geoKey = geohash.encode(lat, lon)
- self.key = '%s:%s' % (self.rangeMin, self.rangeMax)
+ self.key = '%s:%s:%s' % (self.rangeMin, self.rangeMax, self.zipcode)
def save(self, redisConn):
"""
@@ -55,16 +61,13 @@ def __str__(self):
textual representation
"""
return "IPRange: %s" % self.__dict__
-
+
@staticmethod
- def getLocation(ip, redisConn):
+ def get(ip, redisConn):
"""
- Get location object by resolving an IP address
- @param ip IPv4 address string (e.g. 127.0.0.1)
- @oaram redisConn redis connection to the database
- @return a Location object if we can resolve this ip, else None
+ Get a range and all its data by ip
"""
-
+
ipnum = IPRange.ip2long(ip)
#get the location record from redis
@@ -76,8 +79,12 @@ def getLocation(ip, redisConn):
#extract location id
try:
geoKey,rng = record[0][0].split('@')
- geoKey = int(geoKey)
- rngMin, rngMax = (int(x) for x in rng.split(':'))
+
+ lat,lon = geohash.decode(geoKey)
+
+ rngMin, rngMax, zipcode = rng.split(':')
+ rngMin = int(rngMin)
+ rngMax = int(rngMax)
except IndexError:
return None
@@ -85,9 +92,43 @@ def getLocation(ip, redisConn):
if not rngMin <= ipnum <= rngMax:
return None
+ return IPRange(rngMin, rngMax, lat, lon, zipcode)
+
+ @staticmethod
+ def getZIP(ip, redisConn):
+ """
+ Get a zipcode location object based on an IP
+ will return None if you are outside the US
+ """
+
+ range = IPRange.get(ip, redisConn)
+ if not range or not re.match('^[0-9]{5}$', range.zipcode):
+ return None
+
+ return ZIPCode.load('ZIPCode:%s' % range.zipcode, redisConn)
+
+
+
+
+
+
+ @staticmethod
+ def getCity(ip, redisConn):
+ """
+ Get location object by resolving an IP address
+ @param ip IPv4 address string (e.g. 127.0.0.1)
+ @oaram redisConn redis connection to the database
+ @return a Location object if we can resolve this ip, else None
+ """
+
+ range = IPRange.get(ip, redisConn)
+ if not range:
+ return None
+
+
#load a location by the
- return Location.getByGeohash(geoKey, redisConn)
+ return City.getByGeohash(geohash.encode_uint64(range.lat, range.lon), redisConn)
@staticmethod
94 src/location.py
View
@@ -27,38 +27,56 @@
from countries import countries
import geohash
import math
-import struct
-class Location(object):
-
- CITY = 'city'
- VENUE = 'venue'
+class Location(object):
+ """
+ This is the base class for all location subclasses
+ """
+
+ __spec__ = ['lat', 'lon', 'name']
+ __keyspec__ = None
+
def __init__(self, **kwargs):
-
+
self.lat = kwargs.get('lat', None)
self.lon = kwargs.get('lon', None)
self.name = kwargs.get('name', '').strip()
- self.country = countries.get( kwargs.get('country', None), kwargs.get('country', '')).strip()
- self.state = kwargs.get('state', '').strip()
- self.zipcode = kwargs.get('zipcode', '').strip()
- self.key = ':'.join(('loc', self.name, self.country, self.state, self.zipcode)).lower()
+
+ def getId(self):
+
+ return '%s:%s' % (self.__class__.__name__, ':'.join((str(getattr(self, x)) for x in self.__keyspec__ or self.__spec__)))
+
+ @classmethod
+ def getGeohashIndexKey(cls):
+
+ return '%s:geohash' % cls.__name__
def save(self, redisConn):
+
+ #save all properties
+ redisConn.hmset(self.getId(), dict(((k, getattr(self, k)) for k in \
+ self.__spec__)))
- redisConn.hmset(self.key, dict(((k, getattr(self, k)) for k in \
- ('lat', 'lon', 'name', 'country', 'state', 'zipcode'))))
+ self._indexGeohash(redisConn)
- redisConn.zadd('locations:geohash', self.key, geohash.encode_uint64(self.lat, self.lon))
+
+ def _indexGeohash(self, redisConn):
+ """
+ Save the key of the object into the goehash index for this object type
+ """
+
+ redisConn.zadd(self.getGeohashIndexKey(), self.getId(), geohash.encode_uint64(self.lat, self.lon))
+
def __str__(self):
- return "Location: %s" % self.__dict__
+ return "%s: %s" % (self.__class__.__name__, self.__dict__)
- @staticmethod
- def load(key, redisConn):
+ @classmethod
+ def load(cls, key, redisConn):
"""
a Factory function to load a location from a given location key
"""
@@ -69,13 +87,15 @@ def load(key, redisConn):
return None
#build a new object based on the loaded dict
- return Location(**d)
+ return cls(**d)
+
+
+ @classmethod
+ def getByLatLon(cls, lat, lon, redisConn):
- @staticmethod
- def getByLatLon(lat, lon, redisConn):
geoKey = geohash.encode_uint64(lat, lon)
- return Location.getByGeohash(geoKey, redisConn)
+ return cls.getByGeohash(geoKey, redisConn)
@staticmethod
def getDistance(geoHash1, geoHash2):
@@ -85,24 +105,25 @@ def getDistance(geoHash1, geoHash2):
return abs(geoHash1 - geoHash2)
- try:
- coords1 = geohash.decode_uint64(geoHash1)
- coords2 = geohash.decode_uint64(geoHash2)
- print coords1, coords2
- return math.sqrt(math.pow(coords1[0] - coords2[0], 2) +
- math.pow(coords1[1] - coords2[1], 2))
- except Exception, e:
- print e
- return None
+# try:
+# coords1 = geohash.decode_uint64(geoHash1)
+# coords2 = geohash.decode_uint64(geoHash2)
+# print coords1, coords2
+# return math.sqrt(math.pow(coords1[0] - coords2[0], 2) +
+# math.pow(coords1[1] - coords2[1], 2))
+# except Exception, e:
+# print e
+# return None
- @staticmethod
- def getByGeohash(geoKey, redisConn):
-
+ @classmethod
+ def getByGeohash(cls, geoKey, redisConn):
+
+ key = cls.getGeohashIndexKey()
tx = redisConn.pipeline()
- tx.zrangebyscore('locations:geohash', geoKey, 'inf', 0, 1, True)
- tx.zrevrangebyscore('locations:geohash', geoKey, '-inf', 0, 1, True)
+ tx.zrangebyscore(key, geoKey, 'inf', 0, 1, True)
+ tx.zrevrangebyscore(key, geoKey, '-inf', 0, 1, True)
ret = tx.execute()
#find the two closest locations to the left and to the right of us
@@ -116,14 +137,11 @@ def getByGeohash(geoKey, redisConn):
for i in xrange(len(candidates)):
gk = (candidates[i][1])
- #gk = struct.unpack('i', struct.pack('f', candidates [i][1]))[0]
-
dist = Location.getDistance(geoKey, gk)
if dist is None:
continue
-
if not closestDist or dist < closestDist:
closestDist = dist
selected = i
@@ -133,7 +151,7 @@ def getByGeohash(geoKey, redisConn):
return None
- return Location.load(str(candidates[selected][0]), redisConn)
+ return cls.load(str(candidates[selected][0]), redisConn)
25 src/provider/geonames.py
View
@@ -26,26 +26,27 @@
#Importer for locations from geonames
-from location import Location
+from city import City
import csv
import logging
import redis
import re
-from countries import countries
+from importer import Importer
-
-class GeonamesImporter(object):
+class GeonamesImporter(Importer):
- def __init__(self, fileName, redisHost, redisPort):
+ def __init__(self, fileName, redisHost, redisPort, redisDB = 0):
"""
Init a geonames cities importer
@param fileName path to the geonames datafile
@param redisConn redis connection
"""
+
+ Importer.__init__(self, fileName ,redisHost, redisPort, redisDB)
+
fileNames = fileName.split(',')
self.fileName = fileNames[0]
self.adminCodesFileName = fileNames[1] if len(fileNames) > 1 else None
- self.redis = redis.Redis(host = redisHost, port = redisPort)
self._adminCodes = {}
def _readAdminCodes(self):
@@ -93,18 +94,19 @@ def runImport(self):
try:
name = row[2]
-
+
country = row[8]
adminCode = '.'.join((country, row[10]))
region = re.sub('\\(.+\\)', '', self._adminCodes.get(adminCode, '')).strip()
-
- if country == 'US' and not region:
+
+ #for us states - take only state code not full name
+ if country == 'US':
region = row[10]
lat = float(row[4])
lon = float(row[5])
- loc = Location(name = name,
+ loc = City(name = name,
country = country,
state = region,
lat = lat,
@@ -112,13 +114,14 @@ def runImport(self):
loc.save(pipe)
-
+
except Exception, e:
logging.error("Could not import line %s: %s" % (row, e))
i += 1
if i % 1000 == 0:
pipe.execute()
+ pipe.execute()
logging.info("Imported %d locations" % i)
38 src/provider/importer.py
View
@@ -0,0 +1,38 @@
+#Copyright 2011 Do@. All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without modification, are
+#permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+#THIS SOFTWARE IS PROVIDED BY Do@ ``AS IS'' AND ANY EXPRESS OR IMPLIED
+#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#The views and conclusions contained in the software and documentation are those of the
+#authors and should not be interpreted as representing official policies, either expressed
+#or implied, of Do@.
+
+import redis
+
+class Importer(object):
+ """
+ Base class for all importer scripts, inits a redis connection and file name
+ """
+ def __init__(self, fileName ,redisHost, redisPort, redisDB):
+
+ self.fileName = fileName
+ self.redis = redis.Redis(host = redisHost, port = redisPort, db = redisDB)
+
+
25 src/provider/ip2location.py
View
@@ -31,23 +31,15 @@
import logging
import redis
+from importer import Importer
from iprange import IPRange
-class IP2LocationImporter(object):
-
- def __init__(self, fileName, redisHost, redisPort):
- """
- Init a geonames cities importer
- @param fileName path to the geonames datafile
- @param redisConn redis connection
- """
- self.fileName = fileName
- self.redis = redis.Redis(host = redisHost, port = redisPort)
+class IP2LocationImporter(Importer):
def runImport(self):
"""
File Format:
- "50331648","50331903","US","UNITED STATES","MASSACHUSETTS","BEVERLY","42.5685","-70.8619"
+ "67134976","67135231","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.045200","-118.284000","90001"
"""
@@ -62,20 +54,27 @@ def runImport(self):
i = 0
for row in reader:
- #['53160704', '53160959', 'US', 'UNITED STATES', 'MASSACHUSETTS', 'BEVERLY', '42.5685', '-70.8619', 'GENERAL ELECTRIC COMPANY', 'GE.COM']
+
try:
+ #parse the row
countryCode = row[3]
rangeMin = int(row[0])
rangeMax = int(row[1])
lat = float(row[6])
lon = float(row[7])
+ #take the zipcode if possible
+ try:
+ zipcode = row[8]
+ except:
+ zipcode = ''
+
#junk record
if countryCode == '-' and (not lat and not lon):
continue
- range = IPRange(rangeMin, rangeMax, lat, lon)
+ range = IPRange(rangeMin, rangeMax, lat, lon, zipcode)
range.save(pipe)
except Exception, e:
87 src/provider/zipcodes.py
View
@@ -0,0 +1,87 @@
+#Copyright 2011 Do@. All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without modification, are
+#permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+#THIS SOFTWARE IS PROVIDED BY Do@ ``AS IS'' AND ANY EXPRESS OR IMPLIED
+#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#The views and conclusions contained in the software and documentation are those of the
+#authors and should not be interpreted as representing official policies, either expressed
+#or implied, of Do@.
+
+#Importer for zipcodes.csv file found in /data
+
+from zipcode import ZIPCode
+from us_states import code_to_state
+import csv
+import logging
+
+from importer import Importer
+
+class ZIPImporter(Importer):
+
+
+ def runImport(self):
+ """
+ File Format:
+ "00210","Portsmouth","NH","43.005895","-71.013202","-5","1"
+ """
+
+ try:
+ fp = open(self.fileName)
+ except Exception, e:
+ logging.error("could not open file %s for reading: %s" % (self.fileName, e))
+ return False
+
+ reader = csv.reader(fp, delimiter=',', quotechar = '"')
+ pipe = self.redis.pipeline()
+
+ i = 0
+ for row in reader:
+
+ try:
+ name = row[0]
+ city = row[1]
+ stateCode = row[2]
+ lat = float(row[3])
+ lon = float(row[4])
+ state = code_to_state.get(stateCode, '').title()
+ country = 'US'
+
+ loc = ZIPCode(name = name,
+ city = city,
+ country = country,
+ state = state,
+ lat = lat,
+ lon = lon)
+
+ loc.save(pipe)
+
+
+
+ except Exception, e:
+ logging.error("Could not import line %s: %s" % (row, e))
+ i += 1
+ if i % 1000 == 0:
+ pipe.execute()
+
+ pipe.execute()
+
+ logging.info("Imported %d locations" % i)
+
+ return i
5 src/us_states.py
View
@@ -0,0 +1,5 @@
+#US State codes taken from http://www.cmmichael.com/blog/2006/12/29/state-code-mappings-for-python
+
+state_to_code = {'VERMONT': 'VT', 'GEORGIA': 'GA', 'IOWA': 'IA', 'Armed Forces Pacific': 'AP', 'GUAM': 'GU', 'KANSAS': 'KS', 'FLORIDA': 'FL', 'AMERICAN SAMOA': 'AS', 'NORTH CAROLINA': 'NC', 'HAWAII': 'HI', 'NEW YORK': 'NY', 'CALIFORNIA': 'CA', 'ALABAMA': 'AL', 'IDAHO': 'ID', 'FEDERATED STATES OF MICRONESIA': 'FM', 'Armed Forces Americas': 'AA', 'DELAWARE': 'DE', 'ALASKA': 'AK', 'ILLINOIS': 'IL', 'Armed Forces Africa': 'AE', 'SOUTH DAKOTA': 'SD', 'CONNECTICUT': 'CT', 'MONTANA': 'MT', 'MASSACHUSETTS': 'MA', 'PUERTO RICO': 'PR', 'Armed Forces Canada': 'AE', 'NEW HAMPSHIRE': 'NH', 'MARYLAND': 'MD', 'NEW MEXICO': 'NM', 'MISSISSIPPI': 'MS', 'TENNESSEE': 'TN', 'PALAU': 'PW', 'COLORADO': 'CO', 'Armed Forces Middle East': 'AE', 'NEW JERSEY': 'NJ', 'UTAH': 'UT', 'MICHIGAN': 'MI', 'WEST VIRGINIA': 'WV', 'WASHINGTON': 'WA', 'MINNESOTA': 'MN', 'OREGON': 'OR', 'VIRGINIA': 'VA', 'VIRGIN ISLANDS': 'VI', 'MARSHALL ISLANDS': 'MH', 'WYOMING': 'WY', 'OHIO': 'OH', 'SOUTH CAROLINA': 'SC', 'INDIANA': 'IN', 'NEVADA': 'NV', 'LOUISIANA': 'LA', 'NORTHERN MARIANA ISLANDS': 'MP', 'NEBRASKA': 'NE', 'ARIZONA': 'AZ', 'WISCONSIN': 'WI', 'NORTH DAKOTA': 'ND', 'Armed Forces Europe': 'AE', 'PENNSYLVANIA': 'PA', 'OKLAHOMA': 'OK', 'KENTUCKY': 'KY', 'RHODE ISLAND': 'RI', 'DISTRICT OF COLUMBIA': 'DC', 'ARKANSAS': 'AR', 'MISSOURI': 'MO', 'TEXAS': 'TX', 'MAINE': 'ME'}
+
+code_to_state = {'WA': 'WASHINGTON', 'VA': 'VIRGINIA', 'DE': 'DELAWARE', 'DC': 'DISTRICT OF COLUMBIA', 'WI': 'WISCONSIN', 'WV': 'WEST VIRGINIA', 'HI': 'HAWAII', 'AE': 'Armed Forces Middle East', 'FL': 'FLORIDA', 'FM': 'FEDERATED STATES OF MICRONESIA', 'WY': 'WYOMING', 'NH': 'NEW HAMPSHIRE', 'NJ': 'NEW JERSEY', 'NM': 'NEW MEXICO', 'TX': 'TEXAS', 'LA': 'LOUISIANA', 'NC': 'NORTH CAROLINA', 'ND': 'NORTH DAKOTA', 'NE': 'NEBRASKA', 'TN': 'TENNESSEE', 'NY': 'NEW YORK', 'PA': 'PENNSYLVANIA', 'CA': 'CALIFORNIA', 'NV': 'NEVADA', 'AA': 'Armed Forces Americas', 'PW': 'PALAU', 'GU': 'GUAM', 'CO': 'COLORADO', 'VI': 'VIRGIN ISLANDS', 'AK': 'ALASKA', 'AL': 'ALABAMA', 'AP': 'Armed Forces Pacific', 'AS': 'AMERICAN SAMOA', 'AR': 'ARKANSAS', 'VT': 'VERMONT', 'IL': 'ILLINOIS', 'GA': 'GEORGIA', 'IN': 'INDIANA', 'IA': 'IOWA', 'OK': 'OKLAHOMA', 'AZ': 'ARIZONA', 'ID': 'IDAHO', 'CT': 'CONNECTICUT', 'ME': 'MAINE', 'MD': 'MARYLAND', 'MA': 'MASSACHUSETTS', 'OH': 'OHIO', 'UT': 'UTAH', 'MO': 'MISSOURI', 'MN': 'MINNESOTA', 'MI': 'MICHIGAN', 'MH': 'MARSHALL ISLANDS', 'RI': 'RHODE ISLAND', 'KS': 'KANSAS', 'MT': 'MONTANA', 'MP': 'NORTHERN MARIANA ISLANDS', 'MS': 'MISSISSIPPI', 'PR': 'PUERTO RICO', 'SC': 'SOUTH CAROLINA', 'KY': 'KENTUCKY', 'OR': 'OREGON', 'SD': 'SOUTH DAKOTA'}
46 src/zipcode.py
View
@@ -0,0 +1,46 @@
+#Copyright 2011 Do@. All rights reserved.
+#
+#Redistribution and use in source and binary forms, with or without modification, are
+#permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other materials
+# provided with the distribution.
+#
+#THIS SOFTWARE IS PROVIDED BY Do@ ``AS IS'' AND ANY EXPRESS OR IMPLIED
+#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+#FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+#CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+#SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+#ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#The views and conclusions contained in the software and documentation are those of the
+#authors and should not be interpreted as representing official policies, either expressed
+#or implied, of Do@.
+
+from countries import countries
+import geohash
+
+from location import Location
+
+class ZIPCode(Location):
+
+ __spec__ = Location.__spec__ + ['country', 'state', 'city']
+ __keyspec__ = ['name']
+
+ def __init__(self, **kwargs):
+
+ super(ZIPCode, self).__init__(**kwargs)
+
+ self.country = countries.get( kwargs.get('country', None), kwargs.get('country', '')).strip()
+ self.state = kwargs.get('state', '').strip()
+ self.city = kwargs.get('city', '').strip()
+
+
+
202 test/data/ip2location.csv
View
@@ -1,100 +1,102 @@
-"67297912","67297919","US","UNITED STATES","TEXAS","FLOWER MOUND","33.0327","-97.0895"
-"67297920","67297927","US","UNITED STATES","TENNESSEE","MEMPHIS","35.1292","-89.9892"
-"67297928","67297935","US","UNITED STATES","TEXAS","ENNIS","32.3387","-96.6021"
-"67297936","67297943","US","UNITED STATES","MISSOURI","BRANSON","36.6647","-93.2412"
-"67297944","67297951","US","UNITED STATES","SOUTH CAROLINA","WASHINGTON","44.2744","-69.3901"
-"67297952","67298015","US","UNITED STATES","TEXAS","IRVING","32.8412","-96.9596"
-"67298016","67298047","US","UNITED STATES","NEW YORK","NEW YORK","40.7488","-73.9846"
-"67298048","67298111","US","UNITED STATES","SOUTH CAROLINA","CONWAY","33.8157","-79.0739"
-"67298112","67298119","US","UNITED STATES","INDIANA","GOSHEN","41.5836","-85.8345"
-"67298120","67298135","US","UNITED STATES","OHIO","CINCINNATI","39.0975","-84.472"
-"67298136","67298143","US","UNITED STATES","SOUTH CAROLINA","GREENVILLE","34.8522","-82.3924"
-"67298144","67298175","US","UNITED STATES","-","-","0","0"
-"67298176","67298183","US","UNITED STATES","TENNESSEE","MEMPHIS","35.1292","-89.9892"
-"67298184","67298191","US","UNITED STATES","MARYLAND","GAITHERSBURG","39.1578","-77.1963"
-"67298192","67298199","US","UNITED STATES","NEW YORK","NEW YORK","40.7488","-73.9846"
-"67298200","67298207","US","UNITED STATES","UTAH","LINDON","40.3418","-111.723"
-"67298208","67298239","US","UNITED STATES","VIRGINIA","VIENNA","38.9097","-77.2717"
-"67298240","67298271","US","UNITED STATES","SOUTH CAROLINA","MYRTLE BEACH","33.6903","-78.9245"
-"67298272","67298279","US","UNITED STATES","MARYLAND","BALTIMORE","39.2894","-76.6384"
-"67298280","67305471","US","UNITED STATES","-","-","0","0"
-"67305472","67306495","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038"
-"67306496","67306751","US","UNITED STATES","INDIANA","JASPER","38.4046","-86.9484"
-"67306752","67307519","US","UNITED STATES","HAWAII","WAHIAWA","21.5026","-158.028"
-"67307520","67308287","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67308288","67308543","US","UNITED STATES","CALIFORNIA","SANTA MONICA","34.0216","-118.488"
-"67308544","67308799","US","UNITED STATES","CALIFORNIA","MONTCLAIR","34.0753","-117.697"
-"67308800","67309311","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67309312","67309567","US","UNITED STATES","CALIFORNIA","SANTA MONICA","34.0216","-118.488"
-"67309568","67311359","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038"
-"67311360","67311615","US","UNITED STATES","CALIFORNIA","MONTCLAIR","34.0753","-117.697"
-"67311616","67311871","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038"
-"67311872","67312127","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67312128","67312383","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216"
-"67312384","67312639","US","UNITED STATES","CALIFORNIA","SUNLAND","34.2627","-118.316"
-"67312640","67312895","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284"
-"67312896","67313151","US","UNITED STATES","FLORIDA","TAMPA","27.9733","-82.4717"
-"67313152","67313407","US","UNITED STATES","CALIFORNIA","BEVERLY HILLS","34.0749","-118.399"
-"67313408","67313663","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038"
-"67313664","67314431","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67314432","67314687","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216"
-"67314688","67314943","US","UNITED STATES","CALIFORNIA","WEST COVINA","34.0535","-117.918"
-"67314944","67315711","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67315712","67317759","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67317760","67318015","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442"
-"67318016","67318527","US","UNITED STATES","MICHIGAN","LUDINGTON","43.9737","-86.4001"
-"67318528","67319039","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67319040","67319295","US","UNITED STATES","ILLINOIS","CHICAGO","41.865","-87.6718"
-"67319296","67319551","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67319552","67319807","US","UNITED STATES","INDIANA","LAFAYETTE","40.4091","-86.8592"
-"67319808","67320063","US","UNITED STATES","MICHIGAN","LUDINGTON","43.9737","-86.4001"
-"67320064","67320319","US","UNITED STATES","FLORIDA","TAMPA","27.9733","-82.4717"
-"67320320","67320575","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442"
-"67320576","67320831","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67320832","67321343","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284"
-"67321344","67321599","US","UNITED STATES","CALIFORNIA","HUNTINGTON BEACH","33.6907","-118.002"
-"67321600","67321855","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442"
-"67321856","67322879","US","UNITED STATES","TEXAS","IRVING","32.8412","-96.9596"
-"67322880","67323135","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67323136","67323391","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284"
-"67323392","67323647","US","UNITED STATES","FLORIDA","BRANDON","27.9339","-82.2918"
-"67323648","67323903","US","UNITED STATES","TEXAS","GARLAND","32.9161","-96.6327"
-"67323904","67324159","US","UNITED STATES","CALIFORNIA","WOODLAND HILLS","34.1669","-118.604"
-"67324160","67324927","US","UNITED STATES","CALIFORNIA","NEWBURY PARK","34.167","-118.944"
-"67324928","67325439","US","UNITED STATES","CALIFORNIA","WOODLAND HILLS","34.1669","-118.604"
-"67325440","67325695","US","UNITED STATES","CALIFORNIA","NEWBURY PARK","34.167","-118.944"
-"67325696","67325951","US","UNITED STATES","CALIFORNIA","WOODLAND HILLS","34.1669","-118.604"
-"67325952","67326207","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67326208","67326463","US","UNITED STATES","TEXAS","IRVING","32.8412","-96.9596"
-"67326464","67326719","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67326720","67326975","US","UNITED STATES","FLORIDA","TAMPA","27.9733","-82.4717"
-"67326976","67327231","US","UNITED STATES","CALIFORNIA","MONTCLAIR","34.0753","-117.697"
-"67327232","67327999","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284"
-"67328000","67328255","US","UNITED STATES","VIRGINIA","NORFOLK","36.8984","-76.2161"
-"67328256","67329023","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67329024","67330047","US","UNITED STATES","NEW YORK","NEW YORK","40.7488","-73.9846"
-"67330048","67330559","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67330560","67330815","US","UNITED STATES","MISSOURI","COLUMBIA","38.9424","-92.3145"
-"67330816","67331839","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67331840","67332095","US","UNITED STATES","TEXAS","GRAPEVINE","32.9309","-97.0755"
-"67332096","67333119","US","UNITED STATES","CALIFORNIA","AGOURA HILLS","34.1317","-118.766"
-"67333120","67334143","US","UNITED STATES","CALIFORNIA","HACIENDA HEIGHTS","33.9955","-117.976"
-"67334144","67334399","US","UNITED STATES","VIRGINIA","WOODBRIDGE","38.6546","-77.2877"
-"67334400","67334655","US","UNITED STATES","TEXAS","LEWISVILLE","33.0502","-97.0188"
-"67334656","67334911","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67334912","67335167","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442"
-"67335168","67335679","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67335680","67335935","US","UNITED STATES","TEXAS","LEWISVILLE","33.0502","-97.0188"
-"67335936","67336191","US","UNITED STATES","VIRGINIA","MANASSAS","38.7415","-77.4674"
-"67336192","67336447","US","UNITED STATES","TEXAS","GRAPEVINE","32.9309","-97.0755"
-"67336448","67336703","US","UNITED STATES","OREGON","PORTLAND","45.4793","-122.689"
-"67336704","67336959","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284"
-"67336960","67337215","US","UNITED STATES","INDIANA","WEST LAFAYETTE","40.4427","-86.9237"
-"67337216","67337471","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67337472","67337727","US","UNITED STATES","CALIFORNIA","HUNTINGTON BEACH","33.6907","-118.002"
-"67337728","67337983","US","UNITED STATES","CALIFORNIA","ARTESIA","33.8668","-118.082"
-"67337984","67338239","US","UNITED STATES","CALIFORNIA","WEST COVINA","34.0535","-117.918"
-"67338240","67339519","US","UNITED STATES","CALIFORNIA","HACIENDA HEIGHTS","33.9955","-117.976"
-"67339520","67340287","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17"
-"67340288","67341311","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024"
-"67341312","67341567","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238"
+
+"67297920","67297927","US","UNITED STATES","TENNESSEE","MEMPHIS","35.1292","-89.9892","38103"
+"67297928","67297935","US","UNITED STATES","TEXAS","ENNIS","32.3387","-96.6021","75119"
+"67297936","67297943","US","UNITED STATES","MISSOURI","BRANSON","36.6647","-93.2412","65616"
+"67297944","67297951","US","UNITED STATES","SOUTH CAROLINA","GEORGETOWN","33.4905","-79.2882","29440"
+"67297952","67298015","US","UNITED STATES","TEXAS","IRVING","32.8412","-96.9596","75038"
+"67298016","67298047","US","UNITED STATES","NEW YORK","NEW YORK","40.7488","-73.9846","10016"
+"67298048","67298111","US","UNITED STATES","SOUTH CAROLINA","CONWAY","33.8157","-79.0739","29526"
+"67298112","67298119","US","UNITED STATES","INDIANA","GOSHEN","41.5836","-85.8345","46526"
+"67298120","67298135","US","UNITED STATES","OHIO","CINCINNATI","39.0975","-84.472","45202"
+"67298136","67298175","US","UNITED STATES","-","-","38.9048","-77.0354","-"
+"67298176","67298183","US","UNITED STATES","TENNESSEE","MEMPHIS","35.1292","-89.9892","38118"
+"67298184","67298191","US","UNITED STATES","MARYLAND","GAITHERSBURG","39.1578","-77.1963","20878"
+"67298192","67298207","US","UNITED STATES","-","-","38.9048","-77.0354","-"
+"67298208","67298239","US","UNITED STATES","VIRGINIA","VIENNA","38.9097","-77.2717","22180"
+"67298240","67298271","US","UNITED STATES","SOUTH CAROLINA","MYRTLE BEACH","33.6903","-78.9245","29577"
+"67298272","67298279","US","UNITED STATES","MARYLAND","BALTIMORE","39.2894","-76.6384","21230"
+"67298280","67299327","US","UNITED STATES","-","-","38.9048","-77.0354","-"
+"67299328","67305471","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67305472","67306495","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038","27701"
+"67306496","67307007","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67307008","67307519","US","UNITED STATES","INDIANA","INDIANAPOLIS","39.8643","-86.1477","46201"
+"67307520","67309567","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17","90745"
+"67309568","67309823","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038","27701"
+"67309824","67310079","US","UNITED STATES","VIRGINIA","ARLINGTON","38.8783","-77.1078","22201"
+"67310080","67311359","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038","27701"
+"67311360","67311615","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67311616","67311871","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038","27701"
+"67311872","67312127","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67312128","67312383","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67312384","67312639","US","UNITED STATES","CALIFORNIA","RANCHO CUCAMONGA","34.1237","-117.572","91701"
+"67312640","67312895","US","UNITED STATES","CALIFORNIA","MOORPARK","34.3023","-118.873","93020"
+"67312896","67313151","US","UNITED STATES","FLORIDA","TAMPA","27.9733","-82.4717","33601"
+"67313152","67313407","US","UNITED STATES","CALIFORNIA","TORRANCE","33.8413","-118.333","90501"
+"67313408","67313663","US","UNITED STATES","NORTH CAROLINA","DURHAM","35.9971","-78.9038","27701"
+"67313664","67314687","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67314688","67314943","US","UNITED STATES","CALIFORNIA","WEST COVINA","34.0535","-117.918","91790"
+"67314944","67315711","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67315712","67318015","US","UNITED STATES","CALIFORNIA","SYLMAR","34.3177","-118.419","91342"
+"67318016","67318527","US","UNITED STATES","MICHIGAN","LUDINGTON","43.9737","-86.4001","49431"
+"67318528","67319039","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67319040","67319295","US","UNITED STATES","ILLINOIS","ROCKFORD","42.2722","-89.0688","61101"
+"67319296","67319551","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67319552","67319807","US","UNITED STATES","INDIANA","LAFAYETTE","40.4091","-86.8592","47901"
+"67319808","67320063","US","UNITED STATES","MICHIGAN","LUDINGTON","43.9737","-86.4001","49431"
+"67320064","67320319","US","UNITED STATES","FLORIDA","SARASOTA","27.3595","-82.5012","34230"
+"67320320","67320575","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442","20191"
+"67320576","67320831","US","UNITED STATES","TEXAS","CARROLLTON","32.9949","-96.8967","75006"
+"67320832","67321087","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17","90745"
+"67321088","67321343","US","UNITED STATES","CALIFORNIA","MOORPARK","34.3023","-118.873","93020"
+"67321344","67321599","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442","20191"
+"67321600","67321855","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67321856","67322879","US","UNITED STATES","CALIFORNIA","AZUSA","34.1312","-117.916","91702"
+"67322880","67323135","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67323136","67323391","US","UNITED STATES","CALIFORNIA","RANCHO CUCAMONGA","34.1237","-117.572","91701"
+"67323392","67323647","US","UNITED STATES","VIRGINIA","RESTON","38.9623","-77.3442","20191"
+"67323648","67323903","US","UNITED STATES","TEXAS","GARLAND","32.9161","-96.6327","75040"
+"67323904","67324159","US","UNITED STATES","CALIFORNIA","RESEDA","34.2011","-118.538","91335"
+"67324160","67324671","US","UNITED STATES","CALIFORNIA","REDONDO BEACH","33.8521","-118.377","90277"
+"67324672","67325183","US","UNITED STATES","CALIFORNIA","RESEDA","34.2011","-118.538","91335"
+"67325184","67325439","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67325440","67325695","US","UNITED STATES","CALIFORNIA","RESEDA","34.2011","-118.538","91335"
+"67325696","67325951","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67325952","67326463","US","UNITED STATES","TEXAS","ARLINGTON","32.7173","-97.1143","76001"
+"67326464","67326719","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67326720","67326975","US","UNITED STATES","FLORIDA","BRADENTON","27.4649","-82.5465","34201"
+"67326976","67327231","US","UNITED STATES","CALIFORNIA","MONTCLAIR","34.0753","-117.697","91763"
+"67327232","67327999","US","UNITED STATES","CALIFORNIA","OXNARD","34.1928","-119.176","93030"
+"67328000","67329023","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67329024","67330047","US","UNITED STATES","NEW YORK","NEW YORK","40.7488","-73.9846","10001"
+"67330048","67330559","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67330560","67330815","US","UNITED STATES","MISSOURI","COLUMBIA","38.9424","-92.3145","65201"
+"67330816","67331071","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67331072","67331327","US","UNITED STATES","FLORIDA","BRADENTON","27.4649","-82.5465","34201"
+"67331328","67331583","US","UNITED STATES","FLORIDA","-","38.9048","-77.0354","-"
+"67331584","67331839","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67331840","67332095","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17","90745"
+"67332096","67334399","US","UNITED STATES","CALIFORNIA","LA PUENTE","34.0292","-117.955","91744"
+"67334400","67334655","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67334656","67334911","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67334912","67335167","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67335168","67335679","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67335680","67335935","US","UNITED STATES","TEXAS","PILOT POINT","33.3456","-96.9066","76258"
+"67335936","67336191","US","UNITED STATES","VIRGINIA","MANASSAS","38.7415","-77.4674","20108"
+"67336192","67336447","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17","90745"
+"67336448","67336703","US","UNITED STATES","OREGON","PORTLAND","45.4793","-122.689","97201"
+"67336704","67336959","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67336960","67337215","US","UNITED STATES","INDIANA","WEST LAFAYETTE","40.4427","-86.9237","47906"
+"67337216","67338239","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67338240","67339263","US","UNITED STATES","WASHINGTON","EVERETT","47.9563","-122.216","98201"
+"67339264","67340287","US","UNITED STATES","CALIFORNIA","LONG BEACH","33.7876","-118.17","90745"
+"67340288","67340543","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67340544","67341311","US","UNITED STATES","TEXAS","DALLAS","32.7961","-96.8024","75201"
+"67341312","67341567","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67341568","67342079","US","UNITED STATES","NEW YORK","BROOKLYN","40.6594","-73.9625","11201"
+"67342080","67342335","US","UNITED STATES","TEXAS","PLANO","33.0404","-96.7238","75023"
+"67342336","67342591","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67342592","67342847","US","UNITED STATES","CALIFORNIA","RESEDA","34.2011","-118.538","91335"
+"67342848","67343871","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+"67343872","67344127","US","UNITED STATES","CALIFORNIA","REDONDO BEACH","33.8521","-118.377","90277"
+"67344128","67344639","US","UNITED STATES","CALIFORNIA","LOS ANGELES","34.0452","-118.284","90001"
+
741 test/data/zipcodes.csv
View
@@ -0,0 +1,741 @@
+"90001","Los Angeles","CA","33.972914","-118.24878","-8","1"
+"90002","Los Angeles","CA","33.948315","-118.24845","-8","1"
+"90003","Los Angeles","CA","33.962714","-118.276","-8","1"
+"90004","Los Angeles","CA","34.07711","-118.30755","-8","1"
+"90005","Los Angeles","CA","34.058911","-118.30848","-8","1"
+"90006","Los Angeles","CA","34.048351","-118.2943","-8","1"
+"90007","Los Angeles","CA","34.026448","-118.2829","-8","1"
+"90008","Los Angeles","CA","34.009754","-118.33705","-8","1"
+"90009","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90010","Los Angeles","CA","34.062709","-118.31481","-8","1"
+"90011","Los Angeles","CA","34.007063","-118.25868","-8","1"
+"90012","Los Angeles","CA","34.061611","-118.23944","-8","1"
+"90013","Los Angeles","CA","34.044662","-118.24255","-8","1"
+"90014","Los Angeles","CA","34.042912","-118.25193","-8","1"
+"90015","Los Angeles","CA","34.038993","-118.26516","-8","1"
+"90016","Los Angeles","CA","34.029711","-118.35255","-8","1"
+"90017","Los Angeles","CA","34.052561","-118.26434","-8","1"
+"90018","Los Angeles","CA","34.029112","-118.3183","-8","1"
+"90019","Los Angeles","CA","34.048411","-118.34015","-8","1"
+"90020","Los Angeles","CA","34.06646","-118.30863","-8","1"
+"90021","Los Angeles","CA","34.029313","-118.24182","-8","1"
+"90022","Los Angeles","CA","34.023662","-118.15581","-8","1"
+"90023","Los Angeles","CA","34.023039","-118.20231","-8","1"
+"90024","Los Angeles","CA","34.063209","-118.43643","-8","1"
+"90025","Los Angeles","CA","34.045006","-118.44527","-8","1"
+"90026","Los Angeles","CA","34.07851","-118.26596","-8","1"
+"90027","Los Angeles","CA","34.111208","-118.28842","-8","1"
+"90028","Los Angeles","CA","34.098859","-118.32745","-8","1"
+"90029","Los Angeles","CA","34.090259","-118.29455","-8","1"
+"90030","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90031","Los Angeles","CA","34.07871","-118.2161","-8","1"
+"90032","Los Angeles","CA","34.08166","-118.17568","-8","1"
+"90033","Los Angeles","CA","34.050411","-118.21195","-8","1"
+"90034","Los Angeles","CA","34.03056","-118.39804","-8","1"
+"90035","Los Angeles","CA","34.05266","-118.38531","-8","1"
+"90036","Los Angeles","CA","34.07036","-118.34926","-8","1"
+"90037","Los Angeles","CA","34.002063","-118.28737","-8","1"
+"90038","Los Angeles","CA","34.089459","-118.3285","-8","1"
+"90039","Los Angeles","CA","34.110425","-118.25832","-8","1"
+"90040","Los Angeles","CA","33.997492","-118.15284","-8","1"
+"90041","Los Angeles","CA","34.137557","-118.20765","-8","1"
+"90042","Los Angeles","CA","34.114558","-118.19233","-8","1"
+"90043","Los Angeles","CA","33.987463","-118.334","-8","1"
+"90044","Los Angeles","CA","33.953814","-118.29158","-8","1"
+"90045","Los Angeles","CA","33.960041","-118.3949","-8","1"
+"90046","Los Angeles","CA","34.098908","-118.36241","-8","1"
+"90047","Los Angeles","CA","33.958464","-118.30998","-8","1"
+"90048","Los Angeles","CA","34.073759","-118.37376","-8","1"
+"90049","Los Angeles","CA","34.067409","-118.47528","-8","1"
+"90050","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90051","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90052","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90053","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90054","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90055","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90056","Los Angeles","CA","33.986212","-118.37099","-8","1"
+"90057","Los Angeles","CA","34.061911","-118.27687","-8","1"
+"90058","Los Angeles","CA","34.000219","-118.22605","-8","1"
+"90059","Los Angeles","CA","33.927471","-118.24778","-8","1"
+"90060","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90061","Los Angeles","CA","33.923365","-118.27591","-8","1"
+"90062","Los Angeles","CA","34.003213","-118.3078","-8","1"
+"90063","Los Angeles","CA","34.045161","-118.1865","-8","1"
+"90064","Los Angeles","CA","34.03457","-118.42843","-8","1"
+"90065","Los Angeles","CA","34.107559","-118.22663","-8","1"
+"90066","Los Angeles","CA","34.002011","-118.43083","-8","1"
+"90067","Los Angeles","CA","34.056709","-118.41183","-8","1"
+"90068","Los Angeles","CA","34.122058","-118.3379","-8","1"
+"90069","West Hollywood","CA","34.090975","-118.3813","-8","1"
+"90070","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90071","Los Angeles","CA","34.052709","-118.2559","-8","1"
+"90072","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90073","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90074","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90075","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90076","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90077","Los Angeles","CA","34.101007","-118.45077","-8","1"
+"90078","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90079","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90080","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90081","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90082","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90083","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90084","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90086","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90087","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90088","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90089","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90091","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90093","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90094","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90095","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90096","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90097","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90099","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90101","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90102","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90103","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90174","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90185","Los Angeles","CA","33.786594","-118.298662","-8","1"
+"90201","Bell","CA","33.972814","-118.17385","-8","1"
+"90202","Bell Gardens","CA","33.786594","-118.298662","-8","1"
+"90204","Inglewood","CA","33.944714","-118.356908","-8","1"
+"90209","Beverly Hills","CA","33.786594","-118.298662","-8","1"
+"90210","Beverly Hills","CA","34.088808","-118.40612","-8","1"
+"90211","Beverly Hills","CA","34.066009","-118.38271","-8","1"
+"90212","Beverly Hills","CA","34.060859","-118.40191","-8","1"
+"90213","Beverly Hills","CA","33.786594","-118.298662","-8","1"
+"90220","Compton","CA","33.890566","-118.23666","-8","1"
+"90221","Compton","CA","33.893265","-118.204","-8","1"
+"90222","Compton","CA","33.910716","-118.23624","-8","1"
+"90223","Compton","CA","33.786594","-118.298662","-8","1"
+"90224","Compton","CA","33.786594","-118.298662","-8","1"
+"90230","Culver City","CA","33.997179","-118.40145","-8","1"
+"90231","Culver City","CA","33.786594","-118.298662","-8","1"
+"90232","Culver City","CA","34.021611","-118.39168","-8","1"
+"90233","Culver City","CA","33.786594","-118.298662","-8","1"
+"90239","Downey","CA","33.786594","-118.298662","-8","1"
+"90240","Downey","CA","33.958363","-118.11987","-8","1"
+"90241","Downey","CA","33.942289","-118.12901","-8","1"
+"90242","Downey","CA","33.92018","-118.14291","-8","1"
+"90245","El Segundo","CA","33.921313","-118.40843","-8","1"
+"90247","Gardena","CA","33.891265","-118.2975","-8","1"
+"90248","Gardena","CA","33.870466","-118.28813","-8","1"
+"90249","Gardena","CA","33.899265","-118.319","-8","1"
+"90250","Hawthorne","CA","33.914614","-118.35092","-8","1"
+"90251","Hawthorne","CA","33.786594","-118.298662","-8","1"
+"90254","Hermosa Beach","CA","33.866314","-118.39968","-8","1"
+"90255","Huntington Park","CA","33.978404","-118.21773","-8","1"
+"90260","Lawndale","CA","33.888364","-118.35355","-8","1"
+"90261","Lawndale","CA","33.895363","-118.37689","-8","1"
+"90262","Lynwood","CA","33.924642","-118.20186","-8","1"
+"90263","Malibu","CA","34.035087","-118.70752","-8","1"
+"90264","Malibu","CA","33.786594","-118.298662","-8","1"
+"90265","Malibu","CA","34.051056","-118.80768","-8","1"
+"90266","Manhattan Beach","CA","33.88898","-118.40535","-8","1"
+"90267","Manhattan Beach","CA","33.786594","-118.298662","-8","1"
+"90270","Maywood","CA","33.988813","-118.18642","-8","1"
+"90272","Pacific Palisades","CA","34.050505","-118.53374","-8","1"
+"90274","Palos Verdes Peninsula","CA","33.784099","-118.38752","-8","1"
+"90275","Rancho Palos Verdes","CA","33.758216","-118.36425","-8","1"
+"90276","Redondo Beach","CA","33.845064","-118.395107","-8","1"
+"90277","Redondo Beach","CA","33.828815","-118.38322","-8","1"
+"90278","Redondo Beach","CA","33.871214","-118.37177","-8","1"
+"90280","South Gate","CA","33.944264","-118.1949","-8","1"
+"90290","Topanga","CA","34.101447","-118.59933","-8","1"
+"90291","Venice","CA","33.992411","-118.46531","-8","1"
+"90292","Marina Del Rey","CA","33.976373","-118.45458","-8","1"
+"90293","Playa Del Rey","CA","33.957012","-118.44167","-8","1"
+"90294","Venice","CA","33.786594","-118.298662","-8","1"
+"90295","Marina Del Rey","CA","33.786594","-118.298662","-8","1"
+"90296","Playa Del Rey","CA","33.786594","-118.298662","-8","1"
+"90301","Inglewood","CA","33.955913","-118.35868","-8","1"
+"90302","Inglewood","CA","33.975263","-118.35558","-8","1"
+"90303","Inglewood","CA","33.934164","-118.33255","-8","1"
+"90304","Inglewood","CA","33.936163","-118.36076","-8","1"
+"90305","Inglewood","CA","33.960263","-118.3252","-8","1"
+"90306","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90307","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90308","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90309","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90310","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90311","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90312","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90313","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90397","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90398","Inglewood","CA","33.786594","-118.298662","-8","1"
+"90401","Santa Monica","CA","34.01491","-118.4922","-8","1"
+"90402","Santa Monica","CA","34.036759","-118.50121","-8","1"
+"90403","Santa Monica","CA","34.032159","-118.49022","-8","1"
+"90404","Santa Monica","CA","34.026959","-118.47432","-8","1"
+"90405","Santa Monica","CA","34.009276","-118.47286","-8","1"
+"90406","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90407","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90408","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90409","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90410","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90411","Santa Monica","CA","33.786594","-118.298662","-8","1"
+"90421","Santa Monica","CA","34.010328","-118.494107","-8","1"
+"90501","Torrance","CA","33.828766","-118.31367","-8","1"
+"90502","Torrance","CA","33.833416","-118.29198","-8","1"
+"90503","Torrance","CA","33.840264","-118.35587","-8","1"
+"90504","Torrance","CA","33.870414","-118.33065","-8","1"
+"90505","Torrance","CA","33.810848","-118.35096","-8","1"
+"90506","Torrance","CA","33.786594","-118.298662","-8","1"
+"90507","Torrance","CA","33.786594","-118.298662","-8","1"
+"90508","Torrance","CA","33.786594","-118.298662","-8","1"
+"90509","Torrance","CA","33.786594","-118.298662","-8","1"
+"90510","Torrance","CA","33.786594","-118.298662","-8","1"
+"90601","Whittier","CA","34.002333","-118.03562","-8","1"
+"90602","Whittier","CA","33.967562","-118.03384","-8","1"
+"90603","Whittier","CA","33.941363","-117.99477","-8","1"
+"90604","Whittier","CA","33.929163","-118.009","-8","1"
+"90605","Whittier","CA","33.945413","-118.03362","-8","1"
+"90606","Whittier","CA","33.978312","-118.06778","-8","1"
+"90607","Whittier","CA","33.786594","-118.298662","-8","1"
+"90608","Whittier","CA","33.786594","-118.298662","-8","1"
+"90609","Whittier","CA","33.786594","-118.298662","-8","1"
+"90610","Whittier","CA","33.786594","-118.298662","-8","1"
+"90612","Whittier","CA","33.786594","-118.298662","-8","1"
+"90620","Buena Park","CA","33.841014","-118.00969","-8","1"
+"90621","Buena Park","CA","33.875714","-117.99404","-8","1"
+"90622","Buena Park","CA","33.640302","-117.769442","-8","1"
+"90623","La Palma","CA","33.849327","-118.04395","-8","1"
+"90624","Buena Park","CA","33.640302","-117.769442","-8","1"
+"90630","Cypress","CA","33.817481","-118.0399","-8","1"
+"90631","La Habra","CA","33.934513","-117.95159","-8","1"
+"90632","La Habra","CA","33.640302","-117.769442","-8","1"
+"90633","La Habra","CA","33.640302","-117.769442","-8","1"
+"90637","La Mirada","CA","33.786594","-118.298662","-8","1"
+"90638","La Mirada","CA","33.90213","-118.00966","-8","1"
+"90639","La Mirada","CA","33.905813","-118.018247","-8","1"
+"90640","Montebello","CA","34.014212","-118.11358","-8","1"
+"90650","Norwalk","CA","33.906914","-118.08339","-8","1"
+"90651","Norwalk","CA","33.786594","-118.298662","-8","1"
+"90652","Norwalk","CA","33.786594","-118.298662","-8","1"
+"90659","Norwalk","CA","33.786594","-118.298662","-8","1"
+"90660","Pico Rivera","CA","33.989013","-118.08912","-8","1"
+"90661","Pico Rivera","CA","33.786594","-118.298662","-8","1"
+"90662","Pico Rivera","CA","33.786594","-118.298662","-8","1"
+"90665","Pico Rivera","CA","33.786594","-118.298662","-8","1"
+"90670","Santa Fe Springs","CA","33.933551","-118.06821","-8","1"
+"90671","Santa Fe Springs","CA","33.786594","-118.298662","-8","1"
+"90680","Stanton","CA","33.803565","-117.99596","-8","1"
+"90701","Artesia","CA","33.867215","-118.08062","-8","1"
+"90702","Artesia","CA","33.786594","-118.298662","-8","1"
+"90703","Cerritos","CA","33.868314","-118.06754","-8","1"
+"90704","Avalon","CA","33.368642","-118.40835","-8","1"
+"90706","Bellflower","CA","33.888165","-118.1276","-8","1"
+"90707","Bellflower","CA","33.786594","-118.298662","-8","1"
+"90710","Harbor City","CA","33.797317","-118.30065","-8","1"
+"90711","Lakewood","CA","33.786594","-118.298662","-8","1"
+"90712","Lakewood","CA","33.851965","-118.1468","-8","1"
+"90713","Lakewood","CA","33.847265","-118.11337","-8","1"
+"90714","Lakewood","CA","33.851215","-118.1339","-8","1"
+"90715","Lakewood","CA","33.840965","-118.07775","-8","1"
+"90716","Hawaiian Gardens","CA","33.828565","-118.07364","-8","1"
+"90717","Lomita","CA","33.793384","-118.31611","-8","1"
+"90720","Los Alamitos","CA","33.794028","-118.07218","-8","1"
+"90721","Los Alamitos","CA","33.640302","-117.769442","-8","1"
+"90723","Paramount","CA","33.899915","-118.16231","-8","1"
+"90731","San Pedro","CA","33.732368","-118.28905","-8","1"
+"90732","San Pedro","CA","33.736718","-118.31123","-8","1"
+"90733","San Pedro","CA","33.786594","-118.298662","-8","1"
+"90734","San Pedro","CA","33.786594","-118.298662","-8","1"
+"90740","Seal Beach","CA","33.759283","-118.08239","-8","1"
+"90742","Sunset Beach","CA","33.718167","-118.07179","-8","1"
+"90743","Surfside","CA","33.72975","-118.0863","-8","1"
+"90744","Wilmington","CA","33.784018","-118.25897","-8","1"
+"90745","Carson","CA","33.823765","-118.2668","-8","1"
+"90746","Carson","CA","33.857416","-118.25633","-8","1"
+"90747","Carson","CA","33.867138","-118.253825","-8","1"
+"90748","Wilmington","CA","33.786594","-118.298662","-8","1"
+"90749","Carson","CA","33.786594","-118.298662","-8","1"
+"90755","Long Beach","CA","33.801783","-118.168691","-8","1"
+"90774","Los Angeles","CA","33.783038","-118.238683","-8","1"
+"90801","Long Beach","CA","33.804309","-118.200957","-8","1"
+"90802","Long Beach","CA","33.769018","-118.19225","-8","1"
+"90803","Long Beach","CA","33.761117","-118.12986","-8","1"
+"90804","Long Beach","CA","33.783467","-118.15182","-8","1"
+"90805","Long Beach","CA","33.865916","-118.18362","-8","1"
+"90806","Long Beach","CA","33.801767","-118.1858","-8","1"
+"90807","Long Beach","CA","33.828366","-118.18235","-8","1"
+"90808","Long Beach","CA","33.823316","-118.11329","-8","1"
+"90809","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90810","Long Beach","CA","33.816217","-118.21495","-8","1"
+"90813","Long Beach","CA","33.781011","-118.19197","-8","1"
+"90814","Long Beach","CA","33.771167","-118.14482","-8","1"
+"90815","Long Beach","CA","33.795049","-118.11824","-8","1"
+"90822","Long Beach","CA","33.776094","-118.11848","-8","1"
+"90831","Long Beach","CA","33.767817","-118.199401","-8","1"
+"90832","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90833","Long Beach","CA","33.767817","-118.199401","-8","1"
+"90834","Long Beach","CA","33.767817","-118.199401","-8","1"
+"90835","Long Beach","CA","33.767817","-118.199401","-8","1"
+"90840","Long Beach","CA","33.784266","-118.115698","-8","1"
+"90842","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90844","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90845","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90846","Long Beach","CA","33.824918","-118.150352","-8","1"
+"90847","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90848","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90853","Long Beach","CA","33.786594","-118.298662","-8","1"
+"90879","Rancho Palos Verdes","CA","33.769667","-118.313405","-8","1"
+"90888","Long Beach","CA","33.786594","-118.298662","-8","1"
+"91001","Altadena","CA","34.192102","-118.14206","-8","1"
+"91003","Altadena","CA","33.786594","-118.298662","-8","1"
+"91006","Arcadia","CA","34.134057","-118.02662","-8","1"
+"91007","Arcadia","CA","34.126957","-118.05216","-8","1"
+"91009","Duarte","CA","33.786594","-118.298662","-8","1"
+"91010","Duarte","CA","34.137707","-117.96569","-8","1"
+"91011","La Canada Flintridge","CA","34.211171","-118.19776","-8","1"
+"91012","La Canada Flintridge","CA","33.786594","-118.298662","-8","1"
+"91016","Monrovia","CA","34.140806","-118.00184","-8","1"
+"91017","Monrovia","CA","33.786594","-118.298662","-8","1"
+"91020","Montrose","CA","34.211494","-118.23104","-8","1"
+"91021","Montrose","CA","33.786594","-118.298662","-8","1"
+"91023","Mount Wilson","CA","33.786594","-118.298662","-8","1"
+"91024","Sierra Madre","CA","34.164806","-118.0509","-8","1"
+"91025","Sierra Madre","CA","33.786594","-118.298662","-8","1"
+"91030","South Pasadena","CA","34.112958","-118.15577","-8","1"
+"91031","South Pasadena","CA","33.786594","-118.298662","-8","1"
+"91040","Sunland","CA","34.261221","-118.31887","-8","1"
+"91041","Sunland","CA","33.786594","-118.298662","-8","1"
+"91042","Tujunga","CA","34.256952","-118.28453","-8","1"
+"91043","Tujunga","CA","33.786594","-118.298662","-8","1"
+"91046","Verdugo City","CA","33.786594","-118.298662","-8","1"
+"91050","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91051","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91066","Arcadia","CA","33.786594","-118.298662","-8","1"
+"91077","Arcadia","CA","33.786594","-118.298662","-8","1"
+"91101","Pasadena","CA","34.146607","-118.1391","-8","1"
+"91102","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91103","Pasadena","CA","34.166706","-118.159","-8","1"
+"91104","Pasadena","CA","34.169356","-118.12392","-8","1"
+"91105","Pasadena","CA","34.137857","-118.16329","-8","1"
+"91106","Pasadena","CA","34.142557","-118.12715","-8","1"
+"91107","Pasadena","CA","34.151066","-118.08974","-8","1"
+"91108","San Marino","CA","34.122658","-118.11296","-8","1"
+"91109","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91110","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91114","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91115","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91116","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91117","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91118","San Marino","CA","33.786594","-118.298662","-8","1"
+"91121","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91123","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91124","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91125","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91126","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91129","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91131","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91175","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91182","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91184","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91185","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91186","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91187","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91188","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91189","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91191","Pasadena","CA","33.786594","-118.298662","-8","1"
+"91201","Glendale","CA","34.17013","-118.29158","-8","1"
+"91202","Glendale","CA","34.166567","-118.26994","-8","1"
+"91203","Glendale","CA","34.152757","-118.2658","-8","1"
+"91204","Glendale","CA","34.135259","-118.25948","-8","1"
+"91205","Glendale","CA","34.138514","-118.243","-8","1"
+"91206","Glendale","CA","34.156674","-118.22937","-8","1"
+"91207","Glendale","CA","34.165373","-118.24532","-8","1"
+"91208","Glendale","CA","34.189605","-118.22857","-8","1"
+"91209","Glendale","CA","33.786594","-118.298662","-8","1"
+"91210","Glendale","CA","33.786594","-118.298662","-8","1"
+"91214","La Crescenta","CA","34.232003","-118.24753","-8","1"
+"91221","Glendale","CA","33.786594","-118.298662","-8","1"
+"91222","Glendale","CA","33.786594","-118.298662","-8","1"
+"91224","La Crescenta","CA","33.786594","-118.298662","-8","1"
+"91225","Glendale","CA","33.786594","-118.298662","-8","1"
+"91226","Glendale","CA","33.786594","-118.298662","-8","1"
+"91301","Agoura Hills","CA","34.139536","-118.7607","-8","1"
+"91302","Calabasas","CA","34.133513","-118.66464","-8","1"
+"91303","Canoga Park","CA","34.198204","-118.60206","-8","1"
+"91304","Canoga Park","CA","34.218654","-118.62538","-8","1"
+"91305","Canoga Park","CA","33.786594","-118.298662","-8","1"
+"91306","Winnetka","CA","34.209407","-118.57735","-8","1"
+"91307","West Hills","CA","34.197737","-118.64797","-8","1"
+"91308","West Hills","CA","33.786594","-118.298662","-8","1"
+"91309","Canoga Park","CA","33.786594","-118.298662","-8","1"
+"91310","Castaic","CA","33.786594","-118.298662","-8","1"
+"91311","Chatsworth","CA","34.259052","-118.59426","-8","1"
+"91312","Chatsworth","CA","33.786594","-118.298662","-8","1"
+"91313","Chatsworth","CA","33.786594","-118.298662","-8","1"
+"91316","Encino","CA","34.168753","-118.51636","-8","1"
+"91319","Newbury Park","CA","34.032383","-119.1343","-8","1"
+"91320","Newbury Park","CA","34.175038","-118.93956","-8","1"
+"91321","Newhall","CA","34.377782","-118.51489","-8","1"
+"91322","Newhall","CA","33.786594","-118.298662","-8","1"
+"91324","Northridge","CA","34.240353","-118.55038","-8","1"
+"91325","Northridge","CA","34.235055","-118.51766","-8","1"
+"91326","Northridge","CA","34.276154","-118.54581","-8","1"
+"91327","Northridge","CA","33.786594","-118.298662","-8","1"
+"91328","Northridge","CA","33.786594","-118.298662","-8","1"
+"91329","Northridge","CA","33.786594","-118.298662","-8","1"
+"91330","Northridge","CA","33.786594","-118.298662","-8","1"
+"91331","Pacoima","CA","34.254751","-118.42406","-8","1"
+"91333","Pacoima","CA","33.786594","-118.298662","-8","1"
+"91334","Pacoima","CA","33.786594","-118.298662","-8","1"
+"91335","Reseda","CA","34.200104","-118.54099","-8","1"
+"91337","Reseda","CA","33.786594","-118.298662","-8","1"
+"91340","San Fernando","CA","34.284935","-118.43821","-8","1"
+"91341","San Fernando","CA","33.786594","-118.298662","-8","1"
+"91342","Sylmar","CA","34.307877","-118.42904","-8","1"
+"91343","North Hills","CA","34.239503","-118.48224","-8","1"
+"91344","Granada Hills","CA","34.277648","-118.50047","-8","1"
+"91345","Mission Hills","CA","34.264635","-118.45961","-8","1"
+"91346","Mission Hills","CA","33.786594","-118.298662","-8","1"
+"91350","Santa Clarita","CA","34.481172","-118.42821","-8","1"
+"91351","Canyon Country","CA","34.424794","-118.44513","-8","1"
+"91352","Sun Valley","CA","34.224089","-118.37563","-8","1"
+"91353","Sun Valley","CA","33.786594","-118.298662","-8","1"
+"91354","Valencia","CA","34.445313","-118.55252","-8","1"
+"91355","Valencia","CA","34.406519","-118.56214","-8","1"
+"91356","Tarzana","CA","34.164255","-118.54472","-8","1"
+"91357","Tarzana","CA","33.786594","-118.298662","-8","1"
+"91358","Thousand Oaks","CA","34.032383","-119.1343","-8","1"
+"91359","Westlake Village","CA","34.032383","-119.1343","-8","1"
+"91360","Thousand Oaks","CA","34.208837","-118.87348","-8","1"
+"91361","Westlake Village","CA","34.14348","-118.85608","-8","1"
+"91362","Thousand Oaks","CA","34.190804","-118.83704","-8","1"
+"91363","Westlake Village","CA","33.786594","-118.298662","-8","1"
+"91364","Woodland Hills","CA","34.158214","-118.60061","-8","1"
+"91365","Woodland Hills","CA","33.786594","-118.298662","-8","1"
+"91367","Woodland Hills","CA","34.176238","-118.61992","-8","1"
+"91371","Woodland Hills","CA","33.786594","-118.298662","-8","1"
+"91372","Calabasas","CA","33.786594","-118.298662","-8","1"
+"91376","Agoura Hills","CA","33.786594","-118.298662","-8","1"
+"91377","Oak Park","CA","34.182875","-118.76893","-8","1"
+"91380","Santa Clarita","CA","33.786594","-118.298662","-8","1"
+"91381","Stevenson Ranch","CA","34.384663","-118.58704","-8","1"
+"91382","Santa Clarita","CA","33.786594","-118.298662","-8","1"
+"91383","Santa Clarita","CA","33.786594","-118.298662","-8","1"
+"91384","Castaic","CA","34.478797","-118.65255","-8","1"
+"91385","Valencia","CA","33.786594","-118.298662","-8","1"
+"91386","Canyon Country","CA","33.786594","-118.298662","-8","1"
+"91387","Santa Clarita","CA","34.421537","-118.419181","-8","1"
+"91388","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91390","Santa Clarita","CA","34.490004","-118.300826","-8","1"
+"91392","Sylmar","CA","33.786594","-118.298662","-8","1"
+"91393","North Hills","CA","33.786594","-118.298662","-8","1"
+"91394","Granada Hills","CA","33.786594","-118.298662","-8","1"
+"91395","Mission Hills","CA","33.786594","-118.298662","-8","1"
+"91396","Winnetka","CA","33.786594","-118.298662","-8","1"
+"91399","Woodland Hills","CA","33.786594","-118.298662","-8","1"
+"91401","Van Nuys","CA","34.176505","-118.43308","-8","1"
+"91402","Panorama City","CA","34.223753","-118.44322","-8","1"
+"91403","Sherman Oaks","CA","34.152513","-118.46396","-8","1"
+"91404","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91405","Van Nuys","CA","34.199704","-118.44724","-8","1"
+"91406","Van Nuys","CA","34.201491","-118.49376","-8","1"
+"91407","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91408","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91409","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91410","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91411","Van Nuys","CA","34.178305","-118.45858","-8","1"
+"91412","Panorama City","CA","33.786594","-118.298662","-8","1"
+"91413","Sherman Oaks","CA","33.786594","-118.298662","-8","1"
+"91416","Encino","CA","33.786594","-118.298662","-8","1"
+"91423","Sherman Oaks","CA","34.153628","-118.43222","-8","1"
+"91426","Encino","CA","33.786594","-118.298662","-8","1"
+"91436","Encino","CA","34.155625","-118.48925","-8","1"
+"91470","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91482","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91495","Sherman Oaks","CA","33.786594","-118.298662","-8","1"
+"91496","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91497","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91499","Van Nuys","CA","33.786594","-118.298662","-8","1"
+"91501","Burbank","CA","34.186755","-118.30153","-8","1"
+"91502","Burbank","CA","34.177606","-118.30954","-8","1"
+"91503","Burbank","CA","33.786594","-118.298662","-8","1"
+"91504","Burbank","CA","34.201254","-118.32993","-8","1"
+"91505","Burbank","CA","34.166906","-118.34366","-8","1"
+"91506","Burbank","CA","34.169663","-118.32364","-8","1"
+"91507","Burbank","CA","33.786594","-118.298662","-8","1"
+"91508","Burbank","CA","33.786594","-118.298662","-8","1"
+"91510","Burbank","CA","33.786594","-118.298662","-8","1"
+"91521","Burbank","CA","33.786594","-118.298662","-8","1"
+"91522","Burbank","CA","33.786594","-118.298662","-8","1"
+"91523","Burbank","CA","33.786594","-118.298662","-8","1"
+"91526","Burbank","CA","33.786594","-118.298662","-8","1"
+"91601","North Hollywood","CA","34.168206","-118.37246","-8","1"
+"91602","North Hollywood","CA","34.152476","-118.36841","-8","1"
+"91603","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91604","Studio City","CA","34.143856","-118.39429","-8","1"
+"91605","North Hollywood","CA","34.208142","-118.4011","-8","1"
+"91606","North Hollywood","CA","34.185698","-118.38836","-8","1"
+"91607","Valley Village","CA","34.165706","-118.39986","-8","1"
+"91608","Universal City","CA","34.139397","-118.35034","-8","1"
+"91609","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91610","Toluca Lake","CA","33.786594","-118.298662","-8","1"
+"91611","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91612","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91614","Studio City","CA","33.786594","-118.298662","-8","1"
+"91615","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91616","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91617","Valley Village","CA","33.786594","-118.298662","-8","1"
+"91618","North Hollywood","CA","33.786594","-118.298662","-8","1"
+"91671","Los Angeles","CA","34.175205","-118.382212","-8","1"
+"91701","Alta Loma","CA","34.131659","-117.5924","-8","1"
+"91702","Azusa","CA","34.128907","-117.90309","-8","1"
+"91706","Baldwin Park","CA","34.087108","-117.96966","-8","1"
+"91708","Chino","CA","34.839964","-115.967051","-8","1"
+"91709","Chino Hills","CA","33.975267","-117.72305","-8","1"
+"91710","Chino","CA","34.015963","-117.68737","-8","1"
+"91711","Claremont","CA","34.110009","-117.71973","-8","1"
+"91714","City Of Industry","CA","33.786594","-118.298662","-8","1"
+"91715","City Of Industry","CA","33.786594","-118.298662","-8","1"
+"91716","City Of Industry","CA","33.786594","-118.298662","-8","1"
+"91718","Corona","CA","33.752886","-116.055617","-8","1"
+"91719","Corona","CA","33.735688","-117.42049","-8","1"
+"91720","Corona","CA","33.752886","-116.055617","-8","1"
+"91722","Covina","CA","34.097708","-117.90698","-8","1"
+"91723","Covina","CA","34.085809","-117.88694","-8","1"
+"91724","Covina","CA","34.088771","-117.85817","-8","1"
+"91729","Rancho Cucamonga","CA","34.839964","-115.967051","-8","1"
+"91730","Rancho Cucamonga","CA","34.104555","-117.58734","-8","1"
+"91731","El Monte","CA","34.076642","-118.03942","-8","1"
+"91732","El Monte","CA","34.070659","-118.01383","-8","1"
+"91733","South El Monte","CA","34.05051","-118.04834","-8","1"
+"91734","El Monte","CA","33.786594","-118.298662","-8","1"
+"91735","El Monte","CA","33.786594","-118.298662","-8","1"
+"91737","Alta Loma","CA","34.147849","-117.57847","-8","1"
+"91739","Rancho Cucamonga","CA","34.127819","-117.5246","-8","1"
+"91740","Glendora","CA","34.119245","-117.8548","-8","1"
+"91741","Glendora","CA","34.140207","-117.85704","-8","1"
+"91743","Guasti","CA","34.066655","-117.58831","-8","1"
+"91744","La Puente","CA","34.029561","-117.93975","-8","1"
+"91745","Hacienda Heights","CA","34.000578","-117.96943","-8","1"
+"91746","La Puente","CA","34.046889","-117.98464","-8","1"
+"91747","La Puente","CA","33.786594","-118.298662","-8","1"
+"91748","Rowland Heights","CA","33.985012","-117.89705","-8","1"
+"91749","La Puente","CA","33.786594","-118.298662","-8","1"
+"91750","La Verne","CA","34.117047","-117.77097","-8","1"
+"91752","Mira Loma","CA","34.001846","-117.52759","-8","1"
+"91754","Monterey Park","CA","34.048207","-118.14161","-8","1"
+"91755","Monterey Park","CA","34.05471","-118.11823","-8","1"
+"91756","Monterey Park","CA","33.786594","-118.298662","-8","1"
+"91758","Ontario","CA","34.839964","-115.967051","-8","1"
+"91759","Mt Baldy","CA","34.231581","-117.66106","-8","1"
+"91760","Norco","CA","33.752886","-116.055617","-8","1"
+"91761","Ontario","CA","34.036085","-117.6086","-8","1"
+"91762","Ontario","CA","34.057561","-117.66563","-8","1"
+"91763","Montclair","CA","34.07041","-117.69938","-8","1"
+"91764","Ontario","CA","34.077327","-117.6222","-8","1"
+"91765","Diamond Bar","CA","34.004172","-117.81673","-8","1"
+"91766","Pomona","CA","34.045584","-117.75305","-8","1"
+"91767","Pomona","CA","34.080143","-117.73861","-8","1"
+"91768","Pomona","CA","34.06521","-117.77932","-8","1"
+"91769","Pomona","CA","33.786594","-118.298662","-8","1"
+"91770","Rosemead","CA","34.066143","-118.08475","-8","1"
+"91771","Rosemead","CA","33.786594","-118.298662","-8","1"
+"91772","Rosemead","CA","33.786594","-118.298662","-8","1"
+"91773","San Dimas","CA","34.103341","-117.81814","-8","1"
+"91775","San Gabriel","CA","34.114041","-118.09035","-8","1"
+"91776","San Gabriel","CA","34.089059","-118.0951","-8","1"
+"91778","San Gabriel","CA","33.786594","-118.298662","-8","1"
+"91780","Temple City","CA","34.101608","-118.05606","-8","1"
+"91784","Upland","CA","34.138575","-117.66356","-8","1"
+"91785","Upland","CA","34.839964","-115.967051","-8","1"
+"91786","Upland","CA","34.101659","-117.65776","-8","1"
+"91788","Walnut","CA","33.786594","-118.298662","-8","1"
+"91789","Walnut","CA","34.018361","-117.85438","-8","1"
+"91790","West Covina","CA","34.068059","-117.93835","-8","1"
+"91791","West Covina","CA","34.063645","-117.89743","-8","1"
+"91792","West Covina","CA","34.020711","-117.89932","-8","1"
+"91793","West Covina","CA","33.786594","-118.298662","-8","1"
+"91795","Walnut","CA","33.786594","-118.298662","-8","1"
+"91797","Pomona","CA","33.786594","-118.298662","-8","1"
+"91798","Ontario","CA","34.839964","-115.967051","-8","1"
+"91799","Pomona","CA","33.786594","-118.298662","-8","1"
+"91801","Alhambra","CA","34.090409","-118.127","-8","1"
+"91802","Alhambra","CA","33.786594","-118.298662","-8","1"
+"91803","Alhambra","CA","34.072959","-118.1462","-8","1"
+"91804","Alhambra","CA","33.786594","-118.298662","-8","1"
+"91841","Alhambra","CA","33.786594","-118.298662","-8","1"
+"91896","Alhambra","CA","33.786594","-118.298662","-8","1"
+"91899","Alhambra","CA","33.786594","-118.298662","-8","1"
+"91901","Alpine","CA","32.823102","-116.73864","-8","1"
+"91902","Bonita","CA","32.663803","-117.02456","-8","1"
+"91903","Alpine","CA","33.016928","-116.846046","-8","1"
+"91905","Boulevard","CA","32.672239","-116.31497","-8","1"
+"91906","Campo","CA","32.664307","-116.46513","-8","1"
+"91908","Bonita","CA","33.016928","-116.846046","-8","1"
+"91909","Chula Vista","CA","33.016928","-116.846046","-8","1"
+"91910","Chula Vista","CA","32.638654","-117.06686","-8","1"
+"91911","Chula Vista","CA","32.608799","-117.0607","-8","1"
+"91912","Chula Vista","CA","33.016928","-116.846046","-8","1"
+"91913","Chula Vista","CA","32.642486","-116.98973","-8","1"
+"91914","Chula Vista","CA","32.662563","-116.95413","-8","1"
+"91915","Chula Vista","CA","32.638072","-116.95195","-8","1"
+"91916","Descanso","CA","32.890384","-116.62459","-8","1"
+"91917","Dulzura","CA","32.616539","-116.71187","-8","1"
+"91921","Chula Vista","CA","33.016928","-116.846046","-8","1"
+"91927","La Presa","CA","32.701452","-117.002054","-8","1"
+"91931","Guatay","CA","32.852086","-116.55559","-8","1"
+"91932","Imperial Beach","CA","32.579555","-117.11708","-8","1"
+"91933","Imperial Beach","CA","33.016928","-116.846046","-8","1"
+"91934","Jacumba","CA","32.624424","-116.17025","-8","1"
+"91935","Jamul","CA","32.718186","-116.82606","-8","1"
+"91941","La Mesa","CA","32.761801","-117.01273","-8","1"
+"91942","La Mesa","CA","32.785","-117.0186","-8","1"
+"91943","La Mesa","CA","33.016928","-116.846046","-8","1"
+"91944","La Mesa","CA","33.016928","-116.846046","-8","1"
+"91945","Lemon Grove","CA","32.733451","-117.0337","-8","1"
+"91946","Lemon Grove","CA","33.016928","-116.846046","-8","1"
+"91947","Lincoln Acres","CA","33.016928","-116.846046","-8","1"
+"91948","Mount Laguna","CA","32.875267","-116.42826","-8","1"
+"91950","National City","CA","32.670903","-117.09272","-8","1"
+"91951","National City","CA","33.016928","-116.846046","-8","1"
+"91962","Pine Valley","CA","32.773317","-116.49139","-8","1"
+"91963","Potrero","CA","32.620782","-116.60671","-8","1"
+"91976","Spring Valley","CA","33.016928","-116.846046","-8","1"
+"91977","Spring Valley","CA","32.721145","-116.99612","-8","1"
+"91978","Spring Valley","CA","32.732539","-116.95091","-8","1"
+"91979","Spring Valley","CA","33.016928","-116.846046","-8","1"
+"91980","Tecate","CA","32.588485","-116.63034","-8","1"
+"91987","Tecate","CA","33.016928","-116.846046","-8","1"
+"91990","Potrero","CA","33.016928","-116.846046","-8","1"
+"92002","Carlsbad","CA","33.198032","-117.234701","-8","1"
+"92003","Bonsall","CA","33.289265","-117.20011","-8","1"
+"92004","Borrego Springs","CA","33.184028","-116.26597","-8","1"
+"92007","Cardiff By The Sea","CA","33.026742","-117.27816","-8","1"
+"92008","Carlsbad","CA","33.158137","-117.32646","-8","1"
+"92009","Carlsbad","CA","33.097841","-117.26744","-8","1"
+"92013","Carlsbad","CA","33.016928","-116.846046","-8","1"
+"92014","Del Mar","CA","32.961812","-117.25967","-8","1"
+"92018","Carlsbad","CA","33.016928","-116.846046","-8","1"
+"92019","El Cajon","CA","32.788736","-116.90487","-8","1"
+"92020","El Cajon","CA","32.7991","-116.97334","-8","1"
+"92021","El Cajon","CA","32.8201","-116.91234","-8","1"
+"92022","El Cajon","CA","33.016928","-116.846046","-8","1"
+"92023","Encinitas","CA","33.016928","-116.846046","-8","1"
+"92024","Encinitas","CA","33.053092","-117.26855","-8","1"
+"92025","Escondido","CA","33.106862","-117.07077","-8","1"
+"92026","Escondido","CA","33.181543","-117.11136","-8","1"
+"92027","Escondido","CA","33.142706","-117.03049","-8","1"
+"92028","Fallbrook","CA","33.380359","-117.20605","-8","1"
+"92029","Escondido","CA","33.087868","-117.11558","-8","1"
+"92030","Escondido","CA","33.016928","-116.846046","-8","1"
+"92031","Adelanto","CA","34.587473","-117.406293","-8","1"
+"92033","Escondido","CA","33.016928","-116.846046","-8","1"
+"92036","Julian","CA","33.02757","-116.53109","-8","1"
+"92037","La Jolla","CA","32.838761","-117.26159","-8","1"
+"92038","La Jolla","CA","33.016928","-116.846046","-8","1"
+"92039","La Jolla","CA","33.016928","-116.846046","-8","1"
+"92040","Lakeside","CA","32.873849","-116.90477","-8","1"
+"92046","Escondido","CA","33.016928","-116.846046","-8","1"
+"92049","Oceanside","CA","33.016928","-116.846046","-8","1"
+"92051","Oceanside","CA","33.016928","-116.846046","-8","1"
+"92052","Oceanside","CA","33.016928","-116.846046","-8","1"
+"92054","Oceanside","CA","33.202463","-117.36077","-8","1"
+"92055","Camp Pendleton","CA","33.016928","-116.846046","-8","1"
+"92056","Oceanside","CA","33.195354","-117.28232","-8","1"
+"92057","Oceanside","CA","33.240926","-117.29851","-8","1"
+"92058","Oceanside","CA","33.016928","-116.846046","-8","1"
+"92059","Pala","CA","33.369249","-117.07236","-8","1"
+"92060","Palomar Mountain","CA","33.308217","-116.8471","-8","1"
+"92061","Pauma Valley","CA","33.311881","-116.96499","-8","1"
+"92064","Poway","CA","32.973645","-117.03701","-8","1"
+"92065","Ramona","CA","33.035844","-116.8513","-8","1"
+"92066","Ranchita","CA","33.209313","-116.54244","-8","1"
+"92067","Rancho Santa Fe","CA","33.016492","-117.20264","-8","1"
+"92068","San Luis Rey","CA","33.016928","-116.846046","-8","1"
+"92069","San Marcos","CA","33.144908","-117.17128","-8","1"
+"92070","Santa Ysabel","CA","33.166768","-116.71061","-8","1"
+"92071","Santee","CA","32.84681","-116.98983","-8","1"
+"92072","Santee","CA","33.016928","-116.846046","-8","1"
+"92074","Poway","CA","33.016928","-116.846046","-8","1"
+"92075","Solana Beach","CA","32.997543","-117.26087","-8","1"
+"92078","San Marcos","CA","33.122029","-117.15605","-8","1"
+"92079","San Marcos","CA","33.016928","-116.846046","-8","1"
+"92082","Valley Center","CA","33.261748","-117.01027","-8","1"
+"92083","Vista","CA","33.179587","-117.24461","-8","1"
+"92084","Vista","CA","33.213309","-117.21474","-8","1"
+"92085","Vista","CA","33.016928","-116.846046","-8","1"
+"92086","Warner Springs","CA","33.337152","-116.69355","-8","1"
+"92088","Fallbrook","CA","33.016928","-116.846046","-8","1"
+"92090","El Cajon","CA","33.016928","-116.846046","-8","1"
+"92091","Rancho Santa Fe","CA","32.993541","-117.21311","-8","1"
+"92092","La Jolla","CA","33.016928","-116.846046","-8","1"
+"92093","La Jolla","CA","33.016928","-116.846046","-8","1"
+"92096","San Marcos","CA","33.016928","-116.846046","-8","1"
+"92101","San Diego","CA","32.719601","-117.16246","-8","1"
+"92102","San Diego","CA","32.714992","-117.12537","-8","1"
+"92103","San Diego","CA","32.746018","-117.16715","-8","1"
+"92104","San Diego","CA","32.742892","-117.12774","-8","1"
+"92105","San Diego","CA","32.741256","-117.0951","-8","1"
+"92106","San Diego","CA","32.7259","-117.23079","-8","1"
+"92107","San Diego","CA","32.7409","-117.24434","-8","1"
+"92108","San Diego","CA","32.7736","-117.13785","-8","1"
+"92109","San Diego","CA","32.791246","-117.24343","-8","1"
+"92110","San Diego","CA","32.766482","-117.20077","-8","1"
+"92111","San Diego","CA","32.804972","-117.16871","-8","1"
+"92112","San Diego","CA","33.016928","-116.846046","-8","1"
+"92113","San Diego","CA","32.697402","-117.12001","-8","1"
+"92114","San Diego","CA","32.706954","-117.0542","-8","1"
+"92115","San Diego","CA","32.7603","-117.07031","-8","1"
+"92116","San Diego","CA","32.76235","-117.12246","-8","1"
+"92117","San Diego","CA","32.823865","-117.19966","-8","1"
+"92118","Coronado","CA","32.682727","-117.17441","-8","1"
+"92119","San Diego","CA","32.80225","-117.02431","-8","1"
+"92120","San Diego","CA","32.794449","-117.07221","-8","1"
+"92121","San Diego","CA","32.899996","-117.20722","-8","1"
+"92122","San Diego","CA","32.856447","-117.21143","-8","1"
+"92123","San Diego","CA","32.803799","-117.13595","-8","1"
+"92124","San Diego","CA","32.822815","-117.09844","-8","1"
+"92126","San Diego","CA","32.914346","-117.14116","-8","1"
+"92127","San Diego","CA","33.022384","-117.10694","-8","1"
+"92128","San Diego","CA","32.998855","-117.07054","-8","1"
+"92129","San Diego","CA","32.961014","-117.1251","-8","1"
+"92130","San Diego","CA","32.946776","-117.21918","-8","1"
+"92131","San Diego","CA","32.918035","-117.08438","-8","1"
+"92132","San Diego","CA","32.643703","-117.138414","-7","1"
+"92133","San Diego","CA","32.733507","-117.216451","-8","1"
+"92134","San Diego","CA","32.562106","-117.07166","-8","1"
+"92135","San Diego","CA","33.016928","-116.846046","-8","1"
+"92136","San Diego","CA","32.68342","-117.121913","-8","1"
+"92137","San Diego","CA","32.85377","-117.119744","-8","1"
+"92138","San Diego","CA","33.016928","-116.846046","-8","1"
+"92139","San Diego","CA","32.677286","-117.05241","-8","1"
+"92140","San Diego","CA","32.74344","-117.200412","-8","1"
+"92142","San Diego","CA","33.016928","-116.846046","-8","1"
+"92143","San Ysidro","CA","33.016928","-116.846046","-8","1"
+"92145","San Diego","CA","32.889139","-117.100486","-8","1"
+"92147","San Diego","CA","33.016928","-116.846046","-8","1"
+"92149","San Diego","CA","33.016928","-116.846046","-8","1"
+"92150","San Diego","CA","33.016928","-116.846046","-8","1"
+"92152","San Diego","CA","33.016928","-116.846046","-8","1"
+"92153","San Diego","CA","33.016928","-116.846046","-8","1"
+"92154","San Diego","CA","32.574398","-117.05633","-8","1"
+"92155","San Diego","CA","32.671602","-117.165665","-8","1"
+"92158","San Diego","CA","33.016928","-116.846046","-8","1"
+"92159","San Diego","CA","33.016928","-116.846046","-8","1"
+"92160","San Diego","CA","33.016928","-116.846046","-8","1"
+"92161","San Diego","CA","32.871846","-117.229119","-8","1"
+"92162","San Diego","CA","33.016928","-116.846046","-8","1"
+"92163","San Diego","CA","33.016928","-116.846046","-8","1"
+"92164","San Diego","CA","33.016928","-116.846046","-8","1"
+"92165","San Diego","CA","33.016928","-116.846046","-8","1"
+"92166","San Diego","CA","33.016928","-116.846046","-8","1"
+"92167","San Diego","CA","33.016928","-116.846046","-8","1"
+"92168","San Diego","CA","33.016928","-116.846046","-8","1"
+"92169","San Diego","CA","33.016928","-116.846046","-8","1"
+"92170","San Diego","CA","33.016928","-116.846046","-8","1"
+"92171","San Diego","CA","33.016928","-116.846046","-8","1"
+"92172","San Diego","CA","33.016928","-116.846046","-8","1"
+"92173","San Ysidro","CA","32.556264","-117.05057","-8","1"
+"92174","San Diego","CA","33.016928","-116.846046","-8","1"
+"92175","San Diego","CA","33.016928","-116.846046","-8","1"
+"92176","San Diego","CA","33.016928","-116.846046","-8","1"
+"92177","San Diego","CA","33.016928","-116.846046","-8","1"
+"92178","Coronado","CA","33.016928","-116.846046","-8","1"
+"92179","San Diego","CA","32.572602","-116.918724","-8","1"
47 test/test.py
View
@@ -3,43 +3,72 @@
import redis
from provider.geonames import GeonamesImporter
from provider.ip2location import IP2LocationImporter
-from location import Location
+from provider.zipcodes import ZIPImporter
+
+
+from city import City
from iprange import IPRange
+from zipcode import ZIPCode
class TestProvidersTestCase(unittest.TestCase):
def setUp(self):
self.redisHost = 'localhost'
self.redisPort = 6379
+ self.redisDB = 0
def test1_ImportGeonames(self):
- importer = GeonamesImporter('./data/locations.csv', self.redisHost, self.redisPort)
- self.assertTrue(importer.runImport() > 0, 'Could not import locations csv')
+ importer = GeonamesImporter('./data/locations.csv', self.redisHost, self.redisPort, self.redisDB)
+ self.assertTrue(importer.runImport() > 0, 'Could not import cities csv')
def test2_ImportIP2Location(self):
- importer = IP2LocationImporter('./data/ip2location.csv', self.redisHost, self.redisPort)
+ importer = IP2LocationImporter('./data/ip2location.csv', self.redisHost, self.redisPort, self.redisDB)
self.assertTrue(importer.runImport() > 0, 'Could not import ip ranges csv')
- def test3_resolve(self):
- r = redis.Redis(self.redisHost, self.redisPort)
+
+ def test3_ImportZIP(self):
+
+ importer = ZIPImporter('./data/zipcodes.csv', self.redisHost, self.redisPort, self.redisDB)
+ self.assertTrue(importer.runImport() > 0, 'Could not import zipcodes csv')
+
+ def test4_resolve(self):
+ r = redis.Redis(self.redisHost, self.redisPort, self.redisDB)
#resolve by coords
- loc = Location.getByLatLon(34.05,-118.24, r)
+ loc = City.getByLatLon(34.05223, -118.24368, r)
self.assertTrue(loc is not None)
self.assertTrue(loc.country == 'United States')
self.assertTrue(loc.state == 'CA' or loc.state == 'California')
#resolve by ip
- ip = '4.3.32.1'
+ ip = '4.3.68.1'
- loc = IPRange.getLocation(ip, r)
+ loc = IPRange.getCity(ip, r)
+
self.assertTrue(loc is not None)
self.assertTrue(loc.country == 'United States')
self.assertTrue(loc.state == 'CA' or loc.state == 'California')
+
+ #resolve zip by lat,lon
+ loc = ZIPCode.getByLatLon(34.0452, -118.284, r)
+
+ self.assertTrue(loc is not None)
+ self.assertTrue(loc.name == '90006')
+ self.assertTrue(loc.country == 'United States')
+ self.assertTrue(loc.state == 'CA' or loc.state == 'California')
+
+ #resolve zip bu ip
+ loc = IPRange.getZIP(ip, r)
+ self.assertTrue(loc is not None)
+ self.assertTrue(loc.name == '90001')
+ self.assertTrue(loc.country == 'United States')
+ self.assertTrue(loc.state == 'CA' or loc.state == 'California')
+
+
if __name__ == '__main__':
unittest.main()
Please sign in to comment.
Something went wrong with that request. Please try again.