Skip to content

Commit

Permalink
Merge pull request #1803 from jakevdp/schema-inheritance
Browse files Browse the repository at this point in the history
Internal: add inheritance structure to core classes
  • Loading branch information
jakevdp authored Nov 23, 2019
2 parents 4f76460 + 015f2f2 commit 4c33b14
Show file tree
Hide file tree
Showing 11 changed files with 10,421 additions and 10,363 deletions.
17 changes: 15 additions & 2 deletions altair/utils/schemapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ def debug_mode(arg):
DEBUG_MODE = original


def _subclasses(cls):
"""Breadth-first sequence of all classes which inherit from cls."""
seen = set()
current_set = {cls}
while current_set:
seen |= current_set
current_set = set.union(*(set(cls.__subclasses__()) for cls in current_set))
for cls in current_set - seen:
yield cls


def _todict(obj, validate, context):
"""Convert an object to a dict representation."""
if isinstance(obj, SchemaBase):
Expand Down Expand Up @@ -337,7 +348,7 @@ def to_json(self, validate=True, ignore=[], context={},
@classmethod
def _default_wrapper_classes(cls):
"""Return the set of classes used within cls.from_dict()"""
return SchemaBase.__subclasses__()
return _subclasses(SchemaBase)

@classmethod
def from_dict(cls, dct, validate=True, _wrapper_classes=None):
Expand Down Expand Up @@ -487,7 +498,9 @@ def _passthrough(*args, **kwds):
return args[0] if args else kwds

if cls is None:
# TODO: do something more than simply selecting the last match?
# If there are multiple matches, we use the last 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.
matches = self.class_dict[self.hash_schema(schema)]
cls = matches[-1] if matches else _passthrough
schema = _resolve_references(schema, rootschema)
Expand Down
4 changes: 2 additions & 2 deletions altair/vega/v4/schema/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# The contents of this file are automatically written by
# tools/generate_schema_wrapper.py. Do not modify directly.

from altair.utils.schemapi import SchemaBase, Undefined
from altair.utils.schemapi import SchemaBase, Undefined, _subclasses

import pkgutil
import json
Expand All @@ -16,7 +16,7 @@ def load_schema():
class VegaSchema(SchemaBase):
@classmethod
def _default_wrapper_classes(cls):
return VegaSchema.__subclasses__()
return _subclasses(VegaSchema)


class Root(VegaSchema):
Expand Down
4 changes: 2 additions & 2 deletions altair/vega/v5/schema/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# The contents of this file are automatically written by
# tools/generate_schema_wrapper.py. Do not modify directly.

from altair.utils.schemapi import SchemaBase, Undefined
from altair.utils.schemapi import SchemaBase, Undefined, _subclasses

import pkgutil
import json
Expand All @@ -16,7 +16,7 @@ def load_schema():
class VegaSchema(SchemaBase):
@classmethod
def _default_wrapper_classes(cls):
return VegaSchema.__subclasses__()
return _subclasses(VegaSchema)


class Root(VegaSchema):
Expand Down
20 changes: 5 additions & 15 deletions altair/vegalite/v2/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ def _prepare_data(data, context):
data = _consolidate_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)):
if not isinstance(data, (dict, core.Data)):
warnings.warn("data of type {} not recognized".format(type(data)))

return data
Expand Down Expand Up @@ -329,19 +328,12 @@ def condition(predicate, if_true, if_false, **kwargs):
spec: dict or VegaLiteSchema
the spec that describes the condition
"""
selection_predicates = (core.SelectionNot, core.SelectionOr,
core.SelectionAnd, core.SelectionOperand)
test_predicates = (six.string_types, expr.Expression, core.Predicate,
core.LogicalOperandPredicate, core.LogicalNotPredicate,
core.LogicalOrPredicate, core.LogicalAndPredicate,
core.FieldEqualPredicate, core.FieldOneOfPredicate,
core.FieldRangePredicate, core.FieldLTPredicate,
core.FieldGTPredicate, core.FieldLTEPredicate,
core.FieldGTEPredicate, core.SelectionPredicate)
test_predicates = (six.string_types, expr.Expression,
core.LogicalOperandPredicate)

if isinstance(predicate, NamedSelection):
condition = {'selection': predicate._get_name()}
elif isinstance(predicate, selection_predicates):
elif isinstance(predicate, core.SelectionOperand):
condition = {'selection': predicate}
elif isinstance(predicate, test_predicates):
condition = {'test': predicate}
Expand Down Expand Up @@ -872,11 +864,9 @@ def transform_filter(self, filter, **kwargs):
alt.FilterTransform : underlying transform object
"""
selection_predicates = (core.SelectionNot, core.SelectionOr,
core.SelectionAnd, core.SelectionOperand)
if isinstance(filter, NamedSelection):
filter = {'selection': filter._get_name()}
elif isinstance(filter, selection_predicates):
elif isinstance(filter, core.SelectionOperand):
filter = {'selection': filter}
return self._add_transform(core.FilterTransform(filter=filter, **kwargs))

Expand Down
Loading

0 comments on commit 4c33b14

Please sign in to comment.