o
    ÔèFhS0  ã                   @   sˆ   d dl Z d dlmZ d dlmZ d dlmZ d dlmZmZm	Z	 d dl
mZmZmZ d dlmZ d dlmZ d	Zd
ZG dd„ deƒZdS )é    N)Úpartial)Útime)Ú	urlencode)ÚConfigurationErrorÚGeocoderAuthenticationFailureÚGeocoderServiceError)ÚDEFAULT_SENTINELÚGeocoderÚ_synchronized)ÚLocation)Úlogger)ÚArcGISiæ  c                       sœ   e Zd ZdZdZdZdZdZ		ddddeededdd	d
œ
‡ fdd„Z	deddœdd„Z
dd„ Zdeddœdd„Zdd„ Zedœdd„Zedd„ ƒZ‡  ZS )r   z¥Geocoder using the ERSI ArcGIS API.

    Documentation at:
        https://developers.arcgis.com/rest/geocode/api-reference/overview-world-geocoding-service.htm
    iò  z/sharing/generateTokenz?/arcgis/rest/services/World/GeocodeServer/findAddressCandidatesz8/arcgis/rest/services/World/GeocodeServer/reverseGeocodeNé<   zwww.arcgis.comzgeocode.arcgis.com)
ÚrefererÚtoken_lifetimeÚschemeÚtimeoutÚproxiesÚ
user_agentÚssl_contextÚadapter_factoryÚauth_domainÚdomainc       
            sÐ   t ƒ j|||||	|
d� |s|s|r%|r|r|stdƒ‚| jdkr%tdƒ‚|| _|| _|| _| d¡| _d| j| j| j	f | _
|d | _| d¡| _d| j| j| jf | _d| j| j| jf | _d| _d| _dS )	a�  

        :param str username: ArcGIS username. Required if authenticated
            mode is desired.

        :param str password: ArcGIS password. Required if authenticated
            mode is desired.

        :param str referer: Required if authenticated mode is desired.
            `Referer` HTTP header to send with each request,
            e.g., ``'http://www.example.com'``. This is tied to an issued token,
            so fielding queries for multiple referrers should be handled by
            having multiple ArcGIS geocoder instances.

        :param int token_lifetime: Desired lifetime, in minutes, of an
            ArcGIS-issued token.

        :param str scheme:
            See :attr:`geopy.geocoders.options.default_scheme`.
            If authenticated mode is in use, it must be ``'https'``.

        :param int timeout:
            See :attr:`geopy.geocoders.options.default_timeout`.

        :param dict proxies:
            See :attr:`geopy.geocoders.options.default_proxies`.

        :param str user_agent:
            See :attr:`geopy.geocoders.options.default_user_agent`.

        :type ssl_context: :class:`ssl.SSLContext`
        :param ssl_context:
            See :attr:`geopy.geocoders.options.default_ssl_context`.

        :param callable adapter_factory:
            See :attr:`geopy.geocoders.options.default_adapter_factory`.

            .. versionadded:: 2.0

        :param str auth_domain: Domain where the target ArcGIS auth service
            is hosted. Used only in authenticated mode (i.e. username,
            password and referer are set).

        :param str domain: Domain where the target ArcGIS service
            is hosted.
        )r   r   r   r   r   r   z;Authenticated mode requires username, password, and refererÚhttpsz-Authenticated mode requires scheme of 'https'ú/z	%s://%s%sr   N)ÚsuperÚ__init__r   r   ÚusernameÚpasswordr   Ústripr   Ú	auth_pathÚauth_apir   r   Úgeocode_pathÚapiÚreverse_pathÚreverse_apiÚtokenÚtoken_expiry)Úselfr   r   r   r   r   r   r   r   r   r   r   r   ©Ú	__class__© úO/var/www/html/loop/nvenv/lib/python3.10/site-packages/geopy/geocoders/arcgis.pyr   !   s>   >úÿ
ÿÿ
ÿÿ
zArcGIS.__init__T)Úexactly_oner   Ú
out_fieldsc                C   s„   |ddœ}|rd|d< |dur t |tƒr||d< nd |¡|d< d | jt|ƒf¡}t d	| jj|¡ t	| j
|d
�}| j|||d�S )am  
        Return a location point by address.

        :param str 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 out_fields: A list of output fields to be returned in the
            attributes field of the raw data. This can be either a python
            list/tuple of fields or a comma-separated string. See
            https://developers.arcgis.com/rest/geocode/api-reference/geocoding-service-output.htm
            for a list of supported output fields. If you want to return all
            supported output fields, set ``out_fields="*"``.
        :type out_fields: str or iterable

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        Újson)Ú
singleLineÚfé   ÚmaxLocationsNÚ	outFieldsú,ú?z%s.geocode: %s©r-   ©r   )Ú
isinstanceÚstrÚjoinr#   r   r   Údebugr*   Ú__name__r   Ú_parse_geocodeÚ_authenticated_call_geocoder)r(   Úqueryr-   r   r.   ÚparamsÚurlÚcallbackr+   r+   r,   Úgeocodeˆ   s   


