gvsig-scripting / org.gvsig.scripting / trunk / org.gvsig.scripting / org.gvsig.scripting.app / org.gvsig.scripting.app.mainplugin / src / main / resources-plugin / scripting / lib / geopy / geocoders / base.py @ 545
History | View | Annotate | Download (5.4 KB)
1 |
"""
|
---|---|
2 |
:class:`.GeoCoder` base object from which other geocoders are templated.
|
3 |
"""
|
4 |
|
5 |
from socket import timeout as SocketTimeout |
6 |
import simplejson as json |
7 |
|
8 |
from geopy.compat import ( |
9 |
string_compare, |
10 |
HTTPError, |
11 |
py3k, |
12 |
urlopen as urllib_urlopen,
|
13 |
build_opener, |
14 |
ProxyHandler, |
15 |
URLError, |
16 |
install_opener, |
17 |
) |
18 |
from geopy.point import Point |
19 |
from geopy.exc import ( |
20 |
GeocoderServiceError, |
21 |
ConfigurationError, |
22 |
GeocoderTimedOut, |
23 |
GeocoderAuthenticationFailure, |
24 |
GeocoderQuotaExceeded, |
25 |
GeocoderQueryError, |
26 |
GeocoderInsufficientPrivileges, |
27 |
GeocoderUnavailable, |
28 |
GeocoderParseError, |
29 |
) |
30 |
from geopy.util import decode_page |
31 |
|
32 |
|
33 |
__all__ = ( |
34 |
"Geocoder",
|
35 |
"DEFAULT_FORMAT_STRING",
|
36 |
"DEFAULT_SCHEME",
|
37 |
"DEFAULT_TIMEOUT",
|
38 |
"DEFAULT_WKID",
|
39 |
) |
40 |
|
41 |
|
42 |
DEFAULT_FORMAT_STRING = '%s'
|
43 |
DEFAULT_SCHEME = 'https'
|
44 |
DEFAULT_TIMEOUT = 1
|
45 |
DEFAULT_WKID = 4326
|
46 |
|
47 |
ERROR_CODE_MAP = { |
48 |
400: GeocoderQueryError,
|
49 |
401: GeocoderAuthenticationFailure,
|
50 |
402: GeocoderQuotaExceeded,
|
51 |
403: GeocoderInsufficientPrivileges,
|
52 |
407: GeocoderAuthenticationFailure,
|
53 |
412: GeocoderQueryError,
|
54 |
413: GeocoderQueryError,
|
55 |
414: GeocoderQueryError,
|
56 |
502: GeocoderServiceError,
|
57 |
503: GeocoderTimedOut,
|
58 |
504: GeocoderTimedOut
|
59 |
} |
60 |
|
61 |
|
62 |
class Geocoder(object): # pylint: disable=R0921 |
63 |
"""
|
64 |
Template object for geocoders.
|
65 |
"""
|
66 |
|
67 |
def __init__( |
68 |
self,
|
69 |
format_string=DEFAULT_FORMAT_STRING, |
70 |
scheme=DEFAULT_SCHEME, |
71 |
timeout=DEFAULT_TIMEOUT, |
72 |
proxies=None
|
73 |
): |
74 |
"""
|
75 |
Mostly-common geocoder validation, proxies, &c. Not all geocoders
|
76 |
specify format_string and such.
|
77 |
"""
|
78 |
self.format_string = format_string
|
79 |
self.scheme = scheme
|
80 |
if self.scheme not in ('http', 'https'): # pragma: no cover |
81 |
raise ConfigurationError(
|
82 |
'Supported schemes are `http` and `https`.'
|
83 |
) |
84 |
self.proxies = proxies
|
85 |
self.timeout = timeout
|
86 |
|
87 |
if self.proxies: |
88 |
install_opener( |
89 |
build_opener( |
90 |
ProxyHandler(self.proxies)
|
91 |
) |
92 |
) |
93 |
self.urlopen = urllib_urlopen
|
94 |
|
95 |
@staticmethod
|
96 |
def _coerce_point_to_string(point): |
97 |
"""
|
98 |
Do the right thing on "point" input. For geocoders with reverse
|
99 |
methods.
|
100 |
"""
|
101 |
if isinstance(point, Point): |
102 |
return ",".join((str(point.latitude), str(point.longitude))) |
103 |
elif isinstance(point, (list, tuple)): |
104 |
return ",".join((str(point[0]), str(point[1]))) # -altitude |
105 |
elif isinstance(point, string_compare): |
106 |
return point
|
107 |
else: # pragma: no cover |
108 |
raise ValueError("Invalid point") |
109 |
|
110 |
def _parse_json(self, page, exactly_one): # pragma: no cover |
111 |
"""
|
112 |
Template for subclasses
|
113 |
"""
|
114 |
raise NotImplementedError() |
115 |
|
116 |
def _call_geocoder( |
117 |
self,
|
118 |
url, |
119 |
timeout=None,
|
120 |
raw=False,
|
121 |
requester=None,
|
122 |
deserializer=json.loads, |
123 |
**kwargs |
124 |
): |
125 |
"""
|
126 |
For a generated query URL, get the results.
|
127 |
"""
|
128 |
requester = requester or self.urlopen |
129 |
|
130 |
try:
|
131 |
#page = requester(url, timeout=(timeout or self.timeout), **kwargs)
|
132 |
page = requester(url, **kwargs) |
133 |
except Exception,error: # pylint: disable=W0703 |
134 |
message = ( |
135 |
str(error) if not py3k |
136 |
else (
|
137 |
str(error.args[0]) |
138 |
if len(error.args) |
139 |
else str(error) |
140 |
) |
141 |
) |
142 |
if hasattr(self, '_geocoder_exception_handler'): |
143 |
self._geocoder_exception_handler(error, message) # pylint: disable=E1101 |
144 |
if isinstance(error, HTTPError): |
145 |
code = error.getcode() |
146 |
try:
|
147 |
raise ERROR_CODE_MAP[code](message)
|
148 |
except KeyError: |
149 |
raise GeocoderServiceError(message)
|
150 |
elif isinstance(error, URLError): |
151 |
if "timed out" in message: |
152 |
raise GeocoderTimedOut('Service timed out') |
153 |
elif "unreachable" in message: |
154 |
raise GeocoderUnavailable('Service not available') |
155 |
elif isinstance(error, SocketTimeout): |
156 |
raise GeocoderTimedOut('Service timed out') |
157 |
raise GeocoderServiceError(message)
|
158 |
|
159 |
if hasattr(page, 'getcode'): |
160 |
status_code = page.getcode() |
161 |
elif hasattr(page, 'status_code'): |
162 |
status_code = page.status_code |
163 |
else:
|
164 |
status_code = None
|
165 |
if status_code in ERROR_CODE_MAP: |
166 |
raise ERROR_CODE_MAP[page.status_code]("\n%s" % decode_page(page)) |
167 |
|
168 |
if raw:
|
169 |
return page
|
170 |
|
171 |
page = decode_page(page) |
172 |
|
173 |
if deserializer is not None: |
174 |
try:
|
175 |
return deserializer(page)
|
176 |
except ValueError: |
177 |
raise GeocoderParseError(
|
178 |
"Could not deserialize using deserializer:\n%s" % page
|
179 |
) |
180 |
else:
|
181 |
return page
|
182 |
|
183 |
def geocode(self, query, exactly_one=True, timeout=None): |
184 |
"""
|
185 |
Implemented in subclasses.
|
186 |
"""
|
187 |
raise NotImplementedError() |
188 |
|
189 |
def reverse(self, query, exactly_one=True, timeout=None): |
190 |
"""
|
191 |
Implemented in subclasses.
|
192 |
"""
|
193 |
raise NotImplementedError() |