# Path: scalymongo/structure_walker.py
# class StructureWalker(object):
#     """A helper class to recurse a :class:`dict`-like object in accordance with
#     a structure.
# 
#     :param field_translator: should be function mapping the ``value`` and
#         ``type_`` to the new value for a key.
# 
#     """
# 
#     def __init__(self, field_validator):
#         self.field_validator = field_validator
# 
#     def walk_dict(self, body, structure, path=None):
#         """Validate a dictionary in accordance with `structure`.
# 
#         A :class:`ValidationError` is raised if any fields in `body` are
#         not present in `structure`.
# 
#         """
#         _check_for_unknown_fields(body, structure, path)
# 
#         for field, sub_structure in structure.iteritems():
#             if isclass(field):
#                 field_type = field
#                 # For structures like {<TYPE>: {<STRUCT>}} iterate values
#                 # in the body with keys of <TYPE> and verify each against
#                 # <STRUCT>.
#                 for key, value in body.iteritems():
#                     if isinstance(key, field_type):
#                         self._recurse_or_validate_field(
#                             value, sub_structure, _join(path, key))
# 
#             if field in body:
#                 self._recurse_or_validate_field(
#                     body[field], sub_structure, _join(path, field))
# 
#     def _recurse_or_validate_field(self, value, sub_structure, path):
#         if isinstance(sub_structure, list):
#             assert len(sub_structure) == 1
#             if isinstance(value, dict):
#                 # If the structure is a dict this is fine so long as all of the
#                 # keys are integers or the positional operator (`$`). This
#                 # happens with the $set update modifier since we expand
#                 # {'foo.0.bar': 1} to {'foo': {'0': {'bar': 1}}}
#                 for key, value in value.iteritems():
#                     assert key.isdigit() or key == '$'
#                     self._recurse_or_validate_field(
#                         value, sub_structure[0], _join(path, key))
#             else:
#                 # Validate each value in the list against the specified content
#                 # type.
#                 for i, value in enumerate(value):
#                     self._recurse_or_validate_field(
#                         value, sub_structure[0], _join(path, i))
#             return
# 
#         if isinstance(sub_structure, dict):
#             self.walk_dict(value, sub_structure, path)
#             return
# 
#         self.field_validator(path, value, sub_structure)


from dingus import Dingus
from scalymongo.structure_walker import StructureWalker
            '$': Dingus('value_$'),
        }
        self.type = Dingus('type')
        self.body = {'x': self.values}
        self.structure = {'x': [self.type]}
        self.structure_walker.walk_dict(self.body, self.structure)

    def should_visit_x_0(self):
        assert self.field_validator.calls(
            '()', 'x.0', self.values['0'], self.type)

    def should_visit_x_1(self):
        assert self.field_validator.calls(
            '()', 'x.1', self.values['1'], self.type)

    def should_visit_x_positional(self):
        assert self.field_validator.calls(
            '()', 'x.$', self.values['$'], self.type)



class WhenWalkingStructureWithListOfDocuments(BaseStructureWalker):

    @classmethod
    def setup_class(self):
        BaseStructureWalker.setup_class()
        self.value_0_a = Dingus('value_0_a')
        self.value_0_b = Dingus('value_0_b')
        self.value_1_a = Dingus('value_1_a')
        self.value_1_b = Dingus('value_1_b')

# Path: scalymongo/structure_walker.py
# class StructureWalker(object):
#     """A helper class to recurse a :class:`dict`-like object in accordance with
#     a structure.
# 
#     :param field_translator: should be function mapping the ``value`` and
#         ``type_`` to the new value for a key.
# 
#     """
# 
#     def __init__(self, field_validator):
#         self.field_validator = field_validator
# 
#     def walk_dict(self, body, structure, path=None):
#         """Validate a dictionary in accordance with `structure`.
# 
#         A :class:`ValidationError` is raised if any fields in `body` are
#         not present in `structure`.
# 
#         """
#         _check_for_unknown_fields(body, structure, path)
# 
#         for field, sub_structure in structure.iteritems():
#             if isclass(field):
#                 field_type = field
#                 # For structures like {<TYPE>: {<STRUCT>}} iterate values
#                 # in the body with keys of <TYPE> and verify each against
#                 # <STRUCT>.
#                 for key, value in body.iteritems():
#                     if isinstance(key, field_type):
#                         self._recurse_or_validate_field(
#                             value, sub_structure, _join(path, key))
# 
#             if field in body:
#                 self._recurse_or_validate_field(
#                     body[field], sub_structure, _join(path, field))
# 
#     def _recurse_or_validate_field(self, value, sub_structure, path):
#         if isinstance(sub_structure, list):
#             assert len(sub_structure) == 1
#             if isinstance(value, dict):
#                 # If the structure is a dict this is fine so long as all of the
#                 # keys are integers or the positional operator (`$`). This
#                 # happens with the $set update modifier since we expand
#                 # {'foo.0.bar': 1} to {'foo': {'0': {'bar': 1}}}
#                 for key, value in value.iteritems():
#                     assert key.isdigit() or key == '$'
#                     self._recurse_or_validate_field(
#                         value, sub_structure[0], _join(path, key))
#             else:
#                 # Validate each value in the list against the specified content
#                 # type.
#                 for i, value in enumerate(value):
#                     self._recurse_or_validate_field(
#                         value, sub_structure[0], _join(path, i))
#             return
# 
#         if isinstance(sub_structure, dict):
#             self.walk_dict(value, sub_structure, path)
#             return
# 
#         self.field_validator(path, value, sub_structure)


# Path: tests/unit/test_structure_walker.py
from dingus import Dingus
from scalymongo.structure_walker import StructureWalker

            '$': Dingus('value_$'),
        }
        self.type = Dingus('type')
        self.body = {'x': self.values}
        self.structure = {'x': [self.type]}
        self.structure_walker.walk_dict(self.body, self.structure)

    def should_visit_x_0(self):
        assert self.field_validator.calls(
            '()', 'x.0', self.values['0'], self.type)

    def should_visit_x_1(self):
        assert self.field_validator.calls(
            '()', 'x.1', self.values['1'], self.type)

    def should_visit_x_positional(self):
        assert self.field_validator.calls(
            '()', 'x.$', self.values['$'], self.type)



class WhenWalkingStructureWithListOfDocuments(BaseStructureWalker):

    @classmethod
    def setup_class(self):
        BaseStructureWalker.setup_class()
        self.value_0_a = Dingus('value_0_a')
        self.value_0_b = Dingus('value_0_b')
        self.value_1_a = Dingus('value_1_a')
        self.value_1_b = Dingus('value_1_b')

        self.type_a = Dingus('type_a')