fixdictsformatting.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. from __future__ import unicode_literals
  2. import sys
  3. from lib2to3.pytree import Node, Leaf
  4. from lib2to3.fixer_util import token, syms
  5. from yapf.yapflib import pytree_utils
  6. from django.utils import six
  7. def fix_formatting(filesource):
  8. if not ('{' in filesource and ('[' in filesource or '(' in filesource)):
  9. return filesource
  10. tree = pytree_utils.ParseCodeToTree(filesource)
  11. for node in tree.children:
  12. walk_tree(node, node.children)
  13. return six.text_type(tree)
  14. def walk_tree(node, children):
  15. for item in children:
  16. if item.type == syms.dictsetmaker:
  17. walk_dict_tree(item, item.children)
  18. else:
  19. walk_tree(item, item.children)
  20. def walk_dict_tree(node, children):
  21. for item in children:
  22. prev = item.prev_sibling
  23. if isinstance(prev, Leaf) and prev.value == ':':
  24. if isinstance(item, Leaf):
  25. if six.text_type(item).startswith("\n"):
  26. # first case: intended string
  27. item.replace(Leaf(
  28. item.type,
  29. item.value,
  30. prefix=' ',
  31. ))
  32. elif six.text_type(item).strip()[0] in ('[', '{'):
  33. walk_tree(item, item.children)
  34. else:
  35. walk_dedent_tree(item, item.children)
  36. def walk_dedent_tree(node, children):
  37. for item in children:
  38. prev = item.prev_sibling
  39. if not prev:
  40. if isinstance(item, Leaf) and six.text_type(item).startswith("\n"):
  41. # first case: intended string
  42. item.replace(Leaf(
  43. item.type,
  44. item.value,
  45. prefix=' ',
  46. ))
  47. elif isinstance(item, Node):
  48. for subitem in item.children[1:]:
  49. walk_dedent_tree_node(subitem, subitem.children)
  50. def walk_dedent_tree_node(node, children):
  51. if six.text_type(node).startswith("\n"):
  52. if isinstance(node, Leaf):
  53. prev = node.prev_sibling
  54. is_followup = prev and prev.type == token.STRING and node.type == token.STRING
  55. if is_followup:
  56. new_prefix = "\n%s" % (' ' * (len(prev.prefix.lstrip("\n")) / 4 * 4))
  57. node.replace(Leaf(
  58. node.type,
  59. "%s\n%s" % (node.value, (' ' * ((len(prev.prefix.lstrip("\n")) / 4 - 1) * 4))),
  60. prefix=new_prefix,
  61. ))
  62. else:
  63. node.replace(Leaf(
  64. node.type,
  65. node.value,
  66. prefix=node.prefix[:-4],
  67. ))
  68. else:
  69. for item in children:
  70. walk_dedent_tree_node(item, item.children)
  71. elif isinstance(node, Leaf):
  72. if node.type == token.STRING:
  73. prev = node.prev_sibling
  74. next = node.next_sibling
  75. is_opening = prev is None and six.text_type(node.parent.parent).strip()[0] == '('
  76. has_followup = next and next.type == token.STRING
  77. if is_opening and has_followup:
  78. new_prefix = "\n%s" % (' ' * (len(next.prefix.lstrip("\n")) / 4 * 4))
  79. node.replace(Leaf(
  80. node.type,
  81. node.value,
  82. prefix=new_prefix,
  83. ))
  84. else:
  85. for item in children:
  86. walk_dedent_tree_node(item, item.children)