1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from __future__ import absolute_import
6from __future__ import division
7from __future__ import print_function
8import re
9import six
10
11
12def ToUnderscore(obj):
13  """Converts a string, list, or dict from camelCase to lower_with_underscores.
14
15  Descends recursively into lists and dicts, converting all dict keys.
16  Returns a newly allocated object of the same structure as the input.
17  """
18  if isinstance(obj, six.string_types):
19    return re.sub('(?!^)([A-Z]+)', r'_\1', obj).lower()
20
21  elif isinstance(obj, list):
22    return [ToUnderscore(item) for item in obj]
23
24  elif isinstance(obj, dict):
25    output = {}
26    for k, v in six.iteritems(obj):
27      if isinstance(v, list) or isinstance(v, dict):
28        output[ToUnderscore(k)] = ToUnderscore(v)
29      else:
30        output[ToUnderscore(k)] = v
31    return output
32
33  else:
34    return obj
35