Repository: vega/altair

Issue:
Internal: from_dict does strange things with new class hierarchy
Example:
```
>>> alt.Encoding.from_dict({'y': {'field': 'foo', 'type': 'quantitative'}})
Encoding({
  y: X({
    field: FieldName('foo'),
    type: StandardType('quantitative')
  })
})
```
Second example:
```python
>>> import altair as alt
>>> import warnings
>>> warnings.simplefilter("error", alt.utils.AltairDeprecationWarning)
>>> alt.FacetedEncoding.from_dict({'x2': {'field': 'x_binned2'}})
```
```pytb
---------------------------------------------------------------------------
AltairDeprecationWarning                  Traceback (most recent call last)
<ipython-input-1-0497467f0bab> in <module>
      2 import warnings
      3 warnings.simplefilter("error", alt.utils.AltairDeprecationWarning)
----> 4 alt.FacetedEncoding.from_dict({'x2': {'field': 'x_binned2'}})

~/anaconda/envs/python3.7/lib/python3.7/site-packages/altair/utils/schemapi.py in from_dict(cls, dct, validate, _wrapper_classes)
    383             _wrapper_classes = cls._default_wrapper_classes()
    384         converter = _FromDict(_wrapper_classes)
--> 385         return converter.from_dict(dct, cls)
    386 
    387     @classmethod

~/anaconda/envs/python3.7/lib/python3.7/site-packages/altair/utils/schemapi.py in from_dict(self, dct, cls, schema, rootschema)
    530                     val = self.from_dict(val,
    531                         schema=props[key],
--> 532                         rootschema=rootschema
    533                     )
    534                 kwds[key] = val

~/anaconda/envs/python3.7/lib/python3.7/site-packages/altair/utils/schemapi.py in from_dict(self, dct, cls, schema, rootschema)
    519                     return self.from_dict(dct,
    520                         schema=possible_schema,
--> 521                         rootschema=rootschema,
    522                     )
    523 

~/anaconda/envs/python3.7/lib/python3.7/site-packages/altair/utils/schemapi.py in from_dict(self, dct, cls, schema, rootschema)
    533                     )
    534                 kwds[key] = val
--> 535             return cls(**kwds)
    536 
    537         elif isinstance(dct, list):

~/anaconda/envs/python3.7/lib/python3.7/site-packages/altair/utils/deprecation.py in new_obj(*args, **kwargs)
     41         # @functools.wraps(obj)  # TODO: use this in Py3 only
     42         def new_obj(*args, **kwargs):
---> 43             warnings.warn(message, AltairDeprecationWarning)
     44             return obj(*args, **kwargs)
     45         return new_obj

AltairDeprecationWarning: alt.Yerror is deprecated. Use alt.YError instead.
```


Discussion:

Resolving patch:
diff --git a/altair/utils/schemapi.py b/altair/utils/schemapi.py
--- a/altair/utils/schemapi.py
+++ b/altair/utils/schemapi.py
@@ -492,11 +492,11 @@ def _passthrough(*args, **kwds):
             return args[0] if args else kwds
 
         if cls is None:
-            # If there are multiple matches, we use the last one in the dict.
+            # If there are multiple matches, we use the first one in the dict.
             # Our class dict is constructed breadth-first from top to bottom,
-            # so the last class that matches is the most specific.
+            # so the first class that matches is the most general match.
             matches = self.class_dict[self.hash_schema(schema)]
-            cls = matches[-1] if matches else _passthrough
+            cls = matches[0] if matches else _passthrough
         schema = _resolve_references(schema, rootschema)
 
         if 'anyOf' in schema or 'oneOf' in schema:
diff --git a/tools/schemapi/schemapi.py b/tools/schemapi/schemapi.py
--- a/tools/schemapi/schemapi.py
+++ b/tools/schemapi/schemapi.py
@@ -488,11 +488,11 @@ def _passthrough(*args, **kwds):
             return args[0] if args else kwds
 
         if cls is None:
-            # If there are multiple matches, we use the last one in the dict.
+            # If there are multiple matches, we use the first one in the dict.
             # Our class dict is constructed breadth-first from top to bottom,
-            # so the last class that matches is the most specific.
+            # so the first class that matches is the most general match.
             matches = self.class_dict[self.hash_schema(schema)]
-            cls = matches[-1] if matches else _passthrough
+            cls = matches[0] if matches else _passthrough
         schema = _resolve_references(schema, rootschema)
 
         if 'anyOf' in schema or 'oneOf' in schema:


Test patch: