<commit_before># Tweepy
# Copyright 2009-2021 <NAME>
# See LICENSE for details.

from email.utils import parsedate_to_datetime

from tweepy.mixins import Hashable


class ResultSet(list):
    """A list like object that holds results from a Twitter API query."""
    def __init__(self, max_id=None, since_id=None):
        super().__init__()
        self._max_id = max_id
        self._since_id = since_id

    @property
    def max_id(self):
        if self._max_id:
            return self._max_id
        ids = self.ids()
        # Max_id is always set to the *smallest* id, minus one, in the set
        return (min(ids) - 1) if ids else None

    @property
    def since_id(self):
        if self._since_id:
            return self._since_id
        ids = self.ids()
        # Since_id is always set to the *greatest* id in the set
        return max(ids) if ids else None

    def ids(self):
        return [item.id for item in self if hasattr(item, 'id')]


class Model:

    def __init__(self, api=None):
        self._api = api

    def __getstate__(self):
        # pickle
        pickle = dict(self.__dict__)
        try:
            del pickle['_api']  # do not pickle the API reference
        except KeyError:
            pass
        return pickle

    @classmethod
    def parse(cls, api, json):
        """Parse a JSON object into a model instance."""
        raise NotImplementedError

    @classmethod
    def parse_list(cls, api, json_list):
        """
            Parse a list of JSON objects into
            a result set of model instances.
        """
        results = ResultSet()

        if isinstance(json_list, dict):
            # Handle map parameter for statuses/lookup
            if 'id' in json_list:
                for _id, obj in json_list['id'].items():
                    if obj:
                        results.append(cls.parse(api, obj))
                    else:
                        results.append(cls.parse(api, {'id': int(_id)}))
                return results
            # Handle premium search
            if 'results' in json_list:
                json_list = json_list['results']

        for obj in json_list:
            if obj:
                results.append(cls.parse(api, obj))
        return results

    def __repr__(self):
        state = [f'{k}={v!r}' for (k, v) in vars(self).items()]
        return f'{self.__class__.__name__}({", ".join(state)})'


class Status(Model, Hashable):

    @classmethod
    def parse(cls, api, json):
        status = cls(api)
        setattr(status, '_json', json)
        for k, v in json.items():
            if k == 'user':
                user_model = getattr(api.parser.model_factory, 'user') if api else User
                user = user_model.parse(api, v)
                setattr(status, 'author', user)
                setattr(status, 'user', user)  # DEPRECIATED
            elif k == 'created_at':
                setattr(status, k, parsedate_to_datetime(v))
            elif k == 'source':
                if '<' in v:
                    # At this point, v should be of the format:
                    # <a href="{source_url}" rel="nofollow">{source}</a>
                    setattr(status, k, v[v.find('>') + 1:v.rfind('<')])<commit_msg>Default to User model in Status.parse more broadly for user attribute<commit_after># Tweepy
# Copyright 2009-2021 <NAME>
# See LICENSE for details.

from email.utils import parsedate_to_datetime

from tweepy.mixins import Hashable


class ResultSet(list):
    """A list like object that holds results from a Twitter API query."""
    def __init__(self, max_id=None, since_id=None):
        super().__init__()
        self._max_id = max_id
        self._since_id = since_id

    @property
    def max_id(self):
        if self._max_id:
            return self._max_id
        ids = self.ids()
        # Max_id is always set to the *smallest* id, minus one, in the set
        return (min(ids) - 1) if ids else None

    @property
    def since_id(self):
        if self._since_id:
            return self._since_id
        ids = self.ids()
        # Since_id is always set to the *greatest* id in the set
        return max(ids) if ids else None

    def ids(self):
        return [item.id for item in self if hasattr(item, 'id')]


class Model:

    def __init__(self, api=None):
        self._api = api

    def __getstate__(self):
        # pickle
        pickle = dict(self.__dict__)
        try:
            del pickle['_api']  # do not pickle the API reference
        except KeyError:
            pass
        return pickle

    @classmethod
    def parse(cls, api, json):
        """Parse a JSON object into a model instance."""
        raise NotImplementedError

    @classmethod
    def parse_list(cls, api, json_list):
        """
            Parse a list of JSON objects into
            a result set of model instances.
        """
        results = ResultSet()

        if isinstance(json_list, dict):
            # Handle map parameter for statuses/lookup
            if 'id' in json_list:
                for _id, obj in json_list['id'].items():
                    if obj:
                        results.append(cls.parse(api, obj))
                    else:
                        results.append(cls.parse(api, {'id': int(_id)}))
                return results
            # Handle premium search
            if 'results' in json_list:
                json_list = json_list['results']

        for obj in json_list:
            if obj:
                results.append(cls.parse(api, obj))
        return results

    def __repr__(self):
        state = [f'{k}={v!r}' for (k, v) in vars(self).items()]
        return f'{self.__class__.__name__}({", ".join(state)})'


class Status(Model, Hashable):

    @classmethod
    def parse(cls, api, json):
        status = cls(api)
        setattr(status, '_json', json)
        for k, v in json.items():
            if k == 'user':
                try:
                    user = api.parser.model_factory.user.parse(api, v)
                except AttributeError:
                    user = User.parse(api, v)
                setattr(status, 'author', user)
                setattr(status, 'user', user)  # DEPRECIATED
            elif k == 'created_at':
                setattr(status, k, parsedate_to_datetime(v))
            elif k == 'source':
                if '<' in v:
                    # At this point, v should be of the format:
                    # <a href="{source_url}" rel="nofollow">{source}</a>
                    setattr(status, k, v[v.find('>') + 1:v.rfind('<')])
{'fraction_non_alphanumeric': 0.10638943694035513, 'fraction_numerical': 0.0030353619669145544, 'mean_word_length': 1.7561689669594311, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 11, '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': '1255050', 'n_tokens_mistral': 1962, 'n_tokens_neox': 1874, 'n_words': 590}