This file is indexed.

/usr/lib/python3/dist-packages/geopy/geocoders/photon.py is in python3-geopy 1.11.0+ds1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
"""
:class:`.Photon` geocoder.
"""

from geopy.compat import urlencode, string_compare
from geopy.geocoders.base import (
    Geocoder,
    DEFAULT_FORMAT_STRING,
    DEFAULT_TIMEOUT,
    DEFAULT_SCHEME
)
from geopy.location import Location
from geopy.util import logger


__all__ = ("Photon", )


class Photon(Geocoder):  # pylint: disable=W0223
    """
    Geocoder using Photon geocoding service (data based on OpenStreetMap and
    service provided by Komoot on https://photon.komoot.de).
    Documentation at https://github.com/komoot/photon
    """

    def __init__(
            self,
            format_string=DEFAULT_FORMAT_STRING,
            scheme=DEFAULT_SCHEME,
            timeout=DEFAULT_TIMEOUT,
            proxies=None,
            domain='photon.komoot.de'
    ):   # pylint: disable=R0913
        """
        Initialize a Photon/Komoot geocoder which aims to let you "search as
        you type with OpenStreetMap". No API Key is needed by this platform.

        :param string format_string: String containing '%s' where
            the string to geocode should be interpolated before querying
            the geocoder. For example: '%s, Mountain View, CA'. The default
            is just '%s'.

        :param string scheme: Use 'https' or 'http' as the API URL's scheme.
            Default is https. Note that SSL connections' certificates are not
            verified.

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception.

        :param dict proxies: If specified, routes this geocoder's requests
            through the specified proxy. E.g., {"https": "192.0.2.0"}. For
            more information, see documentation on
            :class:`urllib2.ProxyHandler`.

        :param string domain: Should be the localized Photon domain to
            connect to. The default is 'photon.komoot.de', but you
            can change it to a domain of your own.
        """
        super(Photon, self).__init__(
            format_string, scheme, timeout, proxies
        )
        self.domain = domain.strip('/')
        self.api = "%s://%s/api" % (self.scheme, self.domain)
        self.reverse_api = "%s://%s/reverse" % (self.scheme, self.domain)

    def geocode(
            self,
            query,
            exactly_one=True,
            timeout=None,
            location_bias=None,
            language=False,
            osm_tag=None
        ):  # pylint: disable=W0221
        """
        Geocode a location query.

        :param string query: The address or query you wish to geocode.

        :param bool exactly_one: Return one result or a list of results, if
            available.

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

        :param location_bias: The coordinates to used as location bias.
        :type query: :class:`geopy.point.Point`, list or tuple of (latitude,
            longitude), or string as "%(latitude)s, %(longitude)s"

        :param string language: Preferred language in which to return results.

        :param osm_tag: The expression to filter (include/exclude) by key and/
            or value, str as 'key:value' or list/set of str if multiple filters
            are requiered as ['key:!val', '!key', ':!value']

        """
        params = {
            'q': self.format_string % query
        }
        if exactly_one:
            params['limit'] = 1
        if language:
            params['lang'] = language
        if location_bias:
            try:
                lat, lon = [x.strip() for x
                            in self._coerce_point_to_string(location_bias)
                            .split(',')]
                params['lon'] = lon
                params['lat'] = lat
            except ValueError:
                raise ValueError(("Location bias must be a"
                                  " coordinate pair or Point"))
        if osm_tag:
            if isinstance(osm_tag, string_compare):
                params['osm_tag'] = osm_tag
            else:
                try:
                    params['osm_tag'] = '&osm_tag='.join(osm_tag)
                except ValueError:
                    raise ValueError(
                        "osm_tag must be a string expression or "
                        "a set/list of string expressions"
                    )
        url = "?".join((self.api, urlencode(params)))

        logger.debug("%s.geocode: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout),
            exactly_one
        )

    def reverse(
            self,
            query,
            exactly_one=True,
            timeout=None,
            language=False,
            osm_tag=None
        ):  # pylint: disable=W0221
        """
        Returns a reverse geocoded location.

        :param query: The coordinates for which you wish to obtain the
            closest human-readable addresses.
        :type query: :class:`geopy.point.Point`, list or tuple of (latitude,
            longitude), or string as "%(latitude)s, %(longitude)s"

        :param bool exactly_one: Return one result or a list of results, if
            available.

        :param int timeout: Time, in seconds, to wait for the geocoding service
            to respond before raising a :class:`geopy.exc.GeocoderTimedOut`
            exception. Set this only if you wish to override, on this call
            only, the value set during the geocoder's initialization.

        :param string language: Preferred language in which to return results.

        :param osm_tag: The expression to filter (include/exclude) by key and/
            or value, str as 'key:value' or list/set of str if multiple filters
            are requiered as ['key:!val', '!key', ':!value']
        """
        try:
            lat, lon = [x.strip() for x in
                        self._coerce_point_to_string(query).split(',')]
        except ValueError:
            raise ValueError("Must be a coordinate pair or Point")
        params = {
            'lat': lat,
            'lon': lon,
        }
        if exactly_one:
            params['limit'] = 1
        if language:
            params['lang'] = language
        if osm_tag:
            if isinstance(osm_tag, string_compare):
                params['osm_tag'] = osm_tag
            else:
                try:
                    params['osm_tag'] = '&osm_tag='.join(osm_tag)
                except ValueError:
                    raise ValueError(("osm_tag must be a string expression or "
                                      "a set/list of string expressions"))
        url = "?".join((self.reverse_api, urlencode(params)))
        logger.debug("%s.reverse: %s", self.__class__.__name__, url)
        return self._parse_json(
            self._call_geocoder(url, timeout=timeout), exactly_one
        )

    @classmethod
    def _parse_json(cls, resources, exactly_one=True):
        """
        Parse display name, latitude, and longitude from a JSON response.
        """
        if not len(resources):  # pragma: no cover
            return None
        if exactly_one:
            return cls.parse_resource(resources['features'][0])
        else:
            return [cls.parse_resource(resource) for resource
                    in resources['features']]

    @classmethod
    def parse_resource(cls, resource):
        """
        Return location and coordinates tuple from dict.
        """
        name_elements = ['name', 'housenumber', 'street',
                         'postcode', 'street', 'city',
                         'state', 'country']
        name = [resource.get(k) for k
                in name_elements if resource.get(k)]
        location = ', '.join(name)

        latitude = resource['geometry']['coordinates'][1] or None
        longitude = resource['geometry']['coordinates'][0] or None
        if latitude and longitude:
            latitude = float(latitude)
            longitude = float(longitude)

        return Location(location, (latitude, longitude), resource)