<commit_before>"""
    PyHIS.core
    ~~~~~~~~~~

    Core data models for PyHIS
"""

import itertools
import logging

import numpy as np
from matplotlib.nxutils import points_inside_poly
import pandas
import suds

import pyhis
from . import waterml
from . import shapefile


# fancy this up a bit sometime
LOG_FORMAT = '%(message)s'
logging.basicConfig(format=LOG_FORMAT)
log = logging.getLogger(__name__)

try:
    from . import cache
    if not cache.USE_CACHE:
        log.info('cache has been disabled, so it will not be available')
        cache = None
except ImportError as error:
    log.info('cache not available due to import error:\n%s' % error)
    cache = None

__all__ = ['Site', 'Source', 'TimeSeries', 'Variable', 'Units']


class Site(object):
    """
    Contains information about a site
    """
    _timeseries_dict = {}
    _dataframe = None
    _site_info_response = None
    _use_cache = None
    source = None
    name = None
    code = None
    id = None
    network = None
    latitude = None
    longitude = None

    def __init__(self, network=None, code=None, name=None, id=None,
                 latitude=None, longitude=None, source=None, use_cache=True):
        self.network = network
        self.code = code
        self.name = name
        self.id = id
        self.latitude = latitude
        self.longitude = longitude
        self.source = source
        self._use_cache = use_cache

        # if we don't have all the info, make a GetSiteInfo request
        # and update site attributes with that information
        if not name or not latitude or not longitude:
            site_info = self.site_info_response.site[0].siteInfo

            if not self.name:
                self.name = site_info.siteName
            if not self.id:
                try:
                    self.id = site_info.siteCode[0]._siteID
                except AttributeError, KeyError:
                    # siteID is optional
                    pass
            if not self.latitude:
                self.latitude = site_info.geoLocation.geogLocation.latitude
            if not self.longitude:
                self.longitude = site_info.geoLocation.geogLocation.longitude

    @property
    def dataframe(self):
        if not self._dataframe:
            self._update_dataframe()
        return self._dataframe

    @property
    def site_info_response(self):
        if not self._site_info_response:
            self._update_site_info_response()
        return self._site_info_response

    @property
    def timeseries(self):
        if not len(self._timeseries_dict):
            self._update_timeseries_dict()
        return self._timeseries_dict

    def _update_dataframe(self):
        series_dict = dict((ts.variable.code, ts.series)
                       for ts in self.timeseries.values())
        self._dataframe = pandas.DataFrame(series_dict)

    def _update_site_info_response(self):
        """makes a GetSiteInfo updates site info and series information"""
        log.info('making GetSiteInfo request for "%s:%s"...' %
                 (self.network, self.code))
        self._site_info_response = self.source.suds_client.service.GetSiteInfoObject(
            '%s:%s' % (self.network, self.code))

        if len(self._site_info_response.site) > 1 or \
               len(self._site_info_response.site[0].seriesCatalog) > 1:
            raise NotImplementedError(
                "Multiple site instances or multiple seriesCatalogs not "
                "currently supported")

    def _update_timeseries_dict(self):
        """updates the time series dict"""
        cache_enabled = self._use_cache and cache

        if cache_enabled:
            self._timeseries_dict = cache.get_timeseries_dict_for_site(self)
        else:
            self._timeseries_dict = waterml.get_timeseries_dict_for_site(self)

    def __repr__(self):
        return "<Site: %s [%s]>" % (self.name, self.code)