zArcGIS.geocodec                 C   st   d|v rt t|d ƒƒ‚t|d ƒsd S g }|d D ]}|d }| t|d |d |d f|ƒ¡ q|r8|d S |S )NÚerrorÚ
candidatesÚlocationÚaddressÚyÚxr   )r   r:   ÚlenÚappendr   )r(   Úresponser-   ÚgeocodedÚresourceÚgeometryr+   r+   r,   r>   ¯   s   ÿÿzArcGIS._parse_geocode)r-   r   Údistancec          
      C   sp   |   |d¡}t}|d|dœ}|dur||d< d | jt|ƒf¡}t d| jj|¡ t	| j
|d�}	| j||	|d	�S )
aý  
        Return an address by location point.

        :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 int distance: Distance from the query location, in meters,
            within which to search. ArcGIS has a default of 100 meters, if not
            specified.

        :rtype: ``None``, :class:`geopy.location.Location` or a list of them, if
            ``exactly_one=False``.
        z%(lon)s,%(lat)sr/   )rG   r1   ÚoutSRNrQ   r6   z%s.reverse: %sr7   r8   )Ú_coerce_point_to_stringÚDEFAULT_WKIDr;   r%   r   r   r<   r*   r=   r   Ú_parse_reverser?   )
r(   r@   r-   r   rQ   rG   ÚwkidrA   rB   rC   r+   r+   r,   ÚreverseÂ   s   zArcGIS.reversec              	   C   sÄ   t |ƒsd S d|v r5|d d dkr-zd|d d d v r W d S W n ttfy,   Y nw tt|d ƒƒ‚|d  d¡rCd	|d  }n|d d
 }t||d d |d d f|d ƒ}|r_|S |gS )NrE   Úcodei�  zUnable to findÚdetailsr   rH   ÚAddressz=%(Address)s, %(City)s, %(Region)s %(Postal)s, %(CountryCode)sÚ	LongLabelrG   rI   rJ   )rK   ÚKeyErrorÚ
IndexErrorr   r:   Úgetr   )r(   rM   r-   rH   rG   r+   r+   r,   rU   å   s4   ÿÿÿÿýzArcGIS._parse_reverser8   c                   s~   ˆj sˆjˆˆˆd�S ‡ ‡‡‡fdd„}‡‡‡‡fdd„‰ ‡‡‡‡fdd„‰ˆjd u s3ttƒ ƒˆjkr<ˆj|ˆˆjd�S |ƒ S )	Nr8   c                     s>   d  ˆtdˆjiƒf¡} dˆji}ˆj| tˆ ˆjd�ˆ|d�S )Nú&r&   ÚReferer)Ú
from_token©r   Úheaders)r;   r   r&   r   Ú_call_geocoderr   ©Úcall_urlrc   )Úmaybe_reauthenticate_callbackr(   r   rB   r+   r,   Úquery_callback  s   
üz;ArcGIS._authenticated_call_geocoder.<locals>.query_callbackc                   s2   d| v r| d d ˆj krˆjˆˆ|d�S ˆ | ƒS )NrE   rX   ©r   ra   )Ú_TOKEN_EXPIREDÚ_refresh_authentication_token)rM   ra   )Úparse_callbackÚquery_retry_callbackr(   r   r+   r,   rg     s   ÿzJArcGIS._authenticated_call_geocoder.<locals>.maybe_reauthenticate_callbackc                     s4   d  ˆtdˆjiƒf¡} dˆji}ˆj| ˆ ˆ|d�S )Nr_   r&   r`   rb   )r;   r   r&   r   rd   re   )rl   r(   r   rB   r+   r,   rm     s
   
ÿzAArcGIS._authenticated_call_geocoder.<locals>.query_retry_callbackri   )r   rd   r&   Úintr   r'   rk   )r(   rB   rl   r   rh   r+   )rg   rl   rm   r(   r   rB   r,   r?     s   
ÿz#ArcGIS._authenticated_call_geocoderc                   sn   |ˆj krˆ ƒ S ˆjˆjˆjˆjddœ}d ˆjt|ƒf¡‰t 	dˆj
jˆ¡ ‡ ‡‡fdd„}ˆjˆ||d�S )Nr/   )r   r   r   Ú
expirationr1   r6   z$%s._refresh_authentication_token: %sc                    s@   d| vrt dˆt | ¡f ƒ‚| d ˆ_ttƒ ƒˆj ˆ_ˆ ƒ S )Nr&   z@Missing token in auth request.Request URL: %s; response JSON: %s)r   r/   Údumpsr&   rn   r   r   r'   )rM   ©Úcallback_successr(   rB   r+   r,   Úcb>  s   ÿÿ
z0ArcGIS._refresh_authentication_token.<locals>.cbr8   )r&   r   r   r   r   r;   r!   r   r   r<   r*   r=   rd   )r(   rr   r   ra   Útoken_request_argumentsrs   r+   rq   r,   rk   +  s   
ûþ
z$ArcGIS._refresh_authentication_token)NN)r=   Ú
__module__Ú__qualname__Ú__doc__rj   r    r"   r$   r   r   rD   r>   rW   rU   r?   r
   rk   Ú__classcell__r+   r+   r)   r,   r      s@    ýògÿ'ÿ#!ÿ&r   )r/   Ú	functoolsr   r   Úurllib.parser   Ú	geopy.excr   r   r   Úgeopy.geocoders.baser   r	   r
   Úgeopy.locationr   Ú
geopy.utilr   Ú__all__rT   r   r+   r+   r+   r,   Ú<module>   s    