def default()

in src/python/pants/base/hash_utils.py [0:0]


  def default(self, o):
    if self._is_natively_encodable(o):
      # isinstance() checks are expensive, particularly for abstract base classes such as Mapping:
      # https://stackoverflow.com/questions/42378726/why-is-checking-isinstancesomething-mapping-so-slow
      # This means that, if we let natively encodable types all through, we incur a performance hit, since
      # we call this function very often.
      # TODO(#7658) Figure out why we call this function so often.
      return o
    if isinstance(o, Mapping):
      # Preserve order to avoid collisions for OrderedDict inputs to json.dumps(). We don't do this
      # for general mappings because dicts have an arbitrary key ordering in some versions of python
      # 3 (2.7 and 3.6-3.7 are known to have sorted keys, but with different definitions of sorted
      # orders across versions, including insertion order). We want unordered dicts to collide if
      # they have the same keys, in the same way we special-case sets below. Calling sorted() should
      # be very fast if the keys happen to be pre-sorted. Pants options don't support OrderedDict
      # inputs, and allowing them creates an ambiguity we don't need to deal with right now. See
      # discussion in #6475.
      if isinstance(o, OrderedDict):
        raise TypeError('{cls} does not support OrderedDict inputs: {val!r}.'
                        .format(cls=type(self).__name__, val=o))
      # TODO(#7082): we can remove the sorted() and OrderedDict when we drop python 2.7 and simply
      # ensure we encode the keys/values as we do right here.
      ordered_kv_pairs = sorted(o.items(), key=lambda x: x[0])
      return OrderedDict(
        (self._maybe_encode_dict_key(k), self.default(v))
        for k, v in ordered_kv_pairs)
    if isinstance(o, Set):
      # We disallow OrderedSet (although it is not a stdlib collection) for the same reasons as
      # OrderedDict above.
      if isinstance(o, OrderedSet):
        raise TypeError('{cls} does not support OrderedSet inputs: {val!r}.'
                        .format(cls=type(self).__name__, val=o))
      # Set order is arbitrary in python 3.6 and 3.7, so we need to keep this sorted() call.
      return sorted(self.default(i) for i in o)
    if isinstance(o, DatatypeMixin):
      # datatype objects will intentionally raise in the __iter__ method, but the Iterable abstract
      # base class will match any class with any superclass that has the attribute __iter__ in the
      # __dict__ (see https://docs.python.org/2/library/abc.html), so we need to check for it
      # specially here.
      # TODO: determine if the __repr__ should be some abstractmethod on DatatypeMixin!
      return self.default(repr(o))
    if isinstance(o, Iterable) and not isinstance(o, (bytes, list, str)):
      return list(self.default(i) for i in o)
    logger.debug("Our custom json encoder {} is trying to hash a primitive type, but has gone through"
                 "checking every other registered type class before. These checks are expensive,"
                 "so you should consider registering the type {} within"
                 "this function ({}.default)".format(type(self).__name__, type(o), type(self).__name__))
    return o