Repository: altair-viz/altair
Pull request #665 (2018-03-27 21:52:25)

Change examples so that they work when directly pasted into notebook
suggested by @mroswell 

This took a little doing:

- I moved the ``exec_then_eval`` utility from sphinxext into ``altair.utils``, renamed it to ``eval_block``, and added some simple tests
- I changed all examples so that the last statement of each evaluates to a chart object
- I updated example unit tests to use ``eval_block`` to properly extract example charts
- I updated sphinx doc generation to properly display the new examples

I generated the HTML pages locally, and everything seemed to work.


Patch:
diff --git a/altair/sphinxext/altairgallery.py b/altair/sphinxext/altairgallery.py
index 6597a51c..b729b40f 100644
--- a/altair/sphinxext/altairgallery.py
+++ b/altair/sphinxext/altairgallery.py
@@ -19,6 +19,7 @@ from docutils.parsers.rst.directives import flag
 from sphinx.util.nodes import nested_parse_with_titles
 
 from .utils import get_docstring_and_rest, prev_this_next, create_thumbnail
+from altair.utils.execeval import eval_block
 from altair.vegalite.v2.examples import iter_examples
 
 
@@ -88,7 +89,6 @@ EXAMPLE_TEMPLATE = jinja2.Template(u"""
 {{ docstring }}
 
 .. altair-plot::
-    :chart-var-name: chart
     {% if code_below %}:code-below:{% endif %}
 
     {{ code | indent(4) }}
@@ -118,14 +118,13 @@ def save_example_pngs(examples, image_dir, make_thumbnails=True):
 
         example_hash = hashlib.md5(example['code'].encode()).hexdigest()
         hashes_match = (hashes.get(filename, '') == example_hash)
-        print('-> using cached {0}'.format(image_file))
 
-        if not hashes_match or not os.path.exists(image_file):
+        if hashes_match and os.path.exists(image_file):
+            print('-> using cached {0}'.format(image_file))
+        else:
             # the file changed or the image file does not exist. Generate it.
             print('-> saving {0}'.format(image_file))
-            _globals = {}
-            exec(example['code'], _globals)
-            chart = _globals['chart']
+            chart = eval_block(example['code'])
             chart.save(image_file)
             hashes[filename] = example_hash
 
diff --git a/altair/sphinxext/altairplot.py b/altair/sphinxext/altairplot.py
index f5fd5806..02ae00dc 100644
--- a/altair/sphinxext/altairplot.py
+++ b/altair/sphinxext/altairplot.py
@@ -69,7 +69,7 @@ from sphinx import addnodes, directives
 from sphinx.util.nodes import set_source_info
 
 import altair as alt
-from .utils import exec_then_eval
+from altair.utils.execeval import eval_block
 
 # These default URLs can be changed in conf.py; see setup() below.
 VEGA_JS_URL_DEFAULT = "https://cdn.jsdelivr.net/npm/vega@3"
@@ -205,7 +205,7 @@ def html_visit_altair_plot(self, node):
     try:
         f = io.StringIO()
         with contextlib.redirect_stdout(f):
-            chart = exec_then_eval(node['code'], namespace)
+            chart = eval_block(node['code'], namespace)
         stdout = f.getvalue()
     except Exception as e:
         warnings.warn("altair-plot: {0}:{1} Code Execution failed:"
diff --git a/altair/sphinxext/utils.py b/altair/sphinxext/utils.py
index 29f6bcec..b9b4eb11 100644
--- a/altair/sphinxext/utils.py
+++ b/altair/sphinxext/utils.py
@@ -28,56 +28,6 @@ def create_thumbnail(image_filename, thumb_filename, window_size=(144, 80)):
     thumb.save(thumb_filename)
 
 
-class _CatchDisplay(object):
-    """Class to temporarily catch sys.displayhook"""
-    def __init__(self):
-        self.output = None
-
-    def __enter__(self):
-        self.old_hook = sys.displayhook
-        sys.displayhook = self
-        return self
-
-    def __exit__(self, type, value, traceback):
-        sys.displayhook = self.old_hook
-        # Returning False will cause exceptions to propagate
-        return False
-
-    def __call__(self, output):
-        self.output = output
-
-
-def exec_then_eval(code, namespace=None, filename='<string>'):
-    """
-    Execute a multi-line block of code in the given namespace
-
-    If the final statement in the code is an expression, return
-    the result of the expression.
-    """
-    tree = ast.parse(code, filename='<ast>', mode='exec')
-    if namespace is None:
-        namespace = {}
-    catch_display = _CatchDisplay()
-
-    if isinstance(tree.body[-1], ast.Expr):
-        to_exec, to_eval = tree.body[:-1], tree.body[-1:]
-    else:
-        to_exec, to_eval = tree.body, []
-
-    for node in to_exec:
-        compiled = compile(ast.Module([node]),
-                           filename=filename, mode='exec')
-        exec(compiled, namespace)
-
-    with catch_display:
-        for node in to_eval:
-            compiled = compile(ast.Interactive([node]),
-                               filename=filename, mode='single')
-            exec(compiled, namespace)
-
-    return catch_display.output
-
-
 SYNTAX_ERROR_DOCSTRING = """
 SyntaxError
 ===========
diff --git a/altair/utils/execeval.py b/altair/utils/execeval.py
new file mode 100644
index 00000000..a3edd985
--- /dev/null
+++ b/altair/utils/execeval.py
@@ -0,0 +1,52 @@
+import ast
+import sys
+
+
+class _CatchDisplay(object):
+    """Class to temporarily catch sys.displayhook"""
+    def __init__(self):
+        self.output = None
+
+    def __enter__(self):
+        self.old_hook = sys.displayhook
+        sys.displayhook = self
+        return self
+
+    def __exit__(self, type, value, traceback):
+        sys.displayhook = self.old_hook
+        # Returning False will cause exceptions to propagate
+        return False
+
+    def __call__(self, output):
+        self.output = output
+
+
+def eval_block(code, namespace=None, filename='<string>'):
+    """
+    Execute a multi-line block of code in the given namespace
+
+    If the final statement in the code is an expression, return
+    the result of the expression.
+    """
+    tree = ast.parse(code, filename='<ast>', mode='exec')
+    if namespace is None:
+        namespace = {}
+    catch_display = _CatchDisplay()
+
+    if isinstance(tree.body[-1], ast.Expr):
+        to_exec, to_eval = tree.body[:-1], tree.body[-1:]
+    else:
+        to_exec, to_eval = tree.body, []
+
+    for node in to_exec:
+        compiled = compile(ast.Module([node]),
+                           filename=filename, mode='exec')
+        exec(compiled, namespace)
+
+    with catch_display:
+        for node in to_eval:
+            compiled = compile(ast.Interactive([node]),
+                               filename=filename, mode='single')
+            exec(compiled, namespace)
+
+    return catch_display.output
diff --git a/altair/vegalite/v2/examples/aggregate_bar_chart.py b/altair/vegalite/v2/examples/aggregate_bar_chart.py
index e2aacddd..d1048258 100644
--- a/altair/vegalite/v2/examples/aggregate_bar_chart.py
+++ b/altair/vegalite/v2/examples/aggregate_bar_chart.py
@@ -11,10 +11,12 @@ from altair.expr import datum
 from vega_datasets import data
 pop = data.population.url
 
-chart = alt.Chart(pop).mark_bar().encode(
+alt.Chart(pop).mark_bar().encode(
     x = alt.X('sum(people):Q', axis=alt.Axis(title='population')),
     y = 'age:O'
 ).properties(
     height=300,
     width=300
-).transform_filter(datum.year == 2000)
+).transform_filter(
+    datum.year == 2000
+)
diff --git a/altair/vegalite/v2/examples/airports.py b/altair/vegalite/v2/examples/airports.py
index 2e18be4e..fba0cfec 100644
--- a/altair/vegalite/v2/examples/airports.py
+++ b/altair/vegalite/v2/examples/airports.py
@@ -29,4 +29,4 @@ points = alt.Chart(airports).mark_circle().encode(
     color=alt.value('steelblue')
 )
 
-chart = background + points
+background + points
diff --git a/altair/vegalite/v2/examples/anscombe_plot.py b/altair/vegalite/v2/examples/anscombe_plot.py
index f8ae4551..1a1a3f03 100644
--- a/altair/vegalite/v2/examples/anscombe_plot.py
+++ b/altair/vegalite/v2/examples/anscombe_plot.py
@@ -10,9 +10,9 @@ from vega_datasets import data
 
 anscombe = data.anscombe()
 
-chart = alt.Chart(anscombe).mark_circle().encode(
+alt.Chart(anscombe).mark_circle().encode(
     alt.X('X', scale=alt.Scale(zero=False)),
-    alt.Y('Y', scale=alt.Scale(zero=False)), 
+    alt.Y('Y', scale=alt.Scale(zero=False)),
     column='Series'
 ).properties(
     width=150,
diff --git a/altair/vegalite/v2/examples/bar.py b/altair/vegalite/v2/examples/bar.py
index 925ec22f..91e34f99 100644
--- a/altair/vegalite/v2/examples/bar.py
+++ b/altair/vegalite/v2/examples/bar.py
@@ -12,7 +12,7 @@ data = pd.DataFrame({
     'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
 })
 
-chart = alt.Chart(data).mark_bar().encode(
+alt.Chart(data).mark_bar().encode(
     x='a',
     y='b'
 )
diff --git a/altair/vegalite/v2/examples/bar_chart_with_highlight.py b/altair/vegalite/v2/examples/bar_chart_with_highlight.py
index 93e6b8b2..8dae9466 100644
--- a/altair/vegalite/v2/examples/bar_chart_with_highlight.py
+++ b/altair/vegalite/v2/examples/bar_chart_with_highlight.py
@@ -39,4 +39,4 @@ text = alt.Chart(data2).mark_text(
     text=alt.value('hazardous')
 )
 
-chart = bar1 + text + bar2 + rule
+bar1 + text + bar2 + rule
diff --git a/altair/vegalite/v2/examples/bar_chat_with_labels.py b/altair/vegalite/v2/examples/bar_chat_with_labels.py
index 00c5a9e6..9cc3c9a0 100644
--- a/altair/vegalite/v2/examples/bar_chat_with_labels.py
+++ b/altair/vegalite/v2/examples/bar_chat_with_labels.py
@@ -25,4 +25,4 @@ text = bars.mark_text(
     text='b'
 )
 
-chart = bars + text
+bars + text
diff --git a/altair/vegalite/v2/examples/beckers_barley_trellis_plot.py b/altair/vegalite/v2/examples/beckers_barley_trellis_plot.py
index 5656f2c7..d0a49e9d 100644
--- a/altair/vegalite/v2/examples/beckers_barley_trellis_plot.py
+++ b/altair/vegalite/v2/examples/beckers_barley_trellis_plot.py
@@ -9,7 +9,7 @@ from vega_datasets import data
 
 source = data.barley()
 
-chart = alt.Chart(source).mark_point().encode(
+alt.Chart(source).mark_point().encode(
     alt.X('median(yield)', scale=alt.Scale(zero = False)),
     alt.Y(
         'variety',
diff --git a/altair/vegalite/v2/examples/binned_scatterplot.py b/altair/vegalite/v2/examples/binned_scatterplot.py
index f079c4e2..19e7ca8c 100644
--- a/altair/vegalite/v2/examples/binned_scatterplot.py
+++ b/altair/vegalite/v2/examples/binned_scatterplot.py
@@ -9,7 +9,7 @@ from vega_datasets import data
 
 source = data.movies.url
 
-chart = alt.Chart(source).mark_circle().encode(
+alt.Chart(source).mark_circle().encode(
     alt.X('IMDB_Rating:Q', bin=True),
     alt.Y('Rotten_Tomatoes_Rating:Q', bin=True),
     size='count()'
diff --git a/altair/vegalite/v2/examples/boxplot_max_min.py b/altair/vegalite/v2/examples/boxplot_max_min.py
index 93109770..bea5cc9c 100644
--- a/altair/vegalite/v2/examples/boxplot_max_min.py
+++ b/altair/vegalite/v2/examples/boxplot_max_min.py
@@ -44,4 +44,4 @@ middle_tick = alt.Chart(population).mark_tick(
     x='age:O',
 )
 
-chart = lower_plot + middle_plot + upper_plot + middle_tick
+lower_plot + middle_plot + upper_plot + middle_tick
diff --git a/altair/vegalite/v2/examples/bubble_plot.py b/altair/vegalite/v2/examples/bubble_plot.py
index 2a0b3bec..d1872cbf 100644
--- a/altair/vegalite/v2/examples/bubble_plot.py
+++ b/altair/vegalite/v2/examples/bubble_plot.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.cars()
 
-chart = alt.Chart(source).mark_point().encode(
+alt.Chart(source).mark_point().encode(
     x='Horsepower',
     y='Miles_per_Gallon',
     size='Acceleration'
diff --git a/altair/vegalite/v2/examples/candlestick_chart.py b/altair/vegalite/v2/examples/candlestick_chart.py
index 5111fda5..97fe1ead 100644
--- a/altair/vegalite/v2/examples/candlestick_chart.py
+++ b/altair/vegalite/v2/examples/candlestick_chart.py
@@ -237,4 +237,4 @@ bar = alt.Chart(df).mark_bar().encode(
     color=open_close_color
 )
 
-chart = rule + bar
+rule + bar
diff --git a/altair/vegalite/v2/examples/choropleth.py b/altair/vegalite/v2/examples/choropleth.py
index 39661610..5aeb729a 100644
--- a/altair/vegalite/v2/examples/choropleth.py
+++ b/altair/vegalite/v2/examples/choropleth.py
@@ -12,7 +12,7 @@ counties = alt.topo_feature(data.us_10m.url,'counties')
 unemp_data = alt.UrlData(data.unemployment.url)
 
 
-chart = alt.Chart(counties).mark_geoshape().properties(
+alt.Chart(counties).mark_geoshape().properties(
     projection={'type': 'albersUsa'},
     width=500,
     height=300
diff --git a/altair/vegalite/v2/examples/choropleth_repeat.py b/altair/vegalite/v2/examples/choropleth_repeat.py
index d7165808..ecbe512b 100644
--- a/altair/vegalite/v2/examples/choropleth_repeat.py
+++ b/altair/vegalite/v2/examples/choropleth_repeat.py
@@ -14,7 +14,7 @@ pop_eng_hur = alt.UrlData(data.population_engineers_hurricanes.url)
 
 variable_list = ['population','engineers','hurricanes']
 
-chart = alt.Chart(states).mark_geoshape().properties(
+alt.Chart(states).mark_geoshape().properties(
     projection={'type': 'albersUsa'},
     width=500,
     height=300
@@ -25,4 +25,6 @@ chart = alt.Chart(states).mark_geoshape().properties(
     from_=alt.LookupData(pop_eng_hur, 'id', variable_list)
 ).repeat(
     row = variable_list
-).resolve_scale(color='independent')
+).resolve_scale(
+    color='independent'
+)
diff --git a/altair/vegalite/v2/examples/connected_scatterplot.py b/altair/vegalite/v2/examples/connected_scatterplot.py
index e32c0536..12078f90 100644
--- a/altair/vegalite/v2/examples/connected_scatterplot.py
+++ b/altair/vegalite/v2/examples/connected_scatterplot.py
@@ -22,4 +22,4 @@ points = alt.Chart(driving).mark_circle().encode(
     order='year'
 )
 
-chart = lines + points
+lines + points
diff --git a/altair/vegalite/v2/examples/cumulative_wiki_donations.py b/altair/vegalite/v2/examples/cumulative_wiki_donations.py
index 4406bc61..66c443e5 100644
--- a/altair/vegalite/v2/examples/cumulative_wiki_donations.py
+++ b/altair/vegalite/v2/examples/cumulative_wiki_donations.py
@@ -2,7 +2,7 @@
 Cumulative Wikipedia Donations
 ==============================
 
-This chart shows cumulative donations to Wikipedia over the past 10 years. 
+This chart shows cumulative donations to Wikipedia over the past 10 years.
 his chart was inspired by this [reddit post](https://www.reddit.com/r/dataisbeautiful/comments/7guwd0/cumulative_wikimedia_donations_over_the_past_10/) but using lines instead of areas.
 Data comes from https://frdata.wikimedia.org/.
 """
@@ -11,7 +11,7 @@ import altair as alt
 
 data = "https://frdata.wikimedia.org/donationdata-vs-day.csv"
 
-chart = alt.Chart(data).mark_line().encode(
+alt.Chart(data).mark_line().encode(
     alt.X(
         'date:T', timeUnit='monthdate',
         axis=alt.Axis(format='%B', title='Month')
diff --git a/altair/vegalite/v2/examples/diverging_stacked_bar_chart.py b/altair/vegalite/v2/examples/diverging_stacked_bar_chart.py
index 3394efeb..22d52ad5 100644
--- a/altair/vegalite/v2/examples/diverging_stacked_bar_chart.py
+++ b/altair/vegalite/v2/examples/diverging_stacked_bar_chart.py
@@ -354,7 +354,7 @@ y_axis = alt.Axis(title = 'Question',
 
 source = alt.pd.DataFrame(data)
 
-chart = alt.Chart(source).mark_bar().encode(
+alt.Chart(source).mark_bar().encode(
     x='percentage_start:Q',
     x2='percentage_end:Q',
     y=alt.Y('question:N', axis=y_axis),
diff --git a/altair/vegalite/v2/examples/dot_dash_plot.py b/altair/vegalite/v2/examples/dot_dash_plot.py
index 7118a6ae..3a1d772a 100644
--- a/altair/vegalite/v2/examples/dot_dash_plot.py
+++ b/altair/vegalite/v2/examples/dot_dash_plot.py
@@ -40,4 +40,4 @@ y_ticks = alt.Chart(cars).mark_tick().encode(
     selection=brush
 )
 
-chart = y_ticks | (points & x_ticks)
+y_ticks | (points & x_ticks)
diff --git a/altair/vegalite/v2/examples/error_bars_with_ci.py b/altair/vegalite/v2/examples/error_bars_with_ci.py
index 1246078c..2339784b 100644
--- a/altair/vegalite/v2/examples/error_bars_with_ci.py
+++ b/altair/vegalite/v2/examples/error_bars_with_ci.py
@@ -27,4 +27,4 @@ error_bars = alt.Chart(barley).mark_rule().encode(
     y='variety'
 )
 
-chart = points + error_bars
+points + error_bars
diff --git a/altair/vegalite/v2/examples/falkensee.py b/altair/vegalite/v2/examples/falkensee.py
index 07bbe9c6..d9e9866a 100644
--- a/altair/vegalite/v2/examples/falkensee.py
+++ b/altair/vegalite/v2/examples/falkensee.py
@@ -78,4 +78,4 @@ rect = alt.Chart(source2).mark_rect().encode(
     color = 'event:N'
 )
 
-chart = rect + line + point
+rect + line + point
diff --git a/altair/vegalite/v2/examples/gantt_chart.py b/altair/vegalite/v2/examples/gantt_chart.py
index c3bf5ad6..85c20146 100644
--- a/altair/vegalite/v2/examples/gantt_chart.py
+++ b/altair/vegalite/v2/examples/gantt_chart.py
@@ -14,7 +14,7 @@ data = pd.DataFrame([
     {"task": "C","start": 8, "end": 10}
 ])
 
-chart = alt.Chart(data).mark_bar().encode(
+alt.Chart(data).mark_bar().encode(
     x='start',
     x2='end',
     y='task',
diff --git a/altair/vegalite/v2/examples/gapminder_bubble_plot.py b/altair/vegalite/v2/examples/gapminder_bubble_plot.py
index 1fbcb8bf..87d286c1 100644
--- a/altair/vegalite/v2/examples/gapminder_bubble_plot.py
+++ b/altair/vegalite/v2/examples/gapminder_bubble_plot.py
@@ -12,7 +12,7 @@ from vega_datasets import data
 
 gapminder = data.gapminder_health_income.url
 
-chart = alt.Chart(gapminder).mark_circle().encode(
+alt.Chart(gapminder).mark_circle().encode(
     alt.X('income:Q', scale=alt.Scale(type='log')),
     alt.Y('health:Q', scale=alt.Scale(zero=False)),
     size='population:Q'
diff --git a/altair/vegalite/v2/examples/grouped_bar_chart.py b/altair/vegalite/v2/examples/grouped_bar_chart.py
index 13dd41c7..ec1698f2 100644
--- a/altair/vegalite/v2/examples/grouped_bar_chart.py
+++ b/altair/vegalite/v2/examples/grouped_bar_chart.py
@@ -12,7 +12,7 @@ from vega_datasets import data
 
 source = data.population.url
 
-chart = alt.Chart(source).mark_bar(stroke = 'transparent').encode(
+alt.Chart(source).mark_bar(stroke = 'transparent').encode(
     alt.X('gender:N', scale=alt.Scale(rangeStep = 12), axis=alt.Axis(title='')),
     alt.Y('sum(people):Q', axis=alt.Axis(title='population', grid=False)),
     color = alt.Color('gender:N', scale=alt.Scale(range=["#EA98D2", "#659CCA"])),
diff --git a/altair/vegalite/v2/examples/histogram.py b/altair/vegalite/v2/examples/histogram.py
index 909e54e0..6c1b9664 100644
--- a/altair/vegalite/v2/examples/histogram.py
+++ b/altair/vegalite/v2/examples/histogram.py
@@ -11,7 +11,7 @@ from vega_datasets import data
 
 movies = data.movies.url
 
-chart = alt.Chart(movies).mark_bar().encode(
+alt.Chart(movies).mark_bar().encode(
     alt.X("IMDB_Rating:Q", bin=True),
     y='count()',
 )
diff --git a/altair/vegalite/v2/examples/histogram_with_a_global_mean_overlay.py b/altair/vegalite/v2/examples/histogram_with_a_global_mean_overlay.py
index 90843de3..3dbd26bf 100644
--- a/altair/vegalite/v2/examples/histogram_with_a_global_mean_overlay.py
+++ b/altair/vegalite/v2/examples/histogram_with_a_global_mean_overlay.py
@@ -19,4 +19,4 @@ rule = alt.Chart(source).mark_rule(color='red').encode(
     size=alt.value(5)
 )
 
-chart = bar + rule
+bar + rule
diff --git a/altair/vegalite/v2/examples/horizon_graph.py b/altair/vegalite/v2/examples/horizon_graph.py
index 6bb2ae89..13ea1077 100644
--- a/altair/vegalite/v2/examples/horizon_graph.py
+++ b/altair/vegalite/v2/examples/horizon_graph.py
@@ -39,4 +39,4 @@ area2 = area1.encode(
     "ny", datum.y - 50
 )
 
-chart = area1 + area2
+area1 + area2
diff --git a/altair/vegalite/v2/examples/horizontal_stacked_bar_chart.py b/altair/vegalite/v2/examples/horizontal_stacked_bar_chart.py
index 15e836e1..8ac82f9a 100644
--- a/altair/vegalite/v2/examples/horizontal_stacked_bar_chart.py
+++ b/altair/vegalite/v2/examples/horizontal_stacked_bar_chart.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 barley = data.barley()
 
-chart = alt.Chart(barley).mark_bar().encode(
+alt.Chart(barley).mark_bar().encode(
     x='sum(yield)',
     y='variety',
     color='site'
diff --git a/altair/vegalite/v2/examples/interactive_brush.py b/altair/vegalite/v2/examples/interactive_brush.py
index 97fce762..c61a438f 100644
--- a/altair/vegalite/v2/examples/interactive_brush.py
+++ b/altair/vegalite/v2/examples/interactive_brush.py
@@ -13,7 +13,7 @@ from vega_datasets import data
 cars = data.cars.url
 brush = alt.selection(type='interval')
 
-chart = alt.Chart(cars).mark_point().encode(
+alt.Chart(cars).mark_point().encode(
     x='Horsepower:Q',
     y='Miles_per_Gallon:Q',
     color=alt.condition(brush, 'Cylinders:O', alt.value('grey'))
diff --git a/altair/vegalite/v2/examples/interactive_cross_highlight.py b/altair/vegalite/v2/examples/interactive_cross_highlight.py
index fa9c7d14..50f3f543 100644
--- a/altair/vegalite/v2/examples/interactive_cross_highlight.py
+++ b/altair/vegalite/v2/examples/interactive_cross_highlight.py
@@ -40,7 +40,7 @@ bar = alt.Chart(data.movies.url).mark_bar().encode(
     height=200
 )
 
-chart = alt.vconcat(
+alt.vconcat(
     rect + circ,
     bar
 ).resolve_legend(
diff --git a/altair/vegalite/v2/examples/interactive_layered_crossfilter.py b/altair/vegalite/v2/examples/interactive_layered_crossfilter.py
index 9ffdfd39..2d6977fb 100644
--- a/altair/vegalite/v2/examples/interactive_layered_crossfilter.py
+++ b/altair/vegalite/v2/examples/interactive_layered_crossfilter.py
@@ -38,7 +38,7 @@ highlight = base.encode(
 )
 
 # layer the two charts & repeat
-chart = alt.layer(
+alt.layer(
     background, highlight,
     data=flights
 ).transform_calculate(
diff --git a/altair/vegalite/v2/examples/interactive_scatter_plot.py b/altair/vegalite/v2/examples/interactive_scatter_plot.py
index 073ce88a..ca90dc20 100644
--- a/altair/vegalite/v2/examples/interactive_scatter_plot.py
+++ b/altair/vegalite/v2/examples/interactive_scatter_plot.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.cars()
 
-chart = alt.Chart(source).mark_circle().encode(
+alt.Chart(source).mark_circle().encode(
     x='Horsepower',
     y='Miles_per_Gallon',
     color='Origin'
diff --git a/altair/vegalite/v2/examples/interval_selection.py b/altair/vegalite/v2/examples/interval_selection.py
index 1dcb76e7..af74bd43 100644
--- a/altair/vegalite/v2/examples/interval_selection.py
+++ b/altair/vegalite/v2/examples/interval_selection.py
@@ -26,4 +26,4 @@ lower = upper.properties(
     height=60
 )
 
-chart = alt.vconcat(upper, lower, data=sp500)
+alt.vconcat(upper, lower, data=sp500)
diff --git a/altair/vegalite/v2/examples/layer_line_color_rule.py b/altair/vegalite/v2/examples/layer_line_color_rule.py
index 8726b4ba..db7bc991 100644
--- a/altair/vegalite/v2/examples/layer_line_color_rule.py
+++ b/altair/vegalite/v2/examples/layer_line_color_rule.py
@@ -26,4 +26,4 @@ rule = alt.Chart(stocks).mark_rule().encode(
     size=alt.value(2)
 )
 
-chart = line + rule
+line + rule
diff --git a/altair/vegalite/v2/examples/layered_bar_chart.py b/altair/vegalite/v2/examples/layered_bar_chart.py
index 7a6b27fb..9a1ed0c7 100644
--- a/altair/vegalite/v2/examples/layered_bar_chart.py
+++ b/altair/vegalite/v2/examples/layered_bar_chart.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.population.url
 
-chart = alt.Chart(source).mark_bar(opacity=0.7).encode(
+alt.Chart(source).mark_bar(opacity=0.7).encode(
     alt.X('age:O', scale=alt.Scale(rangeStep=17)),
     alt.Y('sum(people):Q', axis=alt.Axis(title='population'), stack=None),
     alt.Color('gender:N', scale=alt.Scale(range=["#EA98D2", "#659CCA"]))
diff --git a/altair/vegalite/v2/examples/layered_chart_bar_mark.py b/altair/vegalite/v2/examples/layered_chart_bar_mark.py
index 319dd6c2..494d8cb4 100644
--- a/altair/vegalite/v2/examples/layered_chart_bar_mark.py
+++ b/altair/vegalite/v2/examples/layered_chart_bar_mark.py
@@ -25,7 +25,7 @@ b = alt.Chart().mark_tick(
     y='goal'
 )
 
-chart = alt.layer(a, b).properties(
+alt.layer(a, b).properties(
     data=data
 ).configure_tick(
     thickness=2,
diff --git a/altair/vegalite/v2/examples/layered_heatmap_text.py b/altair/vegalite/v2/examples/layered_heatmap_text.py
index 51f3b9cc..db3dcf0c 100644
--- a/altair/vegalite/v2/examples/layered_heatmap_text.py
+++ b/altair/vegalite/v2/examples/layered_heatmap_text.py
@@ -26,4 +26,4 @@ text = alt.Chart(cars).mark_text(baseline='middle').encode(
                         alt.value('white'))
 )
 
-chart = heatmap + text
+heatmap + text
diff --git a/altair/vegalite/v2/examples/layered_histogram.py b/altair/vegalite/v2/examples/layered_histogram.py
index a96870d0..fe15917d 100644
--- a/altair/vegalite/v2/examples/layered_histogram.py
+++ b/altair/vegalite/v2/examples/layered_histogram.py
@@ -20,7 +20,7 @@ df = pd.melt(df, id_vars=df.index.name,
              var_name = 'Experiment',
              value_name='Measurement')
 
-chart = alt.Chart(df).mark_area(
+alt.Chart(df).mark_area(
     opacity=0.3,
     interpolate='step'
 ).encode(
diff --git a/altair/vegalite/v2/examples/layered_plot_with_dual_axis.py b/altair/vegalite/v2/examples/layered_plot_with_dual_axis.py
index a2b389a3..79fe5681 100644
--- a/altair/vegalite/v2/examples/layered_plot_with_dual_axis.py
+++ b/altair/vegalite/v2/examples/layered_plot_with_dual_axis.py
@@ -26,4 +26,9 @@ line =  base.mark_line(color='red').encode(
     y='mean(temp_max)',
 )
 
-chart = (bar + line).resolve_scale(y='independent')
+alt.layer(
+    bar,
+    line
+).resolve_scale(
+    y='independent'
+)
diff --git a/altair/vegalite/v2/examples/line_percent.py b/altair/vegalite/v2/examples/line_percent.py
index 9a1e868f..731c3e3f 100644
--- a/altair/vegalite/v2/examples/line_percent.py
+++ b/altair/vegalite/v2/examples/line_percent.py
@@ -1,7 +1,7 @@
 """
 Line Chart with Percent axis
 ----------------------------
-This example shows how to format the tick labels of the 
+This example shows how to format the tick labels of the
 y-axis of a chart as percentages.
 """
 
@@ -11,10 +11,12 @@ from vega_datasets import data
 
 source = data.jobs.url
 
-chart = alt.Chart(source).mark_line().encode(
+alt.Chart(source).mark_line().encode(
     alt.X('year:O'),
     alt.Y('perc:Q', axis=alt.Axis(format='%')),
     color='sex:N'
 ).properties(
     title='Percent of work-force working as Welders'
-).transform_filter(datum.job == 'Welder')
+).transform_filter(
+    datum.job == 'Welder'
+)
diff --git a/altair/vegalite/v2/examples/line_with_ci.py b/altair/vegalite/v2/examples/line_with_ci.py
index 7c316927..9ec1acff 100644
--- a/altair/vegalite/v2/examples/line_with_ci.py
+++ b/altair/vegalite/v2/examples/line_with_ci.py
@@ -10,14 +10,14 @@ from vega_datasets import data
 cars = data.cars()
 
 line = alt.Chart(cars).mark_line().encode(
-    x='Year', 
+    x='Year',
     y='mean(Miles_per_Gallon)'
 )
 
 confidence_interval = alt.Chart(cars).mark_area(opacity=0.3).encode(
-    x='Year', 
+    x='Year',
     y=alt.Y('ci0(Miles_per_Gallon)', axis=alt.Axis(title='Miles/Gallon')),
     y2='ci1(Miles_per_Gallon)'
 )
 
-chart = confidence_interval + line
\ No newline at end of file
+confidence_interval + line
diff --git a/altair/vegalite/v2/examples/london_tube.py b/altair/vegalite/v2/examples/london_tube.py
index 46abc24a..91090e82 100644
--- a/altair/vegalite/v2/examples/london_tube.py
+++ b/altair/vegalite/v2/examples/london_tube.py
@@ -56,4 +56,4 @@ lines = alt.Chart(tubelines).mark_geoshape(
     )
 )
 
-chart = background + labels + lines
+background + labels + lines
diff --git a/altair/vegalite/v2/examples/mean_overlay_over_precipitiation_chart.py b/altair/vegalite/v2/examples/mean_overlay_over_precipitiation_chart.py
index 23300037..bab1f2a0 100644
--- a/altair/vegalite/v2/examples/mean_overlay_over_precipitiation_chart.py
+++ b/altair/vegalite/v2/examples/mean_overlay_over_precipitiation_chart.py
@@ -19,4 +19,4 @@ rule = alt.Chart(source).mark_rule(color = 'red').encode(
     size=alt.value(3)
 )
 
-chart = bar + rule
+bar + rule
diff --git a/altair/vegalite/v2/examples/multifeature_scatter_plot.py b/altair/vegalite/v2/examples/multifeature_scatter_plot.py
index c8cdb4ed..c8272593 100644
--- a/altair/vegalite/v2/examples/multifeature_scatter_plot.py
+++ b/altair/vegalite/v2/examples/multifeature_scatter_plot.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 iris = data.iris()
 
-chart = alt.Chart(iris).mark_circle().encode(
+alt.Chart(iris).mark_circle().encode(
     alt.X('sepalLength', scale=alt.Scale(zero=False)),
     alt.Y('sepalWidth', scale=alt.Scale(zero=False, padding=1)),
     color='species',
diff --git a/altair/vegalite/v2/examples/multiline_highlight.py b/altair/vegalite/v2/examples/multiline_highlight.py
index 2c37ea2b..f2cab760 100644
--- a/altair/vegalite/v2/examples/multiline_highlight.py
+++ b/altair/vegalite/v2/examples/multiline_highlight.py
@@ -33,4 +33,4 @@ lines = base.mark_line().encode(
     size=alt.condition(~highlight, alt.value(1), alt.value(3))
 )
 
-chart = points + lines
+points + lines
diff --git a/altair/vegalite/v2/examples/multiline_tooltip.py b/altair/vegalite/v2/examples/multiline_tooltip.py
index bcb278b5..ffb5d60f 100644
--- a/altair/vegalite/v2/examples/multiline_tooltip.py
+++ b/altair/vegalite/v2/examples/multiline_tooltip.py
@@ -53,5 +53,5 @@ rules = alt.Chart().mark_rule(color='gray').encode(
 )
 
 # Put the five layers into a chart and bind the data
-chart = alt.layer(line, selectors, points, rules, text,
-                  data=data, width=600, height=300)
+alt.layer(line, selectors, points, rules, text,
+          data=data, width=600, height=300)
diff --git a/altair/vegalite/v2/examples/multiple_marks.py b/altair/vegalite/v2/examples/multiple_marks.py
index 17588255..5d55fec2 100644
--- a/altair/vegalite/v2/examples/multiple_marks.py
+++ b/altair/vegalite/v2/examples/multiple_marks.py
@@ -9,7 +9,7 @@ from vega_datasets import data
 
 stocks = data.stocks()
 
-chart = alt.LayerChart(stocks).encode(
+alt.LayerChart(stocks).encode(
     x='date:T',
     y='price:Q',
     color='symbol:N'
diff --git a/altair/vegalite/v2/examples/mutli_series_line.py b/altair/vegalite/v2/examples/mutli_series_line.py
index aea40dc5..a7eeb971 100644
--- a/altair/vegalite/v2/examples/mutli_series_line.py
+++ b/altair/vegalite/v2/examples/mutli_series_line.py
@@ -11,7 +11,7 @@ from vega_datasets import data
 
 stocks = data.stocks()
 
-chart = alt.Chart(stocks).mark_line().encode(
+alt.Chart(stocks).mark_line().encode(
     x='date',
     y='price',
     color='symbol'
diff --git a/altair/vegalite/v2/examples/natural_disasters.py b/altair/vegalite/v2/examples/natural_disasters.py
index 2c97cfe5..2f69b0de 100644
--- a/altair/vegalite/v2/examples/natural_disasters.py
+++ b/altair/vegalite/v2/examples/natural_disasters.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.disasters.url
 
-chart = alt.Chart(source).mark_circle(
+alt.Chart(source).mark_circle(
     opacity=0.8,
     stroke='black',
     strokeWidth=1
diff --git a/altair/vegalite/v2/examples/normalized_stacked_bar_chart.py b/altair/vegalite/v2/examples/normalized_stacked_bar_chart.py
index 4d3cf63a..e82668c1 100644
--- a/altair/vegalite/v2/examples/normalized_stacked_bar_chart.py
+++ b/altair/vegalite/v2/examples/normalized_stacked_bar_chart.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.population.url
 
-chart = alt.Chart(source).mark_bar().encode(
+alt.Chart(source).mark_bar().encode(
     alt.X('age:O', scale=alt.Scale(rangeStep=17)),
     alt.Y('sum(people):Q',
         axis=alt.Axis(title='population'),
diff --git a/altair/vegalite/v2/examples/one_dot_per_zipcode.py b/altair/vegalite/v2/examples/one_dot_per_zipcode.py
index 97264683..d0cd614c 100644
--- a/altair/vegalite/v2/examples/one_dot_per_zipcode.py
+++ b/altair/vegalite/v2/examples/one_dot_per_zipcode.py
@@ -11,7 +11,7 @@ from vega_datasets import data
 
 zipcodes = data.zipcodes.url
 
-chart = alt.Chart(zipcodes).mark_circle(size = 3).encode(
+alt.Chart(zipcodes).mark_circle(size = 3).encode(
     longitude='longitude:Q',
     latitude='latitude:Q',
     color='digit:N'
diff --git a/altair/vegalite/v2/examples/poly_fit.py b/altair/vegalite/v2/examples/poly_fit.py
index fa837a99..a7b6ce87 100644
--- a/altair/vegalite/v2/examples/poly_fit.py
+++ b/altair/vegalite/v2/examples/poly_fit.py
@@ -42,4 +42,4 @@ polynomial_fit = alt.Chart(poly_data).mark_line().encode(
     color='degree'
 )
 
-chart = points + polynomial_fit
+points + polynomial_fit
diff --git a/altair/vegalite/v2/examples/ranged_dot_plot.py b/altair/vegalite/v2/examples/ranged_dot_plot.py
index a6774b8c..e6fc9444 100644
--- a/altair/vegalite/v2/examples/ranged_dot_plot.py
+++ b/altair/vegalite/v2/examples/ranged_dot_plot.py
@@ -38,3 +38,5 @@ chart += alt.Chart().mark_point(
         )
     )
 ).interactive()
+
+chart
diff --git a/altair/vegalite/v2/examples/scatter_linked_brush.py b/altair/vegalite/v2/examples/scatter_linked_brush.py
index d912f069..18f999f9 100644
--- a/altair/vegalite/v2/examples/scatter_linked_brush.py
+++ b/altair/vegalite/v2/examples/scatter_linked_brush.py
@@ -22,4 +22,4 @@ base = alt.Chart(cars).mark_point().encode(
     height=250
 )
 
-chart = base.encode(x='Horsepower') | base.encode(x='Acceleration')
+base.encode(x='Horsepower') | base.encode(x='Acceleration')
diff --git a/altair/vegalite/v2/examples/scatter_matrix.py b/altair/vegalite/v2/examples/scatter_matrix.py
index 3f10246b..0ff8087e 100644
--- a/altair/vegalite/v2/examples/scatter_matrix.py
+++ b/altair/vegalite/v2/examples/scatter_matrix.py
@@ -9,7 +9,7 @@ with linked panning and zooming.
 import altair as alt
 from vega_datasets import data
 
-chart = alt.Chart(data.cars.url).mark_circle().encode(
+alt.Chart(data.cars.url).mark_circle().encode(
     alt.X(alt.repeat("column"), type='quantitative'),
     alt.Y(alt.repeat("row"), type='quantitative'),
     color='Origin:N'
diff --git a/altair/vegalite/v2/examples/seattle_weather_interactive.py b/altair/vegalite/v2/examples/seattle_weather_interactive.py
index 9ec0de3c..a39b76a0 100644
--- a/altair/vegalite/v2/examples/seattle_weather_interactive.py
+++ b/altair/vegalite/v2/examples/seattle_weather_interactive.py
@@ -49,7 +49,7 @@ bars = alt.Chart().mark_bar().encode(
     selection=click
 )
 
-chart = alt.vconcat(points, bars,
+alt.vconcat(points, bars,
     data=data.seattle_weather.url,
     title="Seattle Weather: 2012-2015"
 )
diff --git a/altair/vegalite/v2/examples/selection_histogram.py b/altair/vegalite/v2/examples/selection_histogram.py
index 421d354d..9491b352 100644
--- a/altair/vegalite/v2/examples/selection_histogram.py
+++ b/altair/vegalite/v2/examples/selection_histogram.py
@@ -30,4 +30,4 @@ bars = alt.Chart().mark_bar().encode(
     brush.ref()
 )
 
-chart = alt.vconcat(points, bars, data=cars)
+alt.vconcat(points, bars, data=cars)
diff --git a/altair/vegalite/v2/examples/selection_layer_bar_month.py b/altair/vegalite/v2/examples/selection_layer_bar_month.py
index 0d8caad8..b3b4f978 100644
--- a/altair/vegalite/v2/examples/selection_layer_bar_month.py
+++ b/altair/vegalite/v2/examples/selection_layer_bar_month.py
@@ -26,4 +26,4 @@ line = alt.Chart().mark_rule(color='firebrick').encode(
     size=alt.SizeValue(3)
 ).transform_filter(brush.ref())
 
-chart = alt.layer(bars + line, data=weather)
+alt.layer(bars, line, data=weather)
diff --git a/altair/vegalite/v2/examples/simple_scatter.py b/altair/vegalite/v2/examples/simple_scatter.py
index c3e893fb..12d56026 100644
--- a/altair/vegalite/v2/examples/simple_scatter.py
+++ b/altair/vegalite/v2/examples/simple_scatter.py
@@ -12,7 +12,7 @@ from vega_datasets import data
 
 iris = data.iris()
 
-chart = alt.Chart(iris).mark_point().encode(
+alt.Chart(iris).mark_point().encode(
     x='petalWidth',
     y='petalLength',
     color='species'
diff --git a/altair/vegalite/v2/examples/slope_graph.py b/altair/vegalite/v2/examples/slope_graph.py
index baaeee90..9873076f 100644
--- a/altair/vegalite/v2/examples/slope_graph.py
+++ b/altair/vegalite/v2/examples/slope_graph.py
@@ -13,7 +13,7 @@ source = data.barley()
 # it is best to use either a string representation or a datetime representation.
 source.year = source.year.astype(str)
 
-chart = alt.Chart(source).mark_line().encode(
+alt.Chart(source).mark_line().encode(
     x='year',
     y='median(yield)',
     color='site'
diff --git a/altair/vegalite/v2/examples/stacked_area_chart.py b/altair/vegalite/v2/examples/stacked_area_chart.py
index f5e0c14a..5304ccb7 100644
--- a/altair/vegalite/v2/examples/stacked_area_chart.py
+++ b/altair/vegalite/v2/examples/stacked_area_chart.py
@@ -8,15 +8,13 @@ import altair as alt
 from vega_datasets import data
 import pandas as pd
 
-crimea = data.crimea()
-
-crimea = pd.melt(crimea, id_vars=['date'],
+crimea = pd.melt(data.crimea(), id_vars=['date'],
                  value_vars=['disease', 'other', 'wounds'],
                  var_name='cause',
                  value_name='deaths')
 
-chart = alt.Chart(crimea).mark_area().encode(
+alt.Chart(crimea).mark_area().encode(
     x='date',
-    y='sum(deaths)', 
+    y='sum(deaths)',
     color='cause'
 )
diff --git a/altair/vegalite/v2/examples/stacked_bar_chart.py b/altair/vegalite/v2/examples/stacked_bar_chart.py
index 4ebcd3bf..8027114d 100644
--- a/altair/vegalite/v2/examples/stacked_bar_chart.py
+++ b/altair/vegalite/v2/examples/stacked_bar_chart.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 weather = data.seattle_weather()
 
-chart = alt.Chart(weather).mark_bar().encode(
+alt.Chart(weather).mark_bar().encode(
     alt.Color('weather:N',
         legend=alt.Legend(title='Weather type'),
         scale=alt.Scale(
diff --git a/altair/vegalite/v2/examples/stem_and_leaf.py b/altair/vegalite/v2/examples/stem_and_leaf.py
index 507c5662..2cfb30e4 100644
--- a/altair/vegalite/v2/examples/stem_and_leaf.py
+++ b/altair/vegalite/v2/examples/stem_and_leaf.py
@@ -27,7 +27,7 @@ original_data['position'] = original_data.groupby('stem')\
                                          .reset_index(drop=True)
 
 # Creating stem and leaf plot
-chart = alt.Chart(original_data).mark_text(
+alt.Chart(original_data).mark_text(
     align='left',
     baseline='middle',
     dx=-5
diff --git a/altair/vegalite/v2/examples/step_chart.py b/altair/vegalite/v2/examples/step_chart.py
index bb5f7f60..6253a70a 100644
--- a/altair/vegalite/v2/examples/step_chart.py
+++ b/altair/vegalite/v2/examples/step_chart.py
@@ -1,7 +1,7 @@
 """
 Step Chart
 ----------
-This example shows Google's stock price over time. 
+This example shows Google's stock price over time.
 This uses the "step-after" interpolation scheme.
 The full list of interpolation options includes 'linear’,
 ‘linear-closed’, ‘step’, ‘step-before’, ‘step-after’, ‘basis’,
@@ -16,7 +16,7 @@ from vega_datasets import data
 
 stocks = data.stocks()
 
-chart = alt.Chart(stocks).mark_line(interpolate='step-after').encode(
+alt.Chart(stocks).mark_line(interpolate='step-after').encode(
     x = 'date',
     y = 'price'
 ).transform_filter(
diff --git a/altair/vegalite/v2/examples/streamgraph.py b/altair/vegalite/v2/examples/streamgraph.py
index d4918f5f..188a0fd4 100644
--- a/altair/vegalite/v2/examples/streamgraph.py
+++ b/altair/vegalite/v2/examples/streamgraph.py
@@ -9,7 +9,7 @@ from vega_datasets import data
 
 source = data.unemployment_across_industries.url
 
-chart = alt.Chart(source).mark_area().encode(
+alt.Chart(source).mark_area().encode(
     alt.X('date:T',
         timeUnit = 'yearmonth',
         axis=alt.Axis(format='%Y', domain=False, tickSize=0)
diff --git a/altair/vegalite/v2/examples/strip_plot.py b/altair/vegalite/v2/examples/strip_plot.py
index 4ab511dd..de90c844 100644
--- a/altair/vegalite/v2/examples/strip_plot.py
+++ b/altair/vegalite/v2/examples/strip_plot.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.cars()
 
-chart = alt.Chart(source).mark_tick().encode(
+alt.Chart(source).mark_tick().encode(
     x='Horsepower:Q',
     y='Cylinders:O'
 )
diff --git a/altair/vegalite/v2/examples/table_binned_heatmap.py b/altair/vegalite/v2/examples/table_binned_heatmap.py
index c54f6526..635896a8 100644
--- a/altair/vegalite/v2/examples/table_binned_heatmap.py
+++ b/altair/vegalite/v2/examples/table_binned_heatmap.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.movies.url
 
-chart = alt.Chart(source).mark_rect().encode(
+alt.Chart(source).mark_rect().encode(
     alt.X('IMDB_Rating:Q', bin=alt.Bin(maxbins=60)),
     alt.Y('Rotten_Tomatoes_Rating:Q', bin=alt.Bin(maxbins=40)),
     alt.Color('count(IMDB_Rating):Q', scale=alt.Scale(scheme='greenblue'))
diff --git a/altair/vegalite/v2/examples/table_bubble_plot_github.py b/altair/vegalite/v2/examples/table_bubble_plot_github.py
index 14d2f2c3..e07b31b3 100644
--- a/altair/vegalite/v2/examples/table_bubble_plot_github.py
+++ b/altair/vegalite/v2/examples/table_bubble_plot_github.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.github.url
 
-chart = alt.Chart(source).mark_circle().encode(
+alt.Chart(source).mark_circle().encode(
     alt.X('time:O', timeUnit='hours'),
     alt.Y('time:O', timeUnit='day'),
     size='sum(count):Q'
diff --git a/altair/vegalite/v2/examples/trellis_area.py b/altair/vegalite/v2/examples/trellis_area.py
index 1d95aa66..6160dc88 100644
--- a/altair/vegalite/v2/examples/trellis_area.py
+++ b/altair/vegalite/v2/examples/trellis_area.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.stocks()
 
-chart = alt.Chart(source).mark_area().encode(
+alt.Chart(source).mark_area().encode(
     alt.X('date:T', axis=alt.Axis(format='%Y', title='Time', grid=False)),
     alt.Y('price:Q', axis=alt.Axis(title='Price', grid=False)),
     alt.Color('symbol', legend=None),
diff --git a/altair/vegalite/v2/examples/trellis_histogram.py b/altair/vegalite/v2/examples/trellis_histogram.py
index 45acdd52..2a124898 100644
--- a/altair/vegalite/v2/examples/trellis_histogram.py
+++ b/altair/vegalite/v2/examples/trellis_histogram.py
@@ -8,7 +8,7 @@ import altair as alt
 
 cars = alt.load_dataset('cars')
 
-chart = alt.Chart(cars).mark_bar().encode(
+alt.Chart(cars).mark_bar().encode(
     alt.X("Horsepower:Q", bin=True),
     y='count()',
     row='Origin'
diff --git a/altair/vegalite/v2/examples/trellis_scatter_plot.py b/altair/vegalite/v2/examples/trellis_scatter_plot.py
index e83969b3..3295a826 100644
--- a/altair/vegalite/v2/examples/trellis_scatter_plot.py
+++ b/altair/vegalite/v2/examples/trellis_scatter_plot.py
@@ -10,7 +10,7 @@ from vega_datasets import data
 
 source = data.movies.url
 
-chart = alt.Chart(source).mark_point().encode(
+alt.Chart(source).mark_point().encode(
     x='Worldwide_Gross:Q',
     y='US_DVD_Sales:Q',
     column='MPAA_Rating:N'
diff --git a/altair/vegalite/v2/examples/trellis_stacked_bar_chart.py b/altair/vegalite/v2/examples/trellis_stacked_bar_chart.py
index 8dd9d1a6..9b2a5e8b 100644
--- a/altair/vegalite/v2/examples/trellis_stacked_bar_chart.py
+++ b/altair/vegalite/v2/examples/trellis_stacked_bar_chart.py
@@ -9,7 +9,7 @@ from vega_datasets import data
 
 barley = data.barley()
 
-chart = alt.Chart(barley).mark_bar().encode(
+alt.Chart(barley).mark_bar().encode(
     column='year',
     x='sum(yield)',
     y='variety',
diff --git a/altair/vegalite/v2/examples/us_population_over_time.py b/altair/vegalite/v2/examples/us_population_over_time.py
index 6f1227da..6dfcfc6f 100644
--- a/altair/vegalite/v2/examples/us_population_over_time.py
+++ b/altair/vegalite/v2/examples/us_population_over_time.py
@@ -19,7 +19,7 @@ pink_blue = alt.Scale(domain=('Male', 'Female'),
 slider = alt.binding_range(min=1900, max=2000, step=10)
 year = alt.selection_single(name="year", fields=['year'], bind=slider)
 
-chart = alt.Chart(pop).mark_bar().encode(
+alt.Chart(pop).mark_bar().encode(
     x=alt.X('sex:N', axis=alt.Axis(title=None)),
     y=alt.Y('people:Q', scale=alt.Scale(domain=(0, 12000000))),
     color=alt.Color('sex:N', scale=pink_blue),
diff --git a/altair/vegalite/v2/examples/us_state_capitals.py b/altair/vegalite/v2/examples/us_state_capitals.py
index 701072c6..e7395f77 100644
--- a/altair/vegalite/v2/examples/us_state_capitals.py
+++ b/altair/vegalite/v2/examples/us_state_capitals.py
@@ -44,4 +44,4 @@ points = base.mark_point().encode(
     selection=hover
 )
 
-chart = background + points + text
+background + points + text


Test patch:
diff --git a/altair/utils/tests/test_execeval.py b/altair/utils/tests/test_execeval.py
new file mode 100644
index 00000000..b5985d62
--- /dev/null
+++ b/altair/utils/tests/test_execeval.py
@@ -0,0 +1,33 @@
+import pytest
+
+from ..execeval import eval_block
+
+HAS_RETURN = """
+x = 4
+y = 2 * x
+3 * y
+"""
+
+NO_RETURN = """
+x = 4
+y = 2 * x
+z = 3 * y
+"""
+
+
+def test_eval_block_with_return():
+    _globals = {}
+    result = eval_block(HAS_RETURN, _globals)
+    assert result == 24
+    assert _globals['x'] == 4
+    assert _globals['y'] == 8
+
+
+
+def test_eval_block_without_return():
+    _globals = {}
+    result = eval_block(NO_RETURN, _globals)
+    assert result is None
+    assert _globals['x'] == 4
+    assert _globals['y'] == 8
+    assert _globals['z'] == 24
diff --git a/altair/vegalite/v2/examples/tests/test_examples.py b/altair/vegalite/v2/examples/tests/test_examples.py
index 68a4e471..941e079e 100644
--- a/altair/vegalite/v2/examples/tests/test_examples.py
+++ b/altair/vegalite/v2/examples/tests/test_examples.py
@@ -3,6 +3,8 @@ from os.path import join, dirname, abspath
 
 import pytest
 
+from altair.utils.execeval import eval_block
+
 EXAMPLE_DIR = abspath(join(dirname(__file__), '..'))
 
 
@@ -19,10 +21,10 @@ def iter_example_filenames():
 def test_examples(filename):
     with open(join(EXAMPLE_DIR, filename)) as f:
         source = f.read()
-    globals_ = {}
-    exec(source, globals_)
 
-    if 'chart' not in globals_:
-        raise ValueError("Example file should define a chart variable")
-    chart = globals_['chart']
+    chart = eval_block(source)
+
+    if chart is None:
+        raise ValueError("Example file should define chart in its final "
+                         "statement.")
     dct = chart.to_dict()
diff --git a/altair/vegalite/v2/tests/test_api.py b/altair/vegalite/v2/tests/test_api.py
index a8eaacda..5e079058 100644
--- a/altair/vegalite/v2/tests/test_api.py
+++ b/altair/vegalite/v2/tests/test_api.py
@@ -11,6 +11,19 @@ import pandas as pd
 import altair.vegalite.v2 as alt
 
 
+@pytest.fixture
+def basic_chart():
+    data = pd.DataFrame({
+        'a': ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'],
+        'b': [28, 55, 43, 91, 81, 53, 19, 87, 52]
+    })
+
+    return alt.Chart(data).mark_bar().encode(
+        x='a',
+        y='b'
+    )
+
+
 def test_chart_data_types():
     Chart = lambda data: alt.Chart(data).mark_point().encode(x='x:Q', y='y:Q')
 
@@ -122,9 +135,7 @@ def test_selection_to_dict():
 
 
 @pytest.mark.parametrize('format', ['html', 'json', 'png', 'svg'])
-def test_save(format):
-    from ..examples.bar import chart
-
+def test_save(format, basic_chart):
     if format in ['html', 'json', 'svg']:
         out = io.StringIO()
         mode = 'r'
@@ -135,8 +146,8 @@ def test_save(format):
 
     try:
         try:
-            chart.save(out, format=format)
-            chart.save(filename)
+            basic_chart.save(out, format=format)
+            basic_chart.save(filename)
         except ImportError as err:
             if 'selenium' in str(err) or 'chromedriver' in str(err):
                 pytest.skip("selenium installation required for png/svg export")