o
    GfS                     @  s   d Z ddlmZ ddlZddlZddlZddlmZ ddl	m
Z
 edd dD ZG d	d
 d
eZG dd deZdd ZdZdS )z"
Utilities to support XYZservices
    )annotationsN)Callable)quotec                 C  s   i | ]}|d qS )  ).0xr   r   [/home/deployuser/azure_apps/autowriter/venv/lib/python3.10/site-packages/xyzservices/lib.py
<dictcomp>   s    r
   z., -_/c                   @  sR   e Zd ZdZdd Zdd ZdddZdddZ				ddddZdddZ	dS ) Buncha  A dict with attribute-access

    :class:`Bunch` is used to store :class:`TileProvider` objects.

    Examples
    --------
    >>> black_and_white = TileProvider(
    ...     name="My black and white tiles",
    ...     url="https://myserver.com/bw/{z}/{x}/{y}",
    ...     attribution="(C) xyzservices",
    ... )
    >>> colorful = TileProvider(
    ...     name="My colorful tiles",
    ...     url="https://myserver.com/color/{z}/{x}/{y}",
    ...     attribution="(C) xyzservices",
    ... )
    >>> MyTiles = Bunch(BlackAndWhite=black_and_white, Colorful=colorful)
    >>> MyTiles
    {'BlackAndWhite': {'name': 'My black and white tiles', 'url': 'https://myserver.com/bw/{z}/{x}/{y}', 'attribution': '(C) xyzservices'}, 'Colorful': {'name': 'My colorful tiles', 'url': 'https://myserver.com/color/{z}/{x}/{y}', 'attribution': '(C) xyzservices'}}
    >>> MyTiles.BlackAndWhite.url
    'https://myserver.com/bw/{z}/{x}/{y}'
    c              
   C  s0   z|  |W S  ty } zt||d }~ww N)__getitem__KeyErrorAttributeError)selfkeyerrr   r   r	   __getattr__*   s   
zBunch.__getattr__c                 C  s   |   S r   )keysr   r   r   r	   __dir__0   s   zBunch.__dir__Fc                 C  s   d}| D ].}t | | trd}nd}tt }|d| d| d| d| d| | jd	d
 d7 }q|r7dndt d}d| dt|  d| d}|S )Nr   zxyzservices.TileProviderzxyzservices.BunchzO
            <li class="xyz-child">
                <input type="checkbox" id="z5" class="xyz-checkbox"/>
                <label for="z">z <span>zM</span></label>
                <div class="xyz-inside">
                    T)insidez6
                </div>
            </li>
            <style></style>
        <div>
        z
            <div class="xyz-wrap">
                <div class="xyz-header">
                    <div class="xyz-obj">xyzservices.Bunch</div>
                    <div class="xyz-name">z items</div>
                </div>
                <div class="xyz-details">
                    <ul class="xyz-collapsible">
                        z\
                    </ul>
                </div>
            </div>
        </div>
        )
isinstanceTileProviderstruuiduuid4_repr_html_	CSS_STYLElen)r   r   childrenr   objuidstylehtmlr   r   r	   r    3   s4   

zBunch._repr_html_returndictc                   s   i  fdd  |  S )a  Return the nested :class:`Bunch` collapsed into the one level dictionary.

        Dictionary keys are :class:`TileProvider` names (e.g. ``OpenStreetMap.Mapnik``)
        and its values are :class:`TileProvider` objects.

        Returns
        -------
        flattened : dict
            dictionary of :class:`TileProvider` objects

        Examples
        --------
        >>> import xyzservices.providers as xyz
        >>> len(xyz)
        36

        >>> flat = xyz.flatten()
        >>> len(xyz)
        207

        c                   s2   t | tr| | j< d S |  D ]} | qd S r   )r   r   namevalues)providerprov_get_providersflatr   r	   r/   r   s
   

z%Bunch.flatten.<locals>._get_providersr   r   r   r.   r	   flattenY   s   zBunch.flattenNkeyword
str | Noner*   requires_tokenbool | NonefunctionCallable[[TileProvider], bool]c                   s(   dd  fdd  | ||||dS )a		  Return a subset of the :class:`Bunch` matching the filter conditions

        Each :class:`TileProvider` within a :class:`Bunch` is checked against one or
        more specified conditions and kept if they are satisfied or removed if at least
        one condition is not met.

        Parameters
        ----------
        keyword : str (optional)
            Condition returns ``True`` if ``keyword`` string is present in any string
            value in a :class:`TileProvider` object.
            The comparison is not case sensitive.
        name : str (optional)
            Condition returns ``True`` if ``name`` string is present in
            the name attribute of :class:`TileProvider` object.
            The comparison is not case sensitive.
        requires_token : bool (optional)
            Condition returns ``True`` if :meth:`TileProvider.requires_token` returns
            ``True`` (i.e. if the object requires specification of API token).
        function : callable (optional)
            Custom function taking :class:`TileProvider` as an argument and returns
            bool. If ``function`` is given, other parameters are ignored.

        Returns
        -------
        filtered : Bunch

        Examples
        --------
        >>> import xyzservices.providers as xyz

        You can filter all free providers (not requiring API token):

        >>> free_providers = xyz.filter(requires_token=False)

        Or all providers with ``open`` in the name:

        >>> open_providers = xyz.filter(name="open")

        You can use keyword search to find all providers based on OpenStreetMap data:

        >>> osm_providers = xyz.filter(keyword="openstreetmap")

        You can combine multiple conditions to find providers based on OpenStreetMap
        data that require API token:

        >>> osm_locked = xyz.filter(keyword="openstreetmap", requires_token=True)

        You can also pass custom function that takes :class:`TileProvider` and returns
        boolean value. You can then find all providers with ``max_zoom`` smaller than
        18:

        >>> def zoom18(provider):
        ...    if hasattr(provider, "max_zoom") and provider.max_zoom < 18:
        ...        return True
        ...    return False
        >>> small_zoom = xyz.filter(function=zoom18)
        c           	      S  s   g }|d ur%d}|   D ]}t|tr| | v rd} nq|| |d ur;d}| | j v r6d}|| |d urNd}|  |u rId}|| t|S )NFT)r+   r   r   lowerappendr*   r4   all)	r,   r2   r*   r4   condkeyword_matchv
name_matchtoken_matchr   r   r	   	_validate   s(   


zBunch.filter.<locals>._validatec           	        sx   t  }|  D ]2\}}t|tr*|d u r!||||dr |||< q||r)|||< q |||||d}|r9|||< q|S )N)r2   r*   r4   r2   r*   r4   r6   )r   itemsr   r   )	bunchr2   r*   r4   r6   newr   valuefiltered_filter_bunchr@   r   r	   rH      s4   
z#Bunch.filter.<locals>._filter_bunchrA   r   )r   r2   r*   r4   r6   r   rG   r	   filter}   s   BzBunch.filterr   r   c                 C  sD   dd |    D }|t }||v r|| S td| d)a  Return :class:`TileProvider` based on the name query

        Returns a matching :class:`TileProvider` from the :class:`Bunch` if the ``name``
        contains the same letters in the same order as the provider's name irrespective
        of the letter case, spaces, dashes and other characters.
        See examples for details.

        Parameters
        ----------
        name : str
            Name of the tile provider. Formatting does not matter.

        Returns
        -------
        match: TileProvider

        Examples
        --------
        >>> import xyzservices.providers as xyz

        All these queries return the same ``CartoDB.Positron`` TileProvider:

        >>> xyz.query_name("CartoDB Positron")
        >>> xyz.query_name("cartodbpositron")
        >>> xyz.query_name("cartodb-positron")
        >>> xyz.query_name("carto db/positron")
        >>> xyz.query_name("CARTO_DB_POSITRON")
        >>> xyz.query_name("CartoDB.Positron")

        c                 S  s    i | ]\}}| t |qS r   )	translateQUERY_NAME_TRANSLATIONr8   )r   kr=   r   r   r	   r
     s    z$Bunch.query_name.<locals>.<dictcomp>z*No matching provider found for the query 'z'.)r1   rB   rJ   rK   r8   
ValueError)r   r*   xyz_flat_lower
name_cleanr   r   r	   
query_name   s   
zBunch.query_nameF)r(   r)   )NNNN)
r2   r3   r*   r3   r4   r5   r6   r7   r(   r   r*   r   r(   r   )
__name__
__module____qualname____doc__r   r   r    r1   rI   rP   r   r   r   r	   r      s    

&& r   c                      sx   e Zd ZdZ fddZd!ddZd!ddZ									
d"d#ddZd$ddZe	dd Z
d%ddZed&dd Z  ZS )'r   a$  
    A dict with attribute-access and that
    can be called to update keys


    Examples
    --------

    You can create custom :class:`TileProvider` by passing your attributes to the object
    as it would have been a ``dict()``. It is required to always specify ``name``,
    ``url``, and ``attribution``.

    >>> public_provider = TileProvider(
    ...     name="My public tiles",
    ...     url="https://myserver.com/tiles/{z}/{x}/{y}.png",
    ...     attribution="(C) xyzservices",
    ... )

    Alternatively, you can create it from a dictionary of attributes. When specifying a
    placeholder for the access token, please use the ``"<insert your access token
    here>"`` string to ensure that :meth:`~xyzservices.TileProvider.requires_token`
    method works properly.

    >>> private_provider = TileProvider(
    ...    {
    ...        "url": "https://myserver.com/tiles/{z}/{x}/{y}.png?apikey={accessToken}",
    ...        "attribution": "(C) xyzservices",
    ...        "accessToken": "<insert your access token here>",
    ...        "name": "my_private_provider",
    ...    }
    ... )

    It is customary to include ``html_attribution`` attribute containing HTML string as
    ``'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>
    contributors'`` alongisde a plain-text ``attribution``.

    You can then fetch all information as attributes:

    >>> public_provider.url
    'https://myserver.com/tiles/{z}/{x}/{y}.png'

    >>> public_provider.attribution
    '(C) xyzservices'

    To ensure you will be able to use the tiles, you can check if the
    :class:`TileProvider` requires a token or API key.

    >>> public_provider.requires_token()
    False
    >>> private_provider.requires_token()
    True

    You can also generate URL in the required format with or without placeholders:

    >>> public_provider.build_url()
    'https://myserver.com/tiles/{z}/{x}/{y}.png'
    >>> private_provider.build_url(x=12, y=21, z=11, accessToken="my_token")
    'https://myserver.com/tiles/11/12/21.png?access_token=my_token'

    c                   s`   t  j|i | g }dD ]}||  vr|| qt|dkr.dd| d}t|d S )N)r*   urlattributionr   zyThe attributes `name`, `url`, and `attribution` are required to initialise a `TileProvider`. Please provide values for: `z`, ``)super__init__r   r9   r"   joinr   )r   argskwargsmissingelmsg	__class__r   r	   r[   e  s   
zTileProvider.__init__r(   c                 K  s   t | }|| |S r   )r   update)r   r^   rD   r   r   r	   __call__t  s   
zTileProvider.__call__c                 C  s   t | }|S r   r   )r   rD   r   r   r	   copyy  s   zTileProvider.copyNTr   int | str | Noneyzscale_factorr3   fill_subdomainr5   r   c                 K  s   |   }|du r
d}|du rd}|du rd}|| | r#td|d}|r3|}	|dd n|dd}	|rF|d	d
}
|
d }nd}|jd|||||	d|S )a  
        Build the URL of tiles from the :class:`TileProvider` object

        Can return URL with placeholders or the final tile URL.

        Parameters
        ----------

        x, y, z : int (optional)
            tile number
        scale_factor : str (optional)
            Scale factor (where supported). For example, you can get double resolution
            (512 x 512) instead of standard one (256 x 256) with ``"@2x"``. If you want
            to keep a placeholder, pass `"{r}"`.
        fill_subdomain : bool (optional, default True)
            Fill subdomain placeholder with the first available subdomain. If False, the
            URL will contain ``{s}`` placeholder for subdomain.

        **kwargs
            Other potential attributes updating the :class:`TileProvider`.

        Returns
        -------

        url : str
            Formatted URL

        Examples
        --------
        >>> import xyzservices.providers as xyz

        >>> xyz.CartoDB.DarkMatter.build_url()
        'https://a.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png'

        >>> xyz.CartoDB.DarkMatter.build_url(x=9, y=11, z=5)
        'https://a.basemaps.cartocdn.com/dark_all/5/9/11.png'

        >>> xyz.CartoDB.DarkMatter.build_url(x=9, y=11, z=5, scale_factor="@2x")
        'https://a.basemaps.cartocdn.com/dark_all/5/9/11@2x.png'

        >>> xyz.MapBox.build_url(accessToken="my_token")
        'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=my_token'

        Nz{x}z{y}z{z}zToken is required for this provider, but not provided. You can either update TileProvider or pass respective keywords to build_url().rW   rr   
subdomainsabcr   z{s})r   ri   rj   srm   r   )rg   rd   r4   rM   popformat)r   r   ri   rj   rk   rl   r^   r,   rW   rm   rn   rp   r   r   r	   	build_url}  s,   5


zTileProvider.build_urlboolc                 C  s8   |   D ]\}}t|trd|v r|| jv r dS qdS )al  
        Returns ``True`` if the TileProvider requires access token to fetch tiles.

        The token attribute name vary and some :class:`TileProvider` objects may require
        more than one token (e.g. ``HERE``). The information is deduced from the
        presence of `'<insert your...'` string in one or more of attributes. When
        specifying a placeholder for the access token, please use the ``"<insert your
        access token here>"`` string to ensure that
        :meth:`~xyzservices.TileProvider.requires_token` method works properly.

        Returns
        -------
        bool

        Examples
        --------
        >>> import xyzservices.providers as xyz
        >>> xyz.MapBox.requires_token()
        True

        >>> xyz.CartoDB.Positron
        False

        We can specify this API key by calling the object or overriding the attribute.
        Overriding the attribute will alter existing object:

        >>> xyz.OpenWeatherMap.Clouds["apiKey"] = "my-private-api-key"

        Calling the object will return a copy:

        >>> xyz.OpenWeatherMap.Clouds(apiKey="my-private-api-key")


        z<insert yourTF)rB   r   r   rW   )r   r   valr   r   r	   r4     s
   $zTileProvider.requires_tokenc                 C  s   d| v r| d S | d S )Nhtml_attributionrX   r   r   r   r   r	   rv     s   zTileProvider.html_attributionFc                 C  sf   d}|   D ]\}}|dkr|d| d| d7 }q|rdndt d}d| d	| j d
| d}|S )Nr   r*   z
<dt><span>z</span></dt><dd>z</dd>r   r   r   z
            <div class="xyz-wrap">
                <div class="xyz-header">
                    <div class="xyz-obj">xyzservices.TileProvider</div>
                    <div class="xyz-name">z</div>
                </div>
                <div class="xyz-details">
                    <dl class="xyz-attrs">
                        z\
                    </dl>
                </div>
            </div>
        </div>
        )rB   r!   r*   )r   r   provider_infor   ru   r&   r'   r   r   r	   r      s   
zTileProvider._repr_html_r*   c                 C  s   d}t tj| dt| d}|D ]
}|d |kr n	qtd| d|d }t tj| d| }| |d |d	 |d
|d|ddS )a  
        Creates a :class:`TileProvider` object based on the definition from
        the `Quick Map Services <https://qms.nextgis.com/>`__ open catalog.

        Parameters
        ----------
        name : str
            Service name

        Returns
        -------
        :class:`TileProvider`

        Examples
        --------
        >>> from xyzservices.lib import TileProvider
        >>> provider = TileProvider.from_qms("OpenTopoMap")
        z*https://qms.nextgis.com/api/v1/geoservicesz	/?search=z	&type=tmsr*   z	Service 'z' not found.id/rW   z_minz_maxcopyright_text)r*   rW   min_zoommax_zoomrX   )jsonloadurllibrequesturlopenr   rM   get)clsr*   qms_api_urlservicesservice
