<commit_before>"""
url_builder

See ERDDAP docs for all the response options available,

- tabledap: http://coastwatch.pfeg.noaa.gov/erddap/tabledap/documentation.html
- griddap: http://coastwatch.pfeg.noaa.gov/erddap/griddap/documentation.html

"""

from __future__ import absolute_import, division, print_function

import copy

try:
    from urllib.parse import quote_plus
except ImportError:
    from urllib import quote_plus

from erddapy.utilities import _check_url_response, parse_dates, quote_string_constraints


def search_url(server, response='html', search_for=None, items_per_page=1000, page=1, **kwargs):
    """The search URL for the `server` endpoint provided.

    Args:
        search_for (str): "Google-like" search of the datasets' metadata.

            - Type the words you want to search for, with spaces between the words.
                ERDDAP will search for the words separately, not as a phrase.
            - To search for a phrase, put double quotes around the phrase
                (for example, `"wind speed"`).
            - To exclude datasets with a specific word, use `-excludedWord`.
            - To exclude datasets with a specific phrase, use `-"excluded phrase"`
            - Searches are not case-sensitive.
            - To find just grid or just table datasets, include `protocol=griddap`
                or `protocol=tabledap` in your search.
            - You can search for any part of a word. For example,
                searching for `spee` will find datasets with `speed` and datasets with
                `WindSpeed`
            - The last word in a phrase may be a partial word. For example,
                to find datasets from a specific website (usually the start of the datasetID),
                include (for example) `"datasetID=erd"` in your search.

        response (str): default is HTML.
        items_per_page (int): how many items per page in the return,
            default is 1000.
        page (int): which page to display, default is the first page (1).
        kwargs (dict): extra search constraints based on metadata and/or coordinates ke/value.
            metadata: `cdm_data_type`, `institution`, `ioos_category`,
            `keywords`, `long_name`, `standard_name`, and `variableName`.
            coordinates: `minLon`, `maxLon`, `minLat`, `maxLat`, `minTime`, and `maxTime`.

    Returns:
        url (str): the search URL.

    """
    base = (
        '{server}/search/advanced.{response}'
        '?page={page}'
        '&itemsPerPage={itemsPerPage}'
        '&protocol={protocol}'
        '&cdm_data_type={cdm_data_type}'
        '&institution={institution}'
        '&ioos_category={ioos_category}'
        '&keywords={keywords}'
        '&long_name={long_name}'
        '&standard_name={standard_name}'
        '&variableName={variableName}'
        '&minLon={minLon}'
        '&maxLon={maxLon}'
        '&minLat={minLat}'
        '&maxLat={maxLat}'
        '&minTime={minTime}'
        '&maxTime={maxTime}'
    )
    if search_for:
        search_for = quote_plus(search_for)
        base += '&searchFor={searchFor}'

    # Convert dates from datetime to `seconds since 1970-01-01T00:00:00Z`.
    min_time = kwargs.pop('min_time', None)
    max_time = kwargs.pop('max_time', None)
    if min_time:
        kwargs.update({'min_time': parse_dates(min_time)})
    if max_time:
        kwargs.update({'max_time': parse_dates(max_time)})

    default = '(ANY)'
    url = base.format(
        server=server,
        response=response,
        page=page,
        itemsPerPage=items_per_page,
        protocol=kwargs.get('protocol', default),
        cdm_data_type=kwargs.get('cdm_data_type', default),
        institution=kwargs.get('institution', default),
        ioos_category=kwargs.get('ioos_category', default),
        keywords=kwargs.get('keywords', default),
        long_name=kwargs.get('long_name', default),
        standard_name=kwargs.get('standard_name', default),
        variableName=kwargs.get('variableName', default),
        minLon=kwargs.get('min_lon', default),
        maxLon=kwargs.get('max_lon', default),
        minLat=kwargs.get('min_lat', default),
        maxLat=kwargs.get('max_lat', default),
        minTime=kwargs.get('min_time', default),
        maxTime=kwargs.get('max_time', default),
        searchFor=search_for,
    )
    return _check_url_response(url)


