Yield with uploads (#1339)

This commit is contained in:
Elijah Ahianyo 2023-07-18 21:06:57 +00:00 committed by GitHub
parent 3f151f054d
commit ca11b82432
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 36 deletions

View File

@ -323,21 +323,26 @@ export const uploadFiles = async (state, setResult, handler) => {
}
// Send the file to the server.
await axios.post(UPLOADURL, formdata, headers).then((response) => {
// Apply the delta and set the result.
const update = response.data;
applyDelta(state, update.delta);
// Set processing to false and return.
setResult({
state: state,
events: update.events,
final: true,
processing: false,
});
});
return true;
await axios.post(UPLOADURL, formdata, headers)
.then(() => { return true; })
.catch(
error => {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log(error.message);
}
return false;
}
)
};
/**

View File

@ -88,6 +88,9 @@ class App(Base):
# The component to render if there is a connection error to the server.
connect_error_component: Optional[Component] = None
# The async server name space
event_namespace: Optional[AsyncNamespace] = None
def __init__(self, *args, **kwargs):
"""Initialize the app.
@ -127,11 +130,10 @@ class App(Base):
self.socket_app = ASGIApp(self.sio, socketio_path="")
# Create the event namespace and attach the main app. Not related to any paths.
event_namespace = EventNamespace("/event", self)
self.event_namespace = EventNamespace("/event", self)
# Register the event namespace with the socket.
self.sio.register_namespace(event_namespace)
self.sio.register_namespace(self.event_namespace)
# Mount the socket app with the API.
self.api.mount(str(constants.Endpoint.EVENT), self.socket_app)
@ -592,9 +594,6 @@ def upload(app: App):
Args:
files: The file(s) to upload.
Returns:
The state update after processing the event.
Raises:
ValueError: if there are no args with supported annotation.
"""
@ -603,10 +602,10 @@ def upload(app: App):
for file in files:
assert file.filename is not None
file.filename = file.filename.split(":")[-1]
# Get the state for the session.
state = app.state_manager.get_state(token)
# get the current session ID
sid = state.get_sid()
# get the current state(parent state/substate)
path = handler.split(".")[:-1]
current_state = state.get_substate(path)
@ -636,12 +635,17 @@ def upload(app: App):
name=handler,
payload={handler_upload_param[0]: files},
)
# TODO: refactor this to handle yields.
update = await state._process(event).__anext__()
async for update in state._process(event):
# Postprocess the event.
update = await app.postprocess(state, event, update)
# Send update to client
await asyncio.create_task(
app.event_namespace.emit( # type: ignore
str(constants.SocketEvent.EVENT), update.json(), to=sid
)
)
# Set the state for the session.
app.state_manager.set_state(event.token, state)
return update
return upload_file

View File

@ -602,7 +602,7 @@ async def test_dict_mutation_detection__plain_list(
@pytest.mark.asyncio
@pytest.mark.parametrize(
"fixture, expected",
"fixture, delta",
[
(
"upload_state",
@ -626,22 +626,23 @@ async def test_dict_mutation_detection__plain_list(
),
],
)
async def test_upload_file(fixture, request, expected):
async def test_upload_file(fixture, request, delta):
"""Test that file upload works correctly.
Args:
fixture: The state.
request: Fixture request.
expected: Expected delta
delta: Expected delta
"""
app = App(state=request.getfixturevalue(fixture))
app.event_namespace.emit = AsyncMock() # type: ignore
current_state = app.state_manager.get_state("token")
data = b"This is binary data"
# Create a binary IO object and write data to it
bio = io.BytesIO()
bio.write(data)
app = App(state=request.getfixturevalue(fixture))
file1 = UploadFile(
filename="token:file_upload_state.multi_handle_upload:True:image1.jpg",
file=bio,
@ -650,10 +651,17 @@ async def test_upload_file(fixture, request, expected):
filename="token:file_upload_state.multi_handle_upload:True:image2.jpg",
file=bio,
)
fn = upload(app)
result = await fn([file1, file2]) # type: ignore
assert isinstance(result, StateUpdate)
assert result.delta == expected
upload_fn = upload(app)
await upload_fn([file1, file2])
state_update = StateUpdate(delta=delta, events=[], final=True)
app.event_namespace.emit.assert_called_with( # type: ignore
"event", state_update.json(), to=current_state.get_sid()
)
assert app.state_manager.get_state("token").dict()["img_list"] == [
"image1.jpg",
"image2.jpg",
]
@pytest.mark.asyncio