service_idservice_detailsr   r   r	   from_qms  s(   zTileProvider.from_qms)r(   r   )NNNNT)r   rh   ri   rh   rj   rh   rk   r3   rl   r5   r(   r   )r(   rt   rQ   rR   )rS   rT   rU   rV   r[   re   rg   rs   r4   propertyrv   r    classmethodr   __classcell__r   r   rb   r	   r   '  s"    =


W)

r   c                   sV   t | }t }|D ]}||  d v rt ||< q
t fdd D ||< q
|S )NrW   c                   s   i | ]	}|t  | qS r   rf   )r   ir,   r   r	   r
   X  s    z_load_json.<locals>.<dictcomp>)r   loadsr   r   )fdata	providersprovider_namer   r   r	   
_load_jsonK  s   

r   u8  
/* CSS stylesheet for displaying xyzservices objects in Jupyter.*/
.xyz-wrap {
    --xyz-border-color: var(--jp-border-color2, #ddd);
    --xyz-font-color2: var(--jp-content-font-color2, rgba(128, 128, 128, 1));
    --xyz-background-color-white: var(--jp-layout-color1, white);
    --xyz-background-color: var(--jp-layout-color2, rgba(128, 128, 128, 0.1));
}

html[theme=dark] .xyz-wrap,
body.vscode-dark .xyz-wrap,
body.vscode-high-contrast .xyz-wrap {
    --xyz-border-color: #222;
    --xyz-font-color2: rgba(255, 255, 255, 0.54);
    --xyz-background-color-white: rgba(255, 255, 255, 1);
    --xyz-background-color: rgba(255, 255, 255, 0.05);

}

.xyz-header {
    padding-top: 6px;
    padding-bottom: 6px;
    margin-bottom: 4px;
    border-bottom: solid 1px var(--xyz-border-color);
}

.xyz-header>div {
    display: inline;
    margin-top: 0;
    margin-bottom: 0;
}

.xyz-obj,
.xyz-name {
    margin-left: 2px;
    margin-right: 10px;
}

.xyz-obj {
    color: var(--xyz-font-color2);
}

.xyz-attrs {
    grid-column: 1 / -1;
}

dl.xyz-attrs {
    padding: 0 5px 0 5px;
    margin: 0;
    display: grid;
    grid-template-columns: 135px auto;
    background-color: var(--xyz-background-color);
}

.xyz-attrs dt,
dd {
    padding: 0;
    margin: 0;
    float: left;
    padding-right: 10px;
    width: auto;
}

.xyz-attrs dt {
    font-weight: normal;
    grid-column: 1;
}

.xyz-attrs dd {
    grid-column: 2;
    white-space: pre-wrap;
    word-break: break-all;
}

.xyz-details ul>li>label>span {
    color: var(--xyz-font-color2);
    padding-left: 10px;
}

.xyz-inside {
    display: none;
}

.xyz-checkbox:checked~.xyz-inside {
    display: contents;
}

.xyz-collapsible li>input {
    display: none;
}

.xyz-collapsible>li>label {
    cursor: pointer;
}

.xyz-collapsible>li>label:hover {
    color: var(--xyz-font-color2);
}

ul.xyz-collapsible {
    list-style: none!important;
    padding-left: 20px!important;
}

.xyz-checkbox+label:before {
    content: '►';
    font-size: 11px;
}

.xyz-checkbox:checked+label:before {
    content: '▼';
}

.xyz-wrap {
    margin-bottom: 10px;
}
)rV   
__future__r   r   urllib.requestr   r   typingr   urllib.parser   r   	maketransrK   r)   r   r   r   r!   r   r   r   r	   <module>   s         &