<commit_before>"""
Entity classes for representing the various Strava datatypes.
"""
from __future__ import division, absolute_import, print_function, unicode_literals
import abc
import logging

import six

if six.PY2:
    from collections import Sequence
else:
    from collections.abc import Sequence

from stravalib import exc
from stravalib import unithelper as uh

from stravalib.attributes import (META, SUMMARY, DETAILED, Attribute,
                                  TimestampAttribute, LocationAttribute,
                                  EntityCollection, EntityAttribute,
                                  TimeIntervalAttribute, TimezoneAttribute,
                                  DateAttribute, ChoicesAttribute)


@six.add_metaclass(abc.ABCMeta)
class BaseEntity(object):
    """
    A base class for all entities in the system, including objects that may not
    be first-class entities in Strava.
    """

    def __init__(self, **kwargs):
        self.log = logging.getLogger('{0.__module__}.{0.__name__}'.format(self.__class__))
        self.from_dict(kwargs)

    def to_dict(self):
        """
        Create a dictionary based on the loaded attributes in this object (will not lazy load).

        Note that the dictionary created by this method will most likely not match the dictionaries
        that are passed to the `from_dict()` method.  This intended for serializing for local storage
        debug/etc.

        :rtype: Dict[str, Any]
        """
        d = {}
        for cls in self.__class__.__mro__:
            for attrname, attr in cls.__dict__.items():
                if attrname not in d and isinstance(attr, Attribute):
                    value = getattr(self, attrname)
                    d[attrname] = attr.marshal(value)
        return d

    def from_dict(self, d):
        """
        Populates this object from specified dict.

        Only defined attributes will be set; warnings will be logged for invalid attributes.
        """
        for (k, v) in d.items():
            # Handle special keys such as `hub.challenge` in `SubscriptionCallback`
            if '.' in k:
                k = k.replace('.', '_')
            # Only set defined attributes.
            if hasattr(self.__class__, k):
                self.log.debug("Setting attribute `{0}` [{1}] on entity {2} with value {3!r}".format(k, getattr(self.__class__, k).__class__.__name__, self, v))
                try:
                    setattr(self, k, v)
                except AttributeError as x:
                    raise AttributeError("Could not find attribute `{0}` on entity {1}, value: {2!r}.  (Original: {3!r})".format(k, self, v, x))
            else:
                self.log.debug("No such attribute {0} on entity {1}".format(k, self))

    @classmethod
    def deserialize(cls, v):
        """
        Creates a new object based on serialized (dict) struct.
        """
        o = cls()
        o.from_dict(v)
        return o

    def __repr__(self):
        attrs = []
        if hasattr(self.__class__, 'id'):
            attrs.append('id={0}'.format(self.id))
        if hasattr(self.__class__, 'name'):
            attrs.append('name={0!r}'.format(self.name))
        if hasattr(self.__class__, 'resource_state'):
            attrs.append('resource_state={0}'.format(self.resource_state))

        return '<{0} {1}>'.format(self.__class__.__name__, ' '.join(attrs))


class ResourceStateEntity(BaseEntity):
    """
    Mixin for entities that include the resource_state attribute.
    """
    resource_state = Attribute(int, (META, SUMMARY, DETAILED))  #: The detail-level for this entity.


class IdentifiableEntity(ResourceStateEntity):
    """
    Mixin for entities that include an ID attribute.
    """
    id = Attribute(int, (META, SUMMARY, DETAILED))  #: The numeric ID for this entity.


class BoundEntity(BaseEntity):
    """
    Base class for entities that support lazy loading additional data using a bound client.
    """
<commit_msg>Tweak __repr__ of BaseEntity objects<commit_after>"""
Entity classes for representing the various Strava datatypes.
"""
from __future__ import division, absolute_import, print_function, unicode_literals
import abc
import logging

import six

if six.PY2:
    from collections import Sequence
else:
    from collections.abc import Sequence

from stravalib import exc
from stravalib import unithelper as uh

from stravalib.attributes import (META, SUMMARY, DETAILED, Attribute,
                                  TimestampAttribute, LocationAttribute,
                                  EntityCollection, EntityAttribute,
                                  TimeIntervalAttribute, TimezoneAttribute,
                                  DateAttribute, ChoicesAttribute)


@six.add_metaclass(abc.ABCMeta)
class BaseEntity(object):
    """
    A base class for all entities in the system, including objects that may not
    be first-class entities in Strava.
    """

    def __init__(self, **kwargs):
        self.log = logging.getLogger('{0.__module__}.{0.__name__}'.format(self.__class__))
        self.from_dict(kwargs)

    def to_dict(self):
        """
        Create a dictionary based on the loaded attributes in this object (will not lazy load).

        Note that the dictionary created by this method will most likely not match the dictionaries
        that are passed to the `from_dict()` method.  This intended for serializing for local storage
        debug/etc.

        :rtype: Dict[str, Any]
        """
        d = {}
        for cls in self.__class__.__mro__:
            for attrname, attr in cls.__dict__.items():
                if attrname not in d and isinstance(attr, Attribute):
                    value = getattr(self, attrname)
                    d[attrname] = attr.marshal(value)
        return d

    def from_dict(self, d):
        """
        Populates this object from specified dict.

        Only defined attributes will be set; warnings will be logged for invalid attributes.
        """
        for (k, v) in d.items():
            # Handle special keys such as `hub.challenge` in `SubscriptionCallback`
            if '.' in k:
                k = k.replace('.', '_')
            # Only set defined attributes.
            if hasattr(self.__class__, k):
                self.log.debug("Setting attribute `{0}` [{1}] on entity {2} with value {3!r}".format(k, getattr(self.__class__, k).__class__.__name__, self, v))
                try:
                    setattr(self, k, v)
                except AttributeError as x:
                    raise AttributeError("Could not find attribute `{0}` on entity {1}, value: {2!r}.  (Original: {3!r})".format(k, self, v, x))
            else:
                self.log.debug("No such attribute {0} on entity {1}".format(k, self))

    @classmethod
    def deserialize(cls, v):
        """
        Creates a new object based on serialized (dict) struct.
        """
        o = cls()
        o.from_dict(v)
        return o

    def __repr__(self):
        attrs = []
        if hasattr(self.__class__, 'id'):
            attrs.append('id={0}'.format(self.id))
        if hasattr(self.__class__, 'name'):
            attrs.append('name={0!r}'.format(self.name))
        if hasattr(self.__class__, 'resource_state') and self.resource_state is not None:
            attrs.append('resource_state={0}'.format(self.resource_state))

        return '<{0}{1}>'.format(self.__class__.__name__, ' ' + ' '.join(attrs) if attrs else '')


class ResourceStateEntity(BaseEntity):
    """
    Mixin for entities that include the resource_state attribute.
    """
    resource_state = Attribute(int, (META, SUMMARY, DETAILED))  #: The detail-level for this entity.


class IdentifiableEntity(ResourceStateEntity):
    """
    Mixin for entities that include an ID attribute.
    """
    id = Attribute(int, (META, SUMMARY, DETAILED))  #: The numeric ID for this entity.


class BoundEntity(BaseEntity):
    """
    Base class for entities that support lazy loading additional data using a bound client.
    """

{'fraction_non_alphanumeric': 0.1021752641392169, 'fraction_numerical': 0.004474829086389061, 'mean_word_length': 2.2961900860303155, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3665454', 'n_tokens_mistral': 2226, 'n_tokens_neox': 2142, 'n_words': 709}