def info_url(server, dataset_id, response='html'):
    """The info URL for the `server` endpoint.

    Args:
        dataset_id (str): a dataset unique id.
        response (str): default is HTML.

    Returns:
        url (str): the info URL for the `response` chosen.

    """
    url = f'{server}/info/{dataset_id}/index.{response}'
    return _check_url_response(url)


def download_url(server, dataset_id, protocol, variables, response='html', constraints=None):
    """The download URL for the `server` endpoint.

    Args:
        dataset_id (str): a dataset unique id.
        protocol (str): tabledap or griddap.
        variables (list/tuple): a list of the variables to download.
        response (str): default is HTML.
        constraints (dict): download constraints, default None (opendap-like url)
            example: constraints = {'latitude<=': 41.0,
                                    'latitude>=': 38.0,
                                    'longitude<=': -69.0,
                                    'longitude>=': -72.0,
                                    'time<=': '2017-02-10T00:00:00+00:00',
                                    'time>=': '2016-07-10T00:00:00+00:00',
                                    }

    Returns:
        url (str): the download URL for the `response` chosen.

    """
    url = f'{server}/{protocol}/{dataset_id}.{response}?'

    if variables:
        variables = ','.join(variables)
        url += f'{variables}'

    if constraints:
        _constraints = copy.copy(constraints)
        for k, v in _constraints.items():
            if k.startswith('time'):
                _constraints.update({k: parse_dates(v)})
        _constraints = quote_string_constraints(_constraints)
        _constraints = ''.join([f'&{k}{v}' for k, v in _constraints.items()])

        url += f'{_constraints}'
    return _check_url_response(url)<commit_msg>fix opendap URL<commit_after>"""
url_builder

See ERDDAP docs for all the response options available,

- tabledap: http://coastwatch.pfeg.noaa.gov/erddap/tabledap/documentation.html
- griddap: http://coastwatch.pfeg.noaa.gov/erddap/griddap/documentation.html

"""

from __future__ import absolute_import, division, print_function

import copy

try:
    from urllib.parse import quote_plus
except ImportError:
    from urllib import quote_plus

from erddapy.utilities import _check_url_response, parse_dates, quote_string_constraints


