<commit_before>"""
Core interface to the adsws-api, including data models and user facing
interfaces
"""

import warnings
import math
import json
import requests
import os
import six
import sys
from werkzeug.utils import cached_property

from .exceptions import SolrResponseParseError, SolrResponseError
from .config import SEARCH_URL, TOKEN_FILES, TOKEN_ENVIRON_VARS
from . import __version__

PY3 = sys.version_info > (3, )


class APIResponse(object):
    """
    Base class that represents an adsws-api http response
    """
    response = None

    def get_ratelimits(self):
        """
        Return the current, maximum, and reset rate limits from the response
        header as a dictionary. The values will be strings.
        """
        return {
            "limit": self.response.headers.get('X-RateLimit-Limit'),
            "remaining": self.response.headers.get('X-RateLimit-Remaining'),
            "reset": self.response.headers.get('X-RateLimit-Reset')
        }


class SolrResponse(APIResponse):
    """
    Base class for storing a solr response
    """

    def __init__(self, raw):
        """
        De-serialize a json string representing a solr response
        :param raw: complete json response from solr
        :type raw: basestring
        """
        self._raw = raw
        self.json = json.loads(raw)
        self._articles = None
        try:
            self.responseHeader = self.json['responseHeader']
            self.params = self.json['responseHeader']['params']
            self.response = self.json['response']
            self.numFound = self.response['numFound']
            self.docs = self.response['docs']
        except KeyError as e:
            raise SolrResponseParseError("{}".format(e))

    @classmethod
    def load_http_response(cls, HTTPResponse):
        """
        Returns an instansiated SolrResponse using data in a requests.response.
        Sets class attribute `articles` to a list containing Article instances.
        :param HTTPResponse: response object
        :type HTTPResponse: requests.Response
        :return SolrResponse instance
        """
        if not HTTPResponse.ok:
            raise SolrResponseError(HTTPResponse.text)
        c = cls(HTTPResponse.text)
        c.response = HTTPResponse
        return c

    @property
    def articles(self):
        """
        articles getter
        """
        if self._articles is None:
            self._articles = []
            for doc in self.docs:
                self._articles.append(Article(**doc))
        return self._articles


class Article(object):
    """
    An object to represent a single record in NASA's Astrophysical
    Data System.
    """

    def __init__(self, **kwargs):
        """
        :param kwargs: Set object attributes from kwargs
        """

        if "id" not in kwargs:
            warnings.warn(
                "No article id found -- on-demand attribute lookup will fail",
                RuntimeWarning
            )

        self._raw = kwargs
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)

    def __str__(self):
        return self.__unicode__() if PY3 else self.__unicode__().encode("utf-8")
        
    def __unicode__(self):
        author = self.first_author or "Unknown author"
        print self.author
        if self.author and len(self.author) > 1:
            author += " et al."

        return u"<{author} {year}, {bibcode}>".format(
            author=author,
            year=self.year,
            bibcode=self.bibcode,
        )

    def __eq__(self, other):
        if not hasattr(self, 'bibcode') or not hasattr(other, 'bibcode') or \
                self.bibcode is None or other.bibcode is None:
            raise TypeError("Cannot compare articles without bibcodes")
        return self.bibcode == other.bibcode

    def __ne__(self, other):
        return not self.__eq__(other)

    def keys(self):
        return self._raw.keys()

    def items(self):
        return self._raw.items()

    def iteritems(self):
        return six.iteritems(self._raw)<commit_msg>misc: remove debugging print stmt<commit_after>"""
Core interface to the adsws-api, including data models and user facing
interfaces
"""

import warnings
import math
import json
import requests
import os
import six
import sys
from werkzeug.utils import cached_property

from .exceptions import SolrResponseParseError, SolrResponseError
from .config import SEARCH_URL, TOKEN_FILES, TOKEN_ENVIRON_VARS
from . import __version__

PY3 = sys.version_info > (3, )


class APIResponse(object):
    """
    Base class that represents an adsws-api http response
    """
    response = None

    def get_ratelimits(self):
        """
        Return the current, maximum, and reset rate limits from the response
        header as a dictionary. The values will be strings.
        """
        return {
            "limit": self.response.headers.get('X-RateLimit-Limit'),
            "remaining": self.response.headers.get('X-RateLimit-Remaining'),
            "reset": self.response.headers.get('X-RateLimit-Reset')
        }


class SolrResponse(APIResponse):
    """
    Base class for storing a solr response
    """

    def __init__(self, raw):
        """
        De-serialize a json string representing a solr response
        :param raw: complete json response from solr
        :type raw: basestring
        """
        self._raw = raw
        self.json = json.loads(raw)
        self._articles = None
        try:
            self.responseHeader = self.json['responseHeader']
            self.params = self.json['responseHeader']['params']
            self.response = self.json['response']
            self.numFound = self.response['numFound']
            self.docs = self.response['docs']
        except KeyError as e:
            raise SolrResponseParseError("{}".format(e))

    @classmethod
    def load_http_response(cls, HTTPResponse):
        """
        Returns an instansiated SolrResponse using data in a requests.response.
        Sets class attribute `articles` to a list containing Article instances.
        :param HTTPResponse: response object
        :type HTTPResponse: requests.Response
        :return SolrResponse instance
        """
        if not HTTPResponse.ok:
            raise SolrResponseError(HTTPResponse.text)
        c = cls(HTTPResponse.text)
        c.response = HTTPResponse
        return c

    @property
    def articles(self):
        """
        articles getter
        """
        if self._articles is None:
            self._articles = []
            for doc in self.docs:
                self._articles.append(Article(**doc))
        return self._articles


class Article(object):
    """
    An object to represent a single record in NASA's Astrophysical
    Data System.
    """

    def __init__(self, **kwargs):
        """
        :param kwargs: Set object attributes from kwargs
        """

        if "id" not in kwargs:
            warnings.warn(
                "No article id found -- on-demand attribute lookup will fail",
                RuntimeWarning
            )

        self._raw = kwargs
        for key, value in six.iteritems(kwargs):
            setattr(self, key, value)

    def __str__(self):
        return self.__unicode__() if PY3 else self.__unicode__().encode("utf-8")
        
    def __unicode__(self):
        author = self.first_author or "Unknown author"
        if self.author and len(self.author) > 1:
            author += " et al."

        return u"<{author} {year}, {bibcode}>".format(
            author=author,
            year=self.year,
            bibcode=self.bibcode,
        )

    def __eq__(self, other):
        if not hasattr(self, 'bibcode') or not hasattr(other, 'bibcode') or \
                self.bibcode is None or other.bibcode is None:
            raise TypeError("Cannot compare articles without bibcodes")
        return self.bibcode == other.bibcode

    def __ne__(self, other):
        return not self.__eq__(other)

    def keys(self):
        return self._raw.keys()

    def items(self):
        return self._raw.items()

    def iteritems(self):
        return six.iteritems(self._raw)
{'fraction_non_alphanumeric': 0.09485491343574738, 'fraction_numerical': 0.00121921482565228, 'mean_word_length': 2.169629057187017, 'pattern_counts': {'":': 6, '<': 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': '3768386', 'n_tokens_mistral': 2261, 'n_tokens_neox': 2169, 'n_words': 663}