class Source(object):
    """Represents a water data source"""
    suds_client = None
    url = None
    _description = None
    _all_sites = False
    _sites = {}
    _sites_array = []
    _use_cache = None

    def __init__(self, wsdl_url, description=None, use_cache=True):
        self.suds_client = suds.client.Client(wsdl_url)
        self.url = wsdl_url
        self._description = description
        self._use_cache = use_cache

    @property
    def sites(self):
        return self.get_all_sites()

    @property
    def sites_array(self):
        return self.generate_sites_array()

    @property
    def description(self):
        if not self._description:
            self._update_description()
        return self._description

    def get_all_sites(self):
        """returns all the sites available for a given source"""
        if not self._all_sites:
            self._update_all_sites()
        return self._sites

    def generate_sites_array(self):
        """generates numpy array of locations of all sites
        for convenient spatial queries"""
        if not len(self._sites_array):
            self._sites_array = np.zeros(
                len(self.sites), dtype=[('sitecode', '|S100'),<commit_msg>add large timeout; this is important for huge requests (like can have huge responses that take a while to transmit)<commit_after>"""
    PyHIS.core
    ~~~~~~~~~~

    Core data models for PyHIS
"""

import itertools
import logging

import numpy as np
from matplotlib.nxutils import points_inside_poly
import pandas
import suds

import pyhis
from . import waterml
from . import shapefile

# default timeout for http requests in seconds
SUDS_TIMEOUT = 600  # 5 minutes

# fancy this up a bit sometime
LOG_FORMAT = '%(message)s'
logging.basicConfig(format=LOG_FORMAT)
log = logging.getLogger(__name__)

try:
    from . import cache
    if not cache.USE_CACHE:
        log.info('cache has been disabled, so it will not be available')
        cache = None
except ImportError as error:
    log.info('cache not available due to import error:\n%s' % error)
    cache = None

__all__ = ['Site', 'Source', 'TimeSeries', 'Variable', 'Units']


class Site(object):
    """
    Contains information about a site
    """
    _timeseries_dict = {}
    _dataframe = None
    _site_info_response = None
    _use_cache = None
    source = None
    name = None
    code = None
    id = None
    network = None
    latitude = None
    longitude = None

    def __init__(self, network=None, code=None, name=None, id=None,
                 latitude=None, longitude=None, source=None, use_cache=True):
        self.network = network
        self.code = code
        self.name = name
        self.id = id
        self.latitude = latitude
        self.longitude = longitude
        self.source = source
        self._use_cache = use_cache

        # if we don't have all the info, make a GetSiteInfo request
        # and update site attributes with that information
        if not name or not latitude or not longitude:
            site_info = self.site_info_response.site[0].siteInfo

            if not self.name:
                self.name = site_info.siteName
            if not self.id:
                try:
                    self.id = site_info.siteCode[0]._siteID
                except AttributeError, KeyError:
                    # siteID is optional
                    pass
            if not self.latitude:
                self.latitude = site_info.geoLocation.geogLocation.latitude
            if not self.longitude:
                self.longitude = site_info.geoLocation.geogLocation.longitude

    @property
    def dataframe(self):
        if not self._dataframe:
            self._update_dataframe()
        return self._dataframe

    @property
    def site_info_response(self):
        if not self._site_info_response:
            self._update_site_info_response()
        return self._site_info_response

    @property
    def timeseries(self):
        if not len(self._timeseries_dict):
            self._update_timeseries_dict()
        return self._timeseries_dict

    def _update_dataframe(self):
        series_dict = dict((ts.variable.code, ts.series)
                       for ts in self.timeseries.values())
        self._dataframe = pandas.DataFrame(series_dict)

    def _update_site_info_response(self):
        """makes a GetSiteInfo updates site info and series information"""
        log.info('making GetSiteInfo request for "%s:%s"...' %
                 (self.network, self.code))
        self._site_info_response = self.source.suds_client.service.GetSiteInfoObject(
            '%s:%s' % (self.network, self.code))

        if len(self._site_info_response.site) > 1 or \
               len(self._site_info_response.site[0].seriesCatalog) > 1:
            raise NotImplementedError(
                "Multiple site instances or multiple seriesCatalogs not "
                "currently supported")

    def _update_timeseries_dict(self):
        """updates the time series dict"""
        cache_enabled = self._use_cache and cache

        if cache_enabled:
            self._timeseries_dict = cache.get_timeseries_dict_for_site(self)
        else:
            self._timeseries_dict = waterml.get_timeseries_dict_for_site(self)

    def __repr__(self):
        return "<Site: %s [%s]>" % (self.name, self.code)


class Source(object):
    """Represents a water data source"""
    suds_client = None
    url = None
    _description = None
    _all_sites = False
    _sites = {}
    _sites_array = []
    _use_cache = None

    def __init__(self, wsdl_url, description=None, use_cache=True):
        self.suds_client = suds.client.Client(wsdl_url, timeout=SUDS_TIMEOUT)
        self.url = wsdl_url
        self._description = description
        self._use_cache = use_cache

    @property
    def sites(self):
        return self.get_all_sites()

    @property
    def sites_array(self):
        return self.generate_sites_array()

    @property
    def description(self):
        if not self._description:
            self._update_description()
        return self._description

    def get_all_sites(self):
        """returns all the sites available for a given source"""
        if not self._all_sites:
            self._update_all_sites()
        return self._sites

    def generate_sites_array(self):
        """generates numpy array of locations of all sites
        for convenient spatial queries"""
        if not len(self._sites_array):
            self._sites_array = np.zeros(
                len(self.sites), dtype=[('sitecode', '|S100'),
{'fraction_non_alphanumeric': 0.08608076009501188, 'fraction_numerical': 0.0019002375296912114, 'mean_word_length': 2.31214600377596, 'pattern_counts': {'":': 0, '<': 5, '<?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': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2826728', 'n_tokens_mistral': 3064, 'n_tokens_neox': 2929, 'n_words': 802}