Statistics
| Revision:

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()