def search_url(server, response='html', search_for=None, items_per_page=1000, page=1, **kwargs):
    """The search URL for the `server` endpoint provided.

    Args:
        search_for (str): "Google-like" search of the datasets' metadata.

            - Type the words you want to search for, with spaces between the words.
                ERDDAP will search for the words separately, not as a phrase.
            - To search for a phrase, put double quotes around the phrase
                (for example, `"wind speed"`).
            - To exclude datasets with a specific word, use `-excludedWord`.
            - To exclude datasets with a specific phrase, use `-"excluded phrase"`
            - Searches are not case-sensitive.
            - To find just grid or just table datasets, include `protocol=griddap`
                or `protocol=tabledap` in your search.
            - You can search for any part of a word. For example,
                searching for `spee` will find datasets with `speed` and datasets with
                `WindSpeed`
            - The last word in a phrase may be a partial word. For example,
                to find datasets from a specific website (usually the start of the datasetID),
                include (for example) `"datasetID=erd"` in your search.

        response (str): default is HTML.
        items_per_page (int): how many items per page in the return,
            default is 1000.
        page (int): which page to display, default is the first page (1).
        kwargs (dict): extra search constraints based on metadata and/or coordinates ke/value.
            metadata: `cdm_data_type`, `institution`, `ioos_category`,
            `keywords`, `long_name`, `standard_name`, and `variableName`.
            coordinates: `minLon`, `maxLon`, `minLat`, `maxLat`, `minTime`, and `maxTime`.

    Returns:
        url (str): the search URL.

    """
    base = (
        '{server}/search/advanced.{response}'
        '?page={page}'
        '&itemsPerPage={itemsPerPage}'
        '&protocol={protocol}'
        '&cdm_data_type={cdm_data_type}'
        '&institution={institution}'
        '&ioos_category={ioos_category}'
        '&keywords={keywords}'
        '&long_name={long_name}'
        '&standard_name={standard_name}'
        '&variableName={variableName}'
        '&minLon={minLon}'
        '&maxLon={maxLon}'
        '&minLat={minLat}'
        '&maxLat={maxLat}'
        '&minTime={minTime}'
        '&maxTime={maxTime}'
    )
    if search_for:
        search_for = quote_plus(search_for)
        base += '&searchFor={searchFor}'

    # Convert dates from datetime to `seconds since 1970-01-01T00:00:00Z`.
    min_time = kwargs.pop('min_time', None)
    max_time = kwargs.pop('max_time', None)
    if min_time:
        kwargs.update({'min_time': parse_dates(min_time)})
    if max_time:
        kwargs.update({'max_time': parse_dates(max_time)})

    default = '(ANY)'
    url = base.format(
        server=server,
        response=response,
        page=page,
        itemsPerPage=items_per_page,
        protocol=kwargs.get('protocol', default),
        cdm_data_type=kwargs.get('cdm_data_type', default),
        institution=kwargs.get('institution', default),
        ioos_category=kwargs.get('ioos_category', default),
        keywords=kwargs.get('keywords', default),
        long_name=kwargs.get('long_name', default),
        standard_name=kwargs.get('standard_name', default),
        variableName=kwargs.get('variableName', default),
        minLon=kwargs.get('min_lon', default),
        maxLon=kwargs.get('max_lon', default),
        minLat=kwargs.get('min_lat', default),
        maxLat=kwargs.get('max_lat', default),
        minTime=kwargs.get('min_time', default),
        maxTime=kwargs.get('max_time', default),
        searchFor=search_for,
    )
    return _check_url_response(url)


def info_url(server, dataset_id, response='html'):
    """The info URL for the `server` endpoint.

    Args:
        dataset_id (str): a dataset unique id.
        response (str): default is HTML.

    Returns:
        url (str): the info URL for the `response` chosen.

    """
    url = f'{server}/info/{dataset_id}/index.{response}'
    return _check_url_response(url)


def download_url(server, dataset_id, protocol, variables, response='html', constraints=None):
    """The download URL for the `server` endpoint.

    Args:
        dataset_id (str): a dataset unique id.
        protocol (str): tabledap or griddap.
        variables (list/tuple): a list of the variables to download.
        response (str): default is HTML.
        constraints (dict): download constraints, default None (opendap-like url)
            example: constraints = {'latitude<=': 41.0,
                                    'latitude>=': 38.0,
                                    'longitude<=': -69.0,
                                    'longitude>=': -72.0,
                                    'time<=': '2017-02-10T00:00:00+00:00',
                                    'time>=': '2016-07-10T00:00:00+00:00',
                                    }

    Returns:
        url (str): the download URL for the `response` chosen.

    """
    # This is an unconstrained OPeNDAP response b/c
    # the integer based constrained version is just not worth supporting ;-p
    if response == 'opendap':
        return f'{server}/{protocol}/{dataset_id}'
    else:
        url = f'{server}/{protocol}/{dataset_id}.{response}?'

    if variables:
        variables = ','.join(variables)
        url += f'{variables}'

    if constraints:
        _constraints = copy.copy(constraints)
        for k, v in _constraints.items():
            if k.startswith('time'):
                _constraints.update({k: parse_dates(v)})
        _constraints = quote_string_constraints(_constraints)
        _constraints = ''.join([f'&{k}{v}' for k, v in _constraints.items()])

        url += f'{_constraints}'
    return _check_url_response(url)
{'fraction_non_alphanumeric': 0.11916327170166092, 'fraction_numerical': 0.011281729865246004, 'mean_word_length': 2.4800981461286806, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '622904', 'n_tokens_mistral': 3838, 'n_tokens_neox': 3669, 'n_words': 1003}