Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More readable error messages #480

Closed
jakevdp opened this issue Feb 24, 2018 · 3 comments
Closed

More readable error messages #480

jakevdp opened this issue Feb 24, 2018 · 3 comments
Assignees
Milestone

Comments

@jakevdp
Copy link
Collaborator

jakevdp commented Feb 24, 2018

If a chart produces an invalid schema, the error message is really hard to understand.

One reason for this is that the mime-bundle display system also throws a "NoneType is not iterable" error after the jsonschema validation error.

We really need to figure out how to clean this up. An example, trying to display an empty chart. In a perfect world, I'd like this to just output ValidationError: mark must be specified (or something similar).

In [1]: import altair as alt
In [2]: alt.Chart()
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
~/anaconda/envs/vega3/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
    968 
    969             if method is not None:
--> 970                 return method(include=include, exclude=exclude)
    971             return None
    972         else:

~/github/altair-viz/altair/altair/vegalite/v2/api.py in _repr_mimebundle_(self, include, exclude)
     71     def _repr_mimebundle_(self, include, exclude):
     72         """Return a MIME bundle for display in Jupyter frontends."""
---> 73         return renderers.get()(self.to_dict())
     74 
     75 

~/github/altair-viz/altair/altair/vegalite/v2/api.py in to_dict(self, *args, **kwargs)
     54             context['top_level'] = False
     55         kwargs['context'] = context
---> 56         return super(TopLevelMixin, self).to_dict(*args, **kwargs)
     57 
     58     # Layering and stacking

~/github/altair-viz/altair/altair/utils/schemapi.py in to_dict(self, validate, ignore, context)
    153                              "cannot serialize to dict".format(self.__class__))
    154         if validate:
--> 155             self.validate(result)
    156         return result
    157 

~/github/altair-viz/altair/altair/utils/schemapi.py in validate(cls, instance, schema)
    192             schema = cls._schema
    193         resolver = jsonschema.RefResolver.from_schema(cls._rootschema or cls._schema)
--> 194         return jsonschema.validate(instance, schema, resolver=resolver)
    195 
    196     @classmethod

~/anaconda/envs/vega3/lib/python3.6/site-packages/jsonschema/validators.py in validate(instance, schema, cls, *args, **kwargs)
    539         cls = validator_for(schema)
    540     cls.check_schema(schema)
--> 541     cls(schema, *args, **kwargs).validate(instance)

~/anaconda/envs/vega3/lib/python3.6/site-packages/jsonschema/validators.py in validate(self, *args, **kwargs)
    128         def validate(self, *args, **kwargs):
    129             for error in self.iter_errors(*args, **kwargs):
--> 130                 raise error
    131 
    132         def is_type(self, instance, type):

ValidationError: 'mark' is a required property

