[Differential] [Request, 82 lines] D76: contrib: add a codemod script to rewrite nested with

quark (Jun Wu) phabricator at mercurial-scm.org
Fri Jul 14 01:35:30 UTC 2017


quark created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The codemod script rewrites nested with with a single with if the code could
  be put in one line (80 chars).

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D76

AFFECTED FILES
  contrib/codemod/codemod_nestedwith.py

CHANGE DETAILS

Index: contrib/codemod/codemod_nestedwith.py
===================================================================
--- /dev/null
+++ contrib/codemod/codemod_nestedwith.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# codemod_nestedwith.py - codemod tool to rewrite nested with
+#
+# Copyright 2017 Facebook, Inc.
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+from __future__ import absolute_import, print_function
+
+import sys
+
+import redbaron
+
+def readpath(path):
+    with open(path) as f:
+        return f.read()
+
+def writepath(path, content):
+    with open(path, 'w') as f:
+        f.write(content)
+
+def extractstring(rnode):
+    """get the string from a RedBaron string or call_argument node"""
+    while rnode.type != 'string':
+        rnode = rnode.value
+    return rnode.value[1:-1]  # unquote, "'str'" -> "str"
+
+def nestedwithitems(red):
+    """match nested withs, yield (node, innernode, level)"""
+    visited = set()
+    for node in red.find_all('with'):
+        if node in visited:
+            continue
+        entry = None
+        level = 0
+        cur = node
+        try:
+            while True:
+                if cur.type == 'with':
+                    visited.add(cur)
+                    level += 1
+                    cur = cur[0]
+                else:
+                    break
+            if level > 1:
+                entry = (node, level)
+        except Exception:
+            raise
+            #pass
+        else:
+            if entry:
+                yield entry
+
+def main(argv):
+    if not argv:
+        print('Usage: codemod_nestedwith.py FILES\n')
+
+    # first loop: scan all files before taking any action
+    for i, path in enumerate(argv):
+        print('(%d/%d) scanning %s' % (i + 1, len(argv), path))
+        changed = False
+        red = redbaron.RedBaron(readpath(path))
+
+        for node, level in nestedwithitems(red):
+            while level > 1:
+                # estimate line length after merging two "with"s
+                new = '%swith %s:' % (node.indentation, node.contexts.dumps())
+                new += ', %s' % node[0].contexts.dumps()
+                # only do the rewrite if the end result is within 80 chars
+                if len(new) > 80:
+                    break
+                node.contexts.append(node[0].contexts)
+                node.value = node[0].value
+                node.value.decrease_indentation(4)
+                level -= 1
+                changed = True
+        if changed:
+            print('updating %s' % path)
+            writepath(path, red.dumps())
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv[1:]))


EMAIL PREFERENCES
  https://phab.mercurial-scm.org/settings/panel/emailpreferences/

To: quark, #hg-reviewers
Cc: mercurial-devel, indygreg


More information about the Mercurial-devel mailing list