mercurial/utils/stringutil.py
changeset 37290 cc5a040fe150
parent 37247 2ed180117f76
child 37300 2f859ad7ed8c
--- a/mercurial/utils/stringutil.py	Mon Mar 26 13:59:56 2018 -0700
+++ b/mercurial/utils/stringutil.py	Wed Mar 28 15:05:39 2018 -0700
@@ -9,6 +9,7 @@
 
 from __future__ import absolute_import
 
+import __future__
 import codecs
 import re as remod
 import textwrap
@@ -497,3 +498,29 @@
     If s is not a valid boolean, returns None.
     """
     return _booleans.get(s.lower(), None)
+
+def evalpython(s):
+    """Evaluate a string containing a Python expression.
+
+    THIS FUNCTION IS NOT SAFE TO USE ON UNTRUSTED INPUT. IT'S USE SHOULD BE
+    LIMITED TO DEVELOPER-FACING FUNCTIONALITY.
+    """
+    globs = {
+        r'__builtins__': {
+            r'None': None,
+            r'False': False,
+            r'True': True,
+            r'int': int,
+            r'set': set,
+            r'tuple': tuple,
+            # Don't need to expose dict and list because we can use
+            # literals.
+        },
+    }
+
+    # We can't use eval() directly because it inherits compiler
+    # flags from this module and we need unicode literals for Python 3
+    # compatibility.
+    code = compile(s, r'<string>', r'eval',
+                   __future__.unicode_literals.compiler_flag, True)
+    return eval(code, globs, {})