Failed validating 'required' in schema:
    {'additionalProperties': False,
     'properties': {'$schema': {'description': 'URL to [JSON '
                                               'schema](http://json-schema.org/) '
                                               'for a Vega-Lite '
                                               'specification. Unless you '
                                               'have a reason to change '
                                               'this, use '
                                               '`https://vega.github.io/schema/vega-lite/v2.json`. '
                                               'Setting the `$schema` '
                                               'property allows automatic '
                                               'validation and '
                                               'autocomplete in editors '
                                               'that support JSON schema.',
                                'format': 'uri',
                                'type': 'string'},
                    'autosize': {'anyOf': [{'$ref': '#/definitions/AutosizeType'},
                                           {'$ref': '#/definitions/AutoSizeParams'}],
                                 'description': 'Sets how the '
                                                'visualization size should '
                                                'be determined. If a '
                                                'string, should be one of '
                                                '`"pad"`, `"fit"` or '
                                                '`"none"`.\n'
                                                'Object values can '
                                                'additionally specify '
                                                'parameters for content '
                                                'sizing and automatic '
                                                'resizing.\n'
                                                '`"fit"` is only supported '
                                                'for single and layered '
                                                "views that don't use "
                                                '`rangeStep`.\n'
                                                '\n'
                                                '__Default value__: `pad`'},
                    'background': {'description': 'CSS color property to '
                                                  'use as the background '
                                                  'of visualization.\n'
                                                  '\n'
                                                  '__Default value:__ none '
                                                  '(transparent)',
                                   'type': 'string'},
                    'config': {'$ref': '#/definitions/Config',
                               'description': 'Vega-Lite configuration '
                                              'object.  This property can '
                                              'only be defined at the '
                                              'top-level of a '
                                              'specification.'},
                    'data': {'$ref': '#/definitions/Data',
                             'description': 'An object describing the data '
                                            'source'},
                    'description': {'description': 'Description of this '
                                                   'mark for commenting '
                                                   'purpose.',
                                    'type': 'string'},
                    'encoding': {'$ref': '#/definitions/EncodingWithFacet',
                                 'description': 'A key-value mapping '
                                                'between encoding channels '
                                                'and definition of '
                                                'fields.'},
                    'height': {'description': 'The height of a '
                                              'visualization.\n'
                                              '\n'
                                              '__Default value:__\n'
                                              "- If a view's "
                                              '[`autosize`](https://vega.github.io/vega-lite/docs/size.html#autosize) '
                                              'type is `"fit"` or its '
                                              'y-channel has a [continuous '
                                              'scale](https://vega.github.io/vega-lite/docs/scale.html#continuous), '
                                              'the height will be the '
                                              'value of '
                                              '[`config.view.height`](https://vega.github.io/vega-lite/docs/spec.html#config).\n'
                                              '- For y-axis with a band or '
                                              'point scale: if '
                                              '[`rangeStep`](https://vega.github.io/vega-lite/docs/scale.html#band) '
                                              'is a numeric value or '
                                              'unspecified, the height is '
                                              '[determined by the range '
                                              'step, paddings, and the '
                                              'cardinality of the field '
                                              'mapped to '
                                              'y-channel](https://vega.github.io/vega-lite/docs/scale.html#band). '
                                              'Otherwise, if the '
                                              '`rangeStep` is `null`, the '
                                              'height will be the value of '
                                              '[`config.view.height`](https://vega.github.io/vega-lite/docs/spec.html#config).\n'
                                              '- If no field is mapped to '
                                              '`y` channel, the `height` '
                                              'will be the value of '
                                              '`rangeStep`.\n'
                                              '\n'
                                              '__Note__: For plots with '
                                              '[`row` and `column` '
                                              'channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), '
                                              'this represents the height '
                                              'of a single view.\n'
                                              '\n'
                                              '__See also:__ The '
                                              'documentation for [width '
                                              'and '
                                              'height](https://vega.github.io/vega-lite/docs/size.html) '
                                              'contains more examples.',
                               'type': 'number'},
                    'mark': {'$ref': '#/definitions/AnyMark',
                             'description': 'A string describing the mark '
                                            'type (one of `"bar"`, '
                                            '`"circle"`, `"square"`, '
                                            '`"tick"`, `"line"`,\n'
                                            '* `"area"`, `"point"`, '
                                            '`"rule"`, `"geoshape"`, and '
                                            '`"text"`) or a [mark '
                                            'definition '
                                            'object](https://vega.github.io/vega-lite/docs/mark.html#mark-def).'},
                    'name': {'description': 'Name of the visualization for '
                                            'later reference.',
                             'type': 'string'},
                    'padding': {'$ref': '#/definitions/Padding',
                                'description': 'The default visualization '
                                               'padding, in pixels, from '
                                               'the edge of the '
                                               'visualization canvas to '
                                               'the data rectangle.  If a '
                                               'number, specifies padding '
                                               'for all sides.\n'
                                               'If an object, the value '
                                               'should have the format '
                                               '`{"left": 5, "top": 5, '
                                               '"right": 5, "bottom": 5}` '
                                               'to specify padding for '
                                               'each side of the '
                                               'visualization.\n'
                                               '\n'
                                               '__Default value__: `5`'},
                    'projection': {'$ref': '#/definitions/Projection',
                                   'description': 'An object defining '
                                                  'properties of '
                                                  'geographic projection.\n'
                                                  '\n'
                                                  'Works with `"geoshape"` '
                                                  'marks and `"point"` or '
                                                  '`"line"` marks that '
                                                  'have a channel (one or '
                                                  'more of `"X"`, `"X2"`, '
                                                  '`"Y"`, `"Y2"`) with '
                                                  'type `"latitude"`, or '
                                                  '`"longitude"`.'},
                    'selection': {'additionalProperties': {'$ref': '#/definitions/SelectionDef'},
                                  'description': 'A key-value mapping '
                                                 'between selection names '
                                                 'and definitions.',
                                  'type': 'object'},
                    'title': {'anyOf': [{'type': 'string'},
                                        {'$ref': '#/definitions/TitleParams'}],
                              'description': 'Title for the plot.'},
                    'transform': {'description': 'An array of data '
                                                 'transformations such as '
                                                 'filter and new field '
                                                 'calculation.',
                                  'items': {'$ref': '#/definitions/Transform'},
                                  'type': 'array'},
                    'width': {'description': 'The width of a '
                                             'visualization.\n'
                                             '\n'
                                             '__Default value:__ This will '
                                             'be determined by the '
                                             'following rules:\n'
                                             '\n'
                                             "- If a view's "
                                             '[`autosize`](https://vega.github.io/vega-lite/docs/size.html#autosize) '
                                             'type is `"fit"` or its '
                                             'x-channel has a [continuous '
                                             'scale](https://vega.github.io/vega-lite/docs/scale.html#continuous), '
                                             'the width will be the value '
                                             'of '
                                             '[`config.view.width`](https://vega.github.io/vega-lite/docs/spec.html#config).\n'
                                             '- For x-axis with a band or '
                                             'point scale: if '
                                             '[`rangeStep`](https://vega.github.io/vega-lite/docs/scale.html#band) '
                                             'is a numeric value or '
                                             'unspecified, the width is '
                                             '[determined by the range '
                                             'step, paddings, and the '
                                             'cardinality of the field '
                                             'mapped to '
                                             'x-channel](https://vega.github.io/vega-lite/docs/scale.html#band).   '
                                             'Otherwise, if the '
                                             '`rangeStep` is `null`, the '
                                             'width will be the value of '
                                             '[`config.view.width`](https://vega.github.io/vega-lite/docs/spec.html#config).\n'
                                             '- If no field is mapped to '
                                             '`x` channel, the `width` '
                                             'will be the value of '
                                             '[`config.scale.textXRangeStep`](https://vega.github.io/vega-lite/docs/size.html#default-width-and-height) '
                                             'for `text` mark and the '
                                             'value of `rangeStep` for '
                                             'other marks.\n'
                                             '\n'
                                             '__Note:__ For plots with '
                                             '[`row` and `column` '
                                             'channels](https://vega.github.io/vega-lite/docs/encoding.html#facet), '
                                             'this represents the width of '
                                             'a single view.\n'
                                             '\n'
                                             '__See also:__ The '
                                             'documentation for [width and '
                                             'height](https://vega.github.io/vega-lite/docs/size.html) '
                                             'contains more examples.',
                              'type': 'number'}},
     'required': ['mark'],
     'type': 'object'}

