Repository: vega/altair

Issue:
Refine data generator support
Vega-Lite supports _data generators_ for geo spheres, geo graticules, and numeric sequences: https://vega.github.io/vega-lite/docs/data.html#data-generators

Altair includes auto-generated classes (e.g., `alt.GraticuleGenerator`, `alt.GraticuleParams`) corresponding to these features. However, passing a generator class as the data for a Chart can result in warning output:

```
UserWarning: data of type <class ‘altair.vegalite.v3.schema.core.SphereGenerator’> not recognized
warnings.warn(“data of type {} not recognized”.format(type(data)))
```

Moreover, code like `alt.GraticuleGenerator(graticule=alt.GraticuleParams(...))` feels unnecessarily verbose. Perhaps a more concise syntax would be helpful? For example, merging the generator and params into a single call... For comparison, the Vega-Lite JavaScript API includes top-level methods for generators (`vl.graticule()`); https://observablehq.com/@vega/vega-lite-cartographic-projections provides an example of their use.



Discussion:
Great suggestion! I think something like ``alt.graticule()`` or ``alt.data.graticule()`` would make sense.

What version were these added to Vega-Lite?

Resolving patch:
diff --git a/altair/vegalite/v3/api.py b/altair/vegalite/v3/api.py
--- a/altair/vegalite/v3/api.py
+++ b/altair/vegalite/v3/api.py
@@ -93,7 +93,8 @@ def _prepare_data(data, context):
 
     # if data is still not a recognized type, then return
     if not isinstance(data, (dict, core.Data, core.UrlData,
-                             core.InlineData, core.NamedData)):
+                             core.InlineData, core.NamedData,
+                             core.GraticuleGenerator, core.SequenceGenerator)):
         warnings.warn("data of type {} not recognized".format(type(data)))
 
     return data
@@ -1962,3 +1963,25 @@ def remove_data(subchart):
             subcharts = [remove_data(c) for c in subcharts]
 
     return data, subcharts
+
+
+@utils.use_signature(core.SequenceParams)
+def sequence(start, stop=None, step=Undefined, as_=Undefined, **kwds):
+  """Sequence generator."""
+  if stop is None:
+    start, stop = 0, start
+  params = core.SequenceParams(
+    start=start, stop=stop, step=step, **{'as': as_}
+  )
+  return core.SequenceGenerator(sequence=params, **kwds)
+
+
+@utils.use_signature(core.GraticuleParams)
+def graticule(**kwds):
+  """Graticule generator."""
+  if not kwds:
+      # graticule: True indicates default parameters
+      graticule = True
+  else:
+      graticule = core.GraticuleParams(**kwds)
+  return core.GraticuleGenerator(graticule=graticule)
\ No newline at end of file


Test patch:
diff --git a/altair/vegalite/v3/tests/test_api.py b/altair/vegalite/v3/tests/test_api.py
--- a/altair/vegalite/v3/tests/test_api.py
+++ b/altair/vegalite/v3/tests/test_api.py
@@ -840,3 +840,22 @@ def test_facet(chart_type, facet_arg):
         assert dct['facet'] == expected
     else:
         assert dct['facet'][facet_arg] == expected
+
+
+def test_sequence():
+    data = alt.sequence(100)
+    assert data.to_dict() == {'sequence': {'start': 0, 'stop': 100}}
+
+    data = alt.sequence(5, 10)
+    assert data.to_dict() == {'sequence': {'start': 5, 'stop': 10}}
+
+    data = alt.sequence(0, 1, 0.1, as_='x')
+    assert data.to_dict() == {'sequence': {'start': 0, 'stop': 1, 'step': 0.1, 'as': 'x'}}
+
+
+def test_graticule():
+    data = alt.graticule()
+    assert data.to_dict() == {'graticule': True}
+
+    data = alt.graticule(step=[15, 15])
+    assert data.to_dict() == {'graticule': {'step': [15, 15]}}
\ No newline at end of file