Benjamin-eecs/openrsi-commit-runtime-assets
0168
1diff --git a/CHANGELOG.rst b/CHANGELOG.rst2index d02eb12..3ba8020 1006443--- a/CHANGELOG.rst4+++ b/CHANGELOG.rst5@@ -1,9 +1,34 @@6 Changelog7 ---------8 9-8.3.1 (Unreleased)10+8.4.0 (Unreleased)11 ******************12 13+Features:14+15+* Add a new class attribute, ``empty_value`` to ``DelimitedList`` and16+ ``DelimitedTuple``, with a default of ``""``.17+ This controls the value deserialized when an empty string is seen.18+19+``empty_value`` can be used to handle types other than strings more gracefully, e.g.20+21+.. code-block:: python22+23+ from webargs import fields24+25+26+ class IntList(fields.DelimitedList):27+ empty_value = 028+29+30+ myfield = IntList(fields.Int())31+32+.. note::33+34+ ``empty_value`` will be changing in webargs v9.0 to be ``missing`` by35+ default. This will allow use of fields with ``load_default`` to specify36+ handling of the empty value.37+38 Changes:39 40 * Type annotations for ``FlaskParser`` have been improved41diff --git a/src/webargs/fields.py b/src/webargs/fields.py42index 5598b54..96590a3 10064443--- a/src/webargs/fields.py44+++ b/src/webargs/fields.py45@@ -15,6 +15,8 @@ tells webargs where to parse the request argument from.46 """47 from __future__ import annotations48 49+import typing50+51 import marshmallow as ma52 53 # Expose all fields from marshmallow.fields.54@@ -64,6 +66,8 @@ class DelimitedFieldMixin:55 delimiter: str = ","56 # delimited fields set is_multiple=False for webargs.core.is_multiple57 is_multiple: bool = False58+ # NOTE: in 8.x this defaults to "" but in 9.x it will be 'missing'59+ empty_value: typing.Any = ""60 61 def _serialize(self, value, attr, obj, **kwargs):62 # serializing will start with parent-class serialization, so that we correctly63@@ -77,6 +81,8 @@ class DelimitedFieldMixin:64 if not isinstance(value, (str, bytes)):65 raise self.make_error("invalid")66 values = value.split(self.delimiter) if value else []67+ # convert empty strings to the empty value; typically "" and therefore a no-op68+ values = [v or self.empty_value for v in values]69 return super()._deserialize(values, attr, data, **kwargs)70 71 72@@ -117,6 +123,12 @@ class DelimitedTuple(DelimitedFieldMixin, ma.fields.Tuple):73 74 default_error_messages = {"invalid": "Not a valid delimited tuple."}75 76- def __init__(self, tuple_fields, *, delimiter: str | None = None, **kwargs):77+ def __init__(78+ self,79+ tuple_fields,80+ *,81+ delimiter: str | None = None,82+ **kwargs,83+ ):84 self.delimiter = delimiter or self.delimiter85 super().__init__(tuple_fields, **kwargs)86 