diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fb4819c6..fe5ed9c4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -6,6 +6,7 @@ unreleased Bug fixes: +- Keep custom field mappings scoped to each ``MarshmallowPlugin`` instance. - Recognize ``trace`` operations defined in view docstrings, instead of silently dropping them (:pr:`1059`). Thanks :user:`binggao1230` for the PR. diff --git a/src/apispec/ext/marshmallow/openapi.py b/src/apispec/ext/marshmallow/openapi.py index 3663fce6..803c4a20 100644 --- a/src/apispec/ext/marshmallow/openapi.py +++ b/src/apispec/ext/marshmallow/openapi.py @@ -57,6 +57,7 @@ def __init__( schema_name_resolver, spec: APISpec, ) -> None: + self.field_mapping = self.field_mapping.copy() self.openapi_version = ( Version(openapi_version) if isinstance(openapi_version, str) diff --git a/tests/test_ext_marshmallow.py b/tests/test_ext_marshmallow.py index fc40046e..8f303226 100644 --- a/tests/test_ext_marshmallow.py +++ b/tests/test_ext_marshmallow.py @@ -318,6 +318,45 @@ def test_can_use_schema_in_header(self, spec, schema): class TestCustomField: + def test_custom_field_mapping_is_scoped_to_plugin(self): + class CustomField(String): + pass + + first_plugin = MarshmallowPlugin() + second_plugin = MarshmallowPlugin() + APISpec( + title="First", + version="1.0", + openapi_version="3.0.0", + plugins=[first_plugin], + ) + APISpec( + title="Second", + version="1.0", + openapi_version="3.0.0", + plugins=[second_plugin], + ) + + first_plugin.map_to_openapi_type(CustomField, "integer", "int32") + assert first_plugin.converter.field2property(CustomField()) == { + "type": "integer", + "format": "int32", + } + assert second_plugin.converter.field2property(CustomField()) == { + "type": "string" + } + + third_plugin = MarshmallowPlugin() + APISpec( + title="Third", + version="1.0", + openapi_version="3.0.0", + plugins=[third_plugin], + ) + assert third_plugin.converter.field2property(CustomField()) == { + "type": "string" + } + def test_can_use_custom_field_decorator(self, spec_fixture): class CustomNameA(Field): pass