diff --git a/.travis.yml b/.travis.yml index 09d899c..ff877ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ sudo: false python: - '2.7' + - '3.6' script: - python setup.py test @@ -15,5 +16,6 @@ deploy: secure: Wc/aboeIntZeqgCSIOrd/66vceukY/KmdSLwcLB9gn7kRWRqOM+HiEX9+lJe4IKtMisz3zgRqZNAFJU/UUBBwuclHpbtQtV0FCQOFXEwUHQfouzAvVu/3C4fBgQeoet5KrJFo7OVUmYwyWPm8vJzWIraQWVfsR9Gv/AQBQdfuec= on: tags: true + python: '3.6' distributions: sdist bdist_wheel repo: azavea/python-omgeo diff --git a/CHANGES.rst b/CHANGES.rst index 8dfa642..5c22323 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -49,7 +49,7 @@ v1.3.4, 2012-05-11 * Add test for SnapPoints postprocessor. * Change __unicode__() method for places.Candidate to display info indicating null or empty values, instead of just displaying "None". - + v1.3.5, 2012-05-21 ------------------ * Geocoder().geocode() method can take one-line string OR PlaceQuery instance. @@ -60,11 +60,11 @@ v1.3.6, 2012-05-22 ------------------ * Add SSH support for MapQuest * Add CancelIfRegexInAttr preprocessor to avoid geocoding attempts if - a PlaceQuery instance attribute matches the given regex (such as a + a PlaceQuery instance attribute matches the given regex (such as a PO Box) * Add timeout option that can be included in the GeocodeService settings parameter. There is now a default timeout of 10 seconds. - + v1.3.7, 2012-05-23 ------------------ * Add CancelIfPOBox preprocessor and tests @@ -145,7 +145,7 @@ v1.6.0, 2013-10-31 * Add subregion and neighborhood parameters to queries * Allow HTTP request headers to be specified in geocoder settings * Documentation updates - + v1.7.0, 2014-05-12 ------------------ * Add Census geocoder diff --git a/README.rst b/README.rst index f2d1b33..9fedd96 100644 --- a/README.rst +++ b/README.rst @@ -20,15 +20,15 @@ supported geocoders: **Documentation** -Docs are available in `HTML `_ +Docs are available in `HTML `_ or `PDF `_ format. **Usage Example** Make a new geocoder and geocode and address:: - >>> from omgeo import Geocoder - >>> g = Geocoder() + >>> from omgeo import Geocoder + >>> g = Geocoder() >>> result = g.geocode('340 12th St, Philadelphia PA') Take a look at the result:: diff --git a/omgeo/geocoder.py b/omgeo/geocoder.py index bf533a9..ddd61a2 100644 --- a/omgeo/geocoder.py +++ b/omgeo/geocoder.py @@ -98,7 +98,7 @@ def geocode(self, pq, waterfall=None, force_stats_logging=False): start_time = time.time() waterfall = self.waterfall if waterfall is None else waterfall - if type(pq) in (str, unicode): + if type(pq) in (str, str): pq = PlaceQuery(pq) processed_pq = copy.copy(pq) diff --git a/omgeo/places.py b/omgeo/places.py index efcb224..d7c9bbd 100644 --- a/omgeo/places.py +++ b/omgeo/places.py @@ -16,13 +16,13 @@ def __init__(self, left=-180, top=90, right=180, bottom=-90, wkid=4326): :arg wkid: Well-known ID for spatial reference system (default ``4326``) """ bounds = left, right, bottom, top - if not all([isinstance(x, (int, long, float)) for x in bounds]): + if not all([isinstance(x, (int, float)) for x in bounds]): raise ValueError('One or more bounds (%s) is not a real number.' % bounds) if left > right: raise ValueError('Left x-coord must be less than right x-coord.') if bottom > top: raise ValueError('Bottom y-coord must be less than top y-coord.') - for k in locals().keys(): + for k in list(locals().keys()): if k != 'self': setattr(self, k, locals()[k]) @@ -150,7 +150,7 @@ def __init__(self, query='', address='', neighborhood='', city='', would be returned as "Vereinigte Staaten Von Amerika" instead of "United States". """ - for k in locals().keys(): + for k in list(locals().keys()): if k not in ['self', 'kwargs']: setattr(self, k, locals()[k]) if query == '' and address == '' and city == '' and state == '' and postal == '': @@ -206,7 +206,7 @@ def __init__(self, locator='', score=0, match_addr='', x=None, y=None, return these values. """ - for k in locals().keys(): + for k in list(locals().keys()): if k not in ['self', 'kwargs']: setattr(self, k, locals()[k]) for k in kwargs: diff --git a/omgeo/postprocessors.py b/omgeo/postprocessors.py index 9db910f..cfc9ce5 100644 --- a/omgeo/postprocessors.py +++ b/omgeo/postprocessors.py @@ -403,7 +403,7 @@ def __init__(self, attr_dupes, attr_sort, ordered_list, return_clean=False): def process(self, candidates): def cleanup(str_): """Returns string in uppercase and free of commas.""" - if type(str_) in [str, unicode]: + if type(str_) in [str, str]: return str_.replace(',', '').upper() return str_ diff --git a/omgeo/preprocessors.py b/omgeo/preprocessors.py index 89e879d..4348747 100644 --- a/omgeo/preprocessors.py +++ b/omgeo/preprocessors.py @@ -200,14 +200,14 @@ def __init__(self, regex, attrs, ignorecase=True): :arg bool ignorecase: set to ``False`` for a case-sensitive match (default ``True``) """ regex_type = type(regex) - if type(regex) not in (str, unicode): + if type(regex) not in (str, str): raise Exception('First param "regex" must be a regex of type' ' str or unicode, not %s.' % regex_type) attrs_type = type(attrs) if attrs_type not in (list, tuple): raise Exception('Second param "attrs" must be a list or tuple' ' of PlaceQuery attributes, not %s.' % attrs_type) - if any(type(attr) not in (str, unicode) for attr in attrs): + if any(type(attr) not in (str, str) for attr in attrs): raise Exception('All given PlaceQuery attributes must be strings.') self.attrs = attrs if ignorecase: diff --git a/omgeo/services/base.py b/omgeo/services/base.py index 1ee4703..7bb2dab 100644 --- a/omgeo/services/base.py +++ b/omgeo/services/base.py @@ -4,10 +4,17 @@ import logging import socket from traceback import format_exc -from urllib import urlencode -from urllib2 import urlopen, Request from xml.dom import minidom +try: + # python 3 + from urllib.parse import urlencode + from urllib.request import urlopen, Request +except ImportError: + # python 2 + from urllib import urlencode + from urllib2 import urlopen, Request + logger = logging.getLogger(__name__) diff --git a/omgeo/services/bing.py b/omgeo/services/bing.py index 5c35e33..8fd58e7 100644 --- a/omgeo/services/bing.py +++ b/omgeo/services/bing.py @@ -1,4 +1,4 @@ -from base import GeocodeService +from .base import GeocodeService import logging from omgeo.places import Candidate from omgeo.preprocessors import ReplaceRangeWithNumber diff --git a/omgeo/services/google.py b/omgeo/services/google.py index 7c65ae5..3679036 100644 --- a/omgeo/services/google.py +++ b/omgeo/services/google.py @@ -54,7 +54,7 @@ def _make_candidate_from_result(self, result): 'postal': {'type': 'postal_code', 'key': 'long_name'}, 'country': {'type': 'country', 'key': 'short_name'}, } - for (field, lookup) in component_lookups.iteritems(): + for (field, lookup) in component_lookups.items(): setattr(candidate, 'match_' + field, self._get_component_from_result(result, lookup)) candidate.geoservice = self.__class__.__name__ return candidate diff --git a/omgeo/services/mapquest.py b/omgeo/services/mapquest.py index 1155c4e..ebc211c 100644 --- a/omgeo/services/mapquest.py +++ b/omgeo/services/mapquest.py @@ -1,8 +1,14 @@ -from base import GeocodeService +from .base import GeocodeService import json import logging from omgeo.places import Candidate -from urllib import unquote + +try: + # python 3 + from urllib.parse import unquote +except ImportError: + # python 2 + from urllib import unquote logger = logging.getLogger(__name__) diff --git a/omgeo/services/mapzen.py b/omgeo/services/mapzen.py index dfd8d79..e6abb55 100644 --- a/omgeo/services/mapzen.py +++ b/omgeo/services/mapzen.py @@ -1,10 +1,16 @@ -from base import GeocodeService +from .base import GeocodeService import logging from omgeo.places import Candidate from omgeo.preprocessors import ReplaceRangeWithNumber -from urlparse import urljoin from posixpath import join as posixjoin +try: + # python 3 + from urllib.parse import urljoin +except ImportError: + # python 2 + from urlparse import urljoin + logger = logging.getLogger(__name__) diff --git a/omgeo/services/nominatim.py b/omgeo/services/nominatim.py index 7be6f62..11c31bb 100644 --- a/omgeo/services/nominatim.py +++ b/omgeo/services/nominatim.py @@ -1,4 +1,4 @@ -from base import GeocodeService +from .base import GeocodeService import logging from omgeo.places import Candidate from omgeo.preprocessors import ReplaceRangeWithNumber diff --git a/omgeo/services/us_census.py b/omgeo/services/us_census.py index 8704769..cb76c26 100644 --- a/omgeo/services/us_census.py +++ b/omgeo/services/us_census.py @@ -1,6 +1,6 @@ import re -from base import GeocodeService +from .base import GeocodeService import logging from omgeo.places import Candidate diff --git a/omgeo/tests/tests.py b/omgeo/tests/tests.py index e10dab0..610c99d 100755 --- a/omgeo/tests/tests.py +++ b/omgeo/tests/tests.py @@ -314,11 +314,10 @@ def _test_geocode_results_all_(self, verbosity=0, geocoder=Geocoder(), else: queries_with_results += 1 logger.info('Input: %s' % self.pq[place].query) - logger.info(map(lambda c: 'Output: %r (%s %s)\n' % + logger.info(['Output: %r (%s %s)\n' % (c.match_addr, c.geoservice, - [c.locator, c.score, c.confidence, c.entity]), - candidates)) + [c.locator, c.score, c.confidence, c.entity]) for c in candidates]) self.assertEqual(expected_results, queries_with_results, 'Got results for %d of %d queries.' % (queries_with_results, len(self.pq))) @@ -343,7 +342,7 @@ def test_google_geocode_multipart(self): @unittest.skipIf(GOOGLE_API_KEY is None, GOOGLE_KEY_REQUIRED_MSG) def test_google_country_filter(self): - candidates = self.g_google.get_candidates('York') + candidates = self.g_google.get_candidates(PlaceQuery('York', country='US')) self.assertOneCandidate(candidates) self.assertEqual(candidates[0].match_region, 'PA') candidates = self.g_google.get_candidates(PlaceQuery('York', country='UK')) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/sphinx/conf.py b/sphinx/conf.py index 32757a6..752561b 100644 --- a/sphinx/conf.py +++ b/sphinx/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'python-omgeo' -copyright = u'2012-2013 Azavea' +project = 'python-omgeo' +copyright = '2012-2013 Azavea' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -185,8 +185,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'python-omgeo.tex', u'python-omgeo Documentation', - u'Azavea Inc.', 'manual'), + ('index', 'python-omgeo.tex', 'python-omgeo Documentation', + 'Azavea Inc.', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -215,8 +215,8 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'python-omgeo', u'python-omgeo Documentation', - [u'Andrew Jennings, Joseph Tricarico, Justin Walgran'], 1) + ('index', 'python-omgeo', 'python-omgeo Documentation', + ['Andrew Jennings, Joseph Tricarico, Justin Walgran'], 1) ] # If true, show URL addresses after external links. @@ -229,8 +229,8 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'python-omgeo', u'python-omgeo Documentation', - u'Andrew Jennings, Joseph Tricarico, Justin Walgran', 'python-omgeo', 'One line description of project.', + ('index', 'python-omgeo', 'python-omgeo Documentation', + 'Andrew Jennings, Joseph Tricarico, Justin Walgran', 'python-omgeo', 'One line description of project.', 'Miscellaneous'), ]