Repository: bokeh/bokeh

Issue:
Python 2 incompatibility issue with execfile and bokeh server
I have a bokeh server dashboard written in Python 2.  It includes the use of `print` as a statement.  When run by itself via `bokeh serve --show step3.py`, it runs just fine.

I then write a second script `step4.py` which uses `execfile()` on the first script, and then adds some additional logic of its own.  Now I encounter a very strange problem:

```
2016-12-20 07:52:02,473 Error running application handler <bokeh.application.handlers.script.ScriptHandler object at 0x10bb20f50>: invalid syntax (step3.py, line 41)
File "step4.py", line 3, in <module>:
execfile("step3.py") Traceback (most recent call last):
  File "/Users/pwang/anaconda/envs/bokehdemo/lib/python2.7/site-packages/bokeh/application/handlers/code_runner.py", line 83, in run
    exec(self._code, module.__dict__)
  File "/Users/pwang/src/bokeh.demo/webinar/demo1/step4.py", line 3, in <module>
    execfile("step3.py")
  File "step3.py", line 41
    print attribute, "changed from '%s' to '%s'" % (old, new)
                  ^
SyntaxError: invalid syntax
```

I can verify that this is a `print` statement-related SyntaxError because if I put parentheses around this line, everything works fine.  An additional interesting point of information is that in `step4.py` itself, I can put a `print` statement *before* the `execfile("step3.py")` call, and it works just fine.

So somehow, the logic in `code_runner` isn't accounting for `execfile()` behavior...?  Or perhaps the import of `print_function` at the top of `bokeh.application.handlers.code_runner` is screwing things up?

I'll attach the relevant files later (they're being worked on right now).


Discussion:
> Or perhaps the import of print_function at the top of bokeh.application.handlers.code_runner is screwing things up? 

There's an easy one-character way to test that hypothesis.  :) If that one change solves it, we can probably just comment it there out with a comment why. If not (is `print_function` scoped to modules? Or is an import anywhere some kind of global flag to the interpreter?), then I'm not sure there is anything that can be done. 

Resolving patch:
diff --git a/bokeh/application/handlers/code_runner.py b/bokeh/application/handlers/code_runner.py
--- a/bokeh/application/handlers/code_runner.py
+++ b/bokeh/application/handlers/code_runner.py
@@ -20,7 +20,7 @@ def __init__(self, source, path, argv):
 
         try:
             nodes = ast.parse(source, path)
-            self._code = compile(nodes, filename=path, mode='exec')
+            self._code = compile(nodes, filename=path, mode='exec', dont_inherit=True)
         except SyntaxError as e:
             self._failed = True
             self._error = ("Invalid syntax in \"%s\" on line %d:\n%s" % (os.path.basename(e.filename), e.lineno, e.text))


Test patch:
diff --git a/bokeh/application/handlers/tests/test_code.py b/bokeh/application/handlers/tests/test_code.py
--- a/bokeh/application/handlers/tests/test_code.py
+++ b/bokeh/application/handlers/tests/test_code.py
@@ -5,6 +5,8 @@
 from bokeh.application.handlers import CodeHandler
 from bokeh.document import Document
 
+from bokeh.util.testing import skipIfPy3
+
 script_adds_two_roots = """
 from bokeh.io import curdoc
 from bokeh.model import Model
@@ -32,6 +34,16 @@ def test_empty_script(self):
 
         assert not doc.roots
 
+    @skipIfPy3("this test doesn't have a Python 3 equivalent")
+    def test_exec_and___future___flags(self):
+        doc = Document()
+        handler = CodeHandler(source="exec(\"print \\\"XXX\\\"\")", filename="path/to/test_filename")
+        handler.modify_document(doc)
+        if handler.failed:
+            raise RuntimeError(handler.error)
+
+        assert not doc.roots
+
     def test_script_adds_roots(self):
         doc = Document()
         handler = CodeHandler(source=script_adds_two_roots, filename="path/to/test_filename")