Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ListTarget and associated test case #108

Merged
merged 6 commits into from
Jul 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions streaming_form_data/targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,47 @@ def value(self):
return b"".join(self._values)


class ListTarget(BaseTarget):
"""ListTarget stores the input in an in-memory list of bytes,
which is then joined into the final value and appended to an in-memory
list of byte strings when each value is finished.

This is usefull for situations where more than one value may be submitted for
the same argument.
"""

def __init__(self, _type=bytes, *args, **kwargs):
super().__init__(*args, **kwargs)

self._temp_value = []
self._values = []
self._type = _type

def on_data_received(self, chunk: bytes):
self._temp_value.append(chunk)

def on_finish(self):
value = b"".join(self._temp_value)
self._temp_value = []

if self._type == str:
value = value.decode("UTF-8")
elif self._type == bytes:
pass # already is bytes, no need to do anything
else:
value = self._type(value)

self._values.append(value)

@property
def value(self):
return self._values

@property
def finished(self):
return self._finished


class FileTarget(BaseTarget):
"""FileTarget writes (streams) the input to an on-disk file."""

Expand Down
33 changes: 33 additions & 0 deletions tests/test_targets.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
DirectoryTarget,
NullTarget,
ValueTarget,
ListTarget,
S3Target,
CSVTarget,
)
Expand Down Expand Up @@ -82,6 +83,38 @@ def test_value_target_total_size_validator():
target.data_received(b"world")


def test_list_target_basic():
target = ListTarget()

assert target.value == []

target.multipart_filename = None

target.start()
assert target.multipart_filename is None
assert target.value == []

# Send and finish multiple values
target.data_received(b"Cat")
target.finish()
target.data_received(b"Dog")
target.finish()
target.data_received(b"Big")
target.data_received(b" ")
target.data_received(b"Goldfish")
target.finish()

assert target.multipart_filename is None
assert target.value == [b"Cat", b"Dog", b"Big Goldfish"]


def test_list_target_not_set():
target = ListTarget()

assert target.multipart_filename is None
assert target.value == []


def test_file_target_basic():
filename = os.path.join(tempfile.gettempdir(), "file.txt")

Expand Down
Loading