# Path: marathon/util.py
# def to_camel_case(snake_str):
#     words = snake_str.split('_')
#     return words[0] + ''.join(w.capitalize() for w in words[1:])
# 
# def to_snake_case(camel_str):
#     s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
#     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
# 
# class MarathonJsonEncoder(json.JSONEncoder):
# 
#     """Custom JSON encoder for Marathon object serialization."""
# 
#     def default(self, obj):
#         if hasattr(obj, 'json_repr'):
#             return self.default(obj.json_repr())
# 
#         if isinstance(obj, datetime.datetime):
#             return obj.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# 
#         if isinstance(obj, collections.Iterable) and not isinstance(obj, str):
#             try:
#                 return {k: self.default(v) for k, v in obj.items()}
#             except AttributeError:
#                 return [self.default(e) for e in obj]
# 
#         return obj
# 
# class MarathonMinimalJsonEncoder(json.JSONEncoder):
# 
#     """Custom JSON encoder for Marathon object serialization."""
# 
#     def default(self, obj):
#         if hasattr(obj, 'json_repr'):
#             return self.default(obj.json_repr(minimal=True))
# 
#         if isinstance(obj, datetime.datetime):
#             return obj.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# 
#         if isinstance(obj, collections.Iterable) and not isinstance(obj, str):
#             try:
#                 return {k: self.default(v) for k, v in obj.items() if (v or v in (False, 0))}
#             except AttributeError:
#                 return [self.default(e) for e in obj if (e or e in (False, 0))]
# 
#         return obj


import json
import re
from marathon.util import to_camel_case, to_snake_case, MarathonJsonEncoder, MarathonMinimalJsonEncoder


class MarathonObject:
    """Base Marathon object."""

    def __repr__(self):
        return "{clazz}::{obj}".format(clazz=self.__class__.__name__, obj=self.to_json(minimal=False))

    def __eq__(self, other):
        try:
            return self.__dict__ == other.__dict__
        except Exception:
            return False

    def __hash__(self):
        # Technically this class shouldn't be hashable because it often
        # contains mutable fields, but in practice this class is used more
        # like a record or namedtuple.
        return hash(self.to_json())

    def json_repr(self, minimal=False):
        """Construct a JSON-friendly representation of the object.

        :param bool minimal: Construct a minimal representation of the object (ignore nulls and empty collections)

        :rtype: dict
        """
        if minimal:
            return {to_camel_case(k): v for k, v in vars(self).items() if (v or v is False or v == 0)}
        else:

# Path: marathon/util.py
# def to_camel_case(snake_str):
#     words = snake_str.split('_')
#     return words[0] + ''.join(w.capitalize() for w in words[1:])
# 
# def to_snake_case(camel_str):
#     s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
#     return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
# 
# class MarathonJsonEncoder(json.JSONEncoder):
# 
#     """Custom JSON encoder for Marathon object serialization."""
# 
#     def default(self, obj):
#         if hasattr(obj, 'json_repr'):
#             return self.default(obj.json_repr())
# 
#         if isinstance(obj, datetime.datetime):
#             return obj.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# 
#         if isinstance(obj, collections.Iterable) and not isinstance(obj, str):
#             try:
#                 return {k: self.default(v) for k, v in obj.items()}
#             except AttributeError:
#                 return [self.default(e) for e in obj]
# 
#         return obj
# 
# class MarathonMinimalJsonEncoder(json.JSONEncoder):
# 
#     """Custom JSON encoder for Marathon object serialization."""
# 
#     def default(self, obj):
#         if hasattr(obj, 'json_repr'):
#             return self.default(obj.json_repr(minimal=True))
# 
#         if isinstance(obj, datetime.datetime):
#             return obj.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# 
#         if isinstance(obj, collections.Iterable) and not isinstance(obj, str):
#             try:
#                 return {k: self.default(v) for k, v in obj.items() if (v or v in (False, 0))}
#             except AttributeError:
#                 return [self.default(e) for e in obj if (e or e in (False, 0))]
# 
#         return obj


# Path: marathon/models/base.py
import json
import re
from marathon.util import to_camel_case, to_snake_case, MarathonJsonEncoder, MarathonMinimalJsonEncoder



class MarathonObject:
    """Base Marathon object."""

    def __repr__(self):
        return "{clazz}::{obj}".format(clazz=self.__class__.__name__, obj=self.to_json(minimal=False))

    def __eq__(self, other):
        try:
            return self.__dict__ == other.__dict__
        except Exception:
            return False

    def __hash__(self):
        # Technically this class shouldn't be hashable because it often
        # contains mutable fields, but in practice this class is used more
        # like a record or namedtuple.
        return hash(self.to_json())

    def json_repr(self, minimal=False):
        """Construct a JSON-friendly representation of the object.

        :param bool minimal: Construct a minimal representation of the object (ignore nulls and empty collections)

        :rtype: dict
        """
        if minimal:
            return {to_camel_case(k): v for k, v in vars(self).items() if (v or v is False or v == 0)}
        else:

            return {to_camel_case(k): v for k, v in vars(self).items()}