diff --git a/marshmallow/decorators.py b/marshmallow/decorators.py index 8b6df0df2..8ea52a44a 100644 --- a/marshmallow/decorators.py +++ b/marshmallow/decorators.py @@ -69,7 +69,8 @@ def validates(field_name): return tag_processor(VALIDATES, None, False, field_name=field_name) -def validates_schema(fn=None, pass_many=False, pass_original=False, skip_on_field_errors=True): +def validates_schema(fn=None, pass_many=False, pass_original=False, skip_on_field_errors=True, + order=0): """Register a schema-level validator. By default, receives a single object at a time, regardless of whether ``many=True`` @@ -86,10 +87,10 @@ def validates_schema(fn=None, pass_many=False, pass_original=False, skip_on_fiel ``skip_on_field_errors`` defaults to `True`. """ return tag_processor(VALIDATES_SCHEMA, fn, pass_many, pass_original=pass_original, - skip_on_field_errors=skip_on_field_errors) + skip_on_field_errors=skip_on_field_errors, order=order) -def pre_dump(fn=None, pass_many=False): +def pre_dump(fn=None, pass_many=False, order=0): """Register a method to invoke before serializing an object. The method receives the object to be serialized and returns the processed object. @@ -97,10 +98,10 @@ def pre_dump(fn=None, pass_many=False): is passed to the `Schema`. If ``pass_many=True``, the raw data (which may be a collection) and the value for ``many`` is passed. """ - return tag_processor(PRE_DUMP, fn, pass_many) + return tag_processor(PRE_DUMP, fn, pass_many, order=order) -def post_dump(fn=None, pass_many=False, pass_original=False): +def post_dump(fn=None, pass_many=False, pass_original=False, order=0): """Register a method to invoke after serializing an object. The method receives the serialized object and returns the processed object. @@ -108,10 +109,10 @@ def post_dump(fn=None, pass_many=False, pass_original=False): argument passed to the Schema. If ``pass_many=True``, the raw data (which may be a collection) and the value for ``many`` is passed. """ - return tag_processor(POST_DUMP, fn, pass_many, pass_original=pass_original) + return tag_processor(POST_DUMP, fn, pass_many, pass_original=pass_original, order=order) -def pre_load(fn=None, pass_many=False): +def pre_load(fn=None, pass_many=False, order=0): """Register a method to invoke before deserializing an object. The method receives the data to be deserialized and returns the processed data. @@ -119,10 +120,10 @@ def pre_load(fn=None, pass_many=False): argument passed to the Schema. If ``pass_many=True``, the raw data (which may be a collection) and the value for ``many`` is passed. """ - return tag_processor(PRE_LOAD, fn, pass_many) + return tag_processor(PRE_LOAD, fn, pass_many, order=order) -def post_load(fn=None, pass_many=False, pass_original=False): +def post_load(fn=None, pass_many=False, pass_original=False, order=0): """Register a method to invoke after deserializing an object. The method receives the deserialized data and returns the processed data. @@ -130,7 +131,7 @@ def post_load(fn=None, pass_many=False, pass_original=False): argument passed to the Schema. If ``pass_many=True``, the raw data (which may be a collection) and the value for ``many`` is passed. """ - return tag_processor(POST_LOAD, fn, pass_many, pass_original=pass_original) + return tag_processor(POST_LOAD, fn, pass_many, pass_original=pass_original, order=order) def tag_processor(tag_name, fn, pass_many, **kwargs): diff --git a/marshmallow/schema.py b/marshmallow/schema.py index 0b5f04477..cb6672c70 100644 --- a/marshmallow/schema.py +++ b/marshmallow/schema.py @@ -164,14 +164,19 @@ def _resolve_processors(self): try: processor_tags = attr.__marshmallow_tags__ + processor_kwargs = attr.__marshmallow_kwargs__ except AttributeError: continue self._has_processors = bool(processor_tags) for tag in processor_tags: + order = processor_kwargs[tag].get('order') # Use name here so we can get the bound method later, in case # the processor was a descriptor or something. - self.__processors__[tag].append(attr_name) + self.__processors__[tag].append((order, attr_name)) + + for tag, processors in iteritems(self.__processors__): + self.__processors__[tag] = [attr_name for _, attr_name in sorted(processors)] class SchemaOpts(object):