Repository: marshmallow-code/apispec
Pull request #648 (2021-03-21 05:48:50)

Allow to_yaml to pass options to yaml.dump
When generating YAML with unicode, it is very annoying to have escaped unicode like `\uAC00`.

This PR allows `APISpec.to_yaml` method to pass additional options for `yaml.dump`.

With this PR, I can use options like `allow_unicode=True` to resolve the problem mention above.

lafrech: Thanks. The implementation is fine.

I'm just wondering whether passing all args/kwargs to `dict_to_yaml` is the right API. If someday we decided that `to_dict` also takes parameters, we'd be screwed.

Should we namespace that in a `yaml_dump_kwargs` argument?

Patch:
diff --git a/AUTHORS.rst b/AUTHORS.rst
index d1fed7e..71932f6 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -67,3 +67,4 @@ Contributors (chronological)
 - David Bishop `@teancom <https://github.com/teancom>`_
 - Andrea Ghensi `@sanzoghenzo <https://github.com/sanzoghenzo>`_
 - `@timsilvers <https://github.com/timsilvers>`_
+- Kangwook Lee `@pbzweihander <https://github.com/pbzweihander>`_
diff --git a/setup.py b/setup.py
index 444515d..6280d8f 100644
--- a/setup.py
+++ b/setup.py
@@ -8,7 +8,7 @@ EXTRAS_REQUIRE = {
     "docs": [
         "marshmallow>=3.0.0",
         "pyyaml==5.4.1",
-        "sphinx==3.5.3",
+        "sphinx==3.5.2",
         "sphinx-issues==1.2.0",
         "sphinx-rtd-theme==0.5.1",
     ],
diff --git a/src/apispec/core.py b/src/apispec/core.py
index 13861ef..150e532 100644
--- a/src/apispec/core.py
+++ b/src/apispec/core.py
@@ -238,11 +238,14 @@ class APISpec:
         ret = deepupdate(ret, self.options)
         return ret
 
-    def to_yaml(self):
-        """Render the spec to YAML. Requires PyYAML to be installed."""
+    def to_yaml(self, yaml_dump_kwargs=None):
+        """Render the spec to YAML. Requires PyYAML to be installed.
+
+        :param dict yaml_dump_kwargs: Additional keyword arguments to pass to `yaml.dump`
+        """
         from .yaml_utils import dict_to_yaml
 
-        return dict_to_yaml(self.to_dict())
+        return dict_to_yaml(self.to_dict(), yaml_dump_kwargs)
 
     def tag(self, tag):
         """ Store information about a tag.
diff --git a/src/apispec/yaml_utils.py b/src/apispec/yaml_utils.py
index 9b041e9..3033743 100644
--- a/src/apispec/yaml_utils.py
+++ b/src/apispec/yaml_utils.py
@@ -15,8 +15,10 @@ class YAMLDumper(yaml.Dumper):
 yaml.add_representer(OrderedDict, YAMLDumper._represent_dict, Dumper=YAMLDumper)
 
 
-def dict_to_yaml(dic):
-    return yaml.dump(dic, Dumper=YAMLDumper)
+def dict_to_yaml(dic, yaml_dump_kwargs=None):
+    if yaml_dump_kwargs is None:
+        yaml_dump_kwargs = {}
+    return yaml.dump(dic, Dumper=YAMLDumper, **yaml_dump_kwargs)
 
 
 def load_yaml_from_docstring(docstring):


Test patch:
diff --git a/tests/test_yaml_utils.py b/tests/test_yaml_utils.py
index 733f6a5..b538c01 100644
--- a/tests/test_yaml_utils.py
+++ b/tests/test_yaml_utils.py
@@ -26,3 +26,8 @@ def test_load_yaml_from_docstring_empty_docstring(docstring):
 @pytest.mark.parametrize("docstring", (None, "", "---"))
 def test_load_operations_from_docstring_empty_docstring(docstring):
     assert yaml_utils.load_operations_from_docstring(docstring) == {}
+
+
+def test_dict_to_yaml_unicode():
+    assert yaml_utils.dict_to_yaml({"가": "나"}) == '"\\uAC00": "\\uB098"\n'
+    assert yaml_utils.dict_to_yaml({"가": "나"}, {"allow_unicode": True}) == "가: 나\n"