On instance:
    {'$schema': 'https://vega.github.io/schema/vega-lite/v2.json',
     'height': 300,
     'width': 400}
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-33e15bb25d36> in <module>()
----> 1 alt.Chart()

~/anaconda/envs/vega3/lib/python3.6/site-packages/IPython/core/displayhook.py in __call__(self, result)
    255             self.start_displayhook()
    256             self.write_output_prompt()
--> 257             format_dict, md_dict = self.compute_format_data(result)
    258             self.update_user_ns(result)
    259             self.fill_exec_result(result)

~/anaconda/envs/vega3/lib/python3.6/site-packages/IPython/core/displayhook.py in compute_format_data(self, result)
    149 
    150         """
--> 151         return self.shell.display_formatter.format(result)
    152 
    153     # This can be set to True by the write_output_prompt method in a subclass

~/anaconda/envs/vega3/lib/python3.6/site-packages/IPython/core/formatters.py in format(self, obj, include, exclude)
    148             return {}, {}
    149 
--> 150         format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
    151 
    152         if format_dict or md_dict:

TypeError: 'NoneType' object is not iterable
@jakevdp jakevdp added this to the 2.0 milestone Feb 24, 2018
@ellisonbg
Copy link
Collaborator

ellisonbg commented Feb 24, 2018 via email

@jakevdp
Copy link
Collaborator Author

jakevdp commented Mar 10, 2018

Edit: current behavior is better, but still has an extra error from the renderer:

---------------------------------------------------------------------------
SchemaValidationError                     Traceback (most recent call last)
~/anaconda/envs/altair-dev/lib/python3.6/site-packages/IPython/core/formatters.py in __call__(self, obj, include, exclude)
    968 
    969             if method is not None:
--> 970                 return method(include=include, exclude=exclude)
    971             return None
    972         else:

~/github/altair-viz/altair/altair/vegalite/v2/api.py in _repr_mimebundle_(self, include, exclude)
    320     def _repr_mimebundle_(self, include, exclude):
    321         """Return a MIME bundle for display in Jupyter frontends."""
--> 322         return renderers.get()(self.to_dict())
    323 
    324     def repeat(self, row=Undefined, column=Undefined, **kwargs):

~/github/altair-viz/altair/altair/vegalite/v2/api.py in to_dict(self, *args, **kwargs)
    254         if dct is None:
    255             kwargs['validate'] = 'deep'
--> 256             dct = super(TopLevelMixin, copy).to_dict(*args, **kwargs)
    257 
    258         if is_top_level:

~/github/altair-viz/altair/altair/utils/schemapi.py in to_dict(self, validate, ignore, context)
    228                 self.validate(result)
    229             except jsonschema.ValidationError as err:
--> 230                 raise SchemaValidationError(self, err)
    231         return result
    232 

SchemaValidationError: Invalid specification

        altair.vegalite.v2.api.Chart, validating 'required'

        'mark' is a required property
        
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-9828fa16e394> in <module>()
      1 import altair as alt
----> 2 alt.Chart()

~/anaconda/envs/altair-dev/lib/python3.6/site-packages/IPython/core/displayhook.py in __call__(self, result)
    255             self.start_displayhook()
    256             self.write_output_prompt()
--> 257             format_dict, md_dict = self.compute_format_data(result)
    258             self.update_user_ns(result)
    259             self.fill_exec_result(result)

~/anaconda/envs/altair-dev/lib/python3.6/site-packages/IPython/core/displayhook.py in compute_format_data(self, result)
    149 
    150         """
--> 151         return self.shell.display_formatter.format(result)
    152 
    153     # This can be set to True by the write_output_prompt method in a subclass

~/anaconda/envs/altair-dev/lib/python3.6/site-packages/IPython/core/formatters.py in format(self, obj, include, exclude)
    148             return {}, {}
    149 
--> 150         format_dict, md_dict = self.mimebundle_formatter(obj, include=include, exclude=exclude)
    151 
    152         if format_dict or md_dict:

TypeError: 'NoneType' object is not iterable

@ellisonbg
Copy link
Collaborator

This may have been fixed here:

ipython/ipython#10896

But not released yet. Eventually, we should maybe test the version of ipython and only do the hack for versions < 6.2 or 5.6.

@jakevdp jakevdp closed this as completed Mar 25, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants