Inconsistency with table.update() in Python with Dicts #1268
Closed
Description
Bug Report
First off, thank you for making this great package.
I have noticed a undocumented inconsistency with the table.update
function in the Python API.
If you format the update
data as a dict that maps to lists/arrays, it replaces the entry at the index instead of updating the fields.
TABLE.update({"index": ["b"], "num": [0], "static": [0]}) # initial data
TABLE.update({"index": ["b"], "num": [1]}) # this REPLACES the info at index "b" instead of updates
in the above code, the second update deletes the static
value of index
"b"
Basically, I expected
"index": "b", "num": 0, "static": 0 --> "index": "b", "num": 1, "static": 0
but got
"index": "b", "num": 0, "static": 0 --> "index": "b", "num": 1
If one does
BASE_TABLE.update([{"index": "b", "num": i}]) # no list inside the dictionary
it works though.
Steps to Reproduce:
Here is an MVP of the bug that connects to LocalHost
import asyncio
import threading
import tornado
import perspective
def perspective_thread(MANAGER):
loop = tornado.ioloop.IOLoop()
MANAGER.set_loop_callback(loop.add_callback)
loop.start()
class MainHandler(tornado.web.RequestHandler):
def get(self):
html = """<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{ table_name }}</title>
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<script src="https://cdn.jsdelivr.net/npm/@finos/perspective-workspace"></script>
<script src="https://cdn.jsdelivr.net/npm/@finos/perspective-viewer-datagrid"></script>
<script src="https://cdn.jsdelivr.net/npm/@finos/perspective-viewer-d3fc"></script>
<script src="https://cdn.jsdelivr.net/npm/@finos/perspective/dist/umd/perspective.js"></script>
</head>
<style>
perspective-viewer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>
<body>
<perspective-viewer id="viewer" , plugin="datagrid"></perspective-viewer>
<script>
websocket_url = 'ws://localhost:8080/websocket'
table_name = 'test_table'
window.addEventListener('WebComponentsReady', async function () {
const viewer = document.getElementById('viewer');
const websocket = perspective.websocket(websocket_url);
const table = websocket.open_table(table_name);
viewer.load(table);
viewer.toggleConfig();
});
</script>
</body>
</html>"""
self.write(html)
def make_app(MANAGER,):
handlers = [
(r"/", MainHandler,),
(
r"/websocket",
perspective.PerspectiveTornadoHandler,
{"manager": MANAGER, "check_origin": True},
),
]
app = tornado.web.Application(handlers)
return app
async def main(port):
MANAGER = perspective.PerspectiveManager()
columns = {"index": str, "num": int, "static": int}
BASE_TABLE = perspective.Table(columns, index="index",)
MANAGER.host_table("test_table", BASE_TABLE)
thread = threading.Thread(target=perspective_thread, args=(MANAGER,))
thread.daemon = True
thread.start()
app = make_app(MANAGER)
app.listen(port)
i = 0
BASE_TABLE.update({"index": ["b", "c"], "num": [0, 1], "static": [0, 1]})
while True:
await asyncio.sleep(1)
BASE_TABLE.update({"index": ["b"], "num": [i]})
# BASE_TABLE.update([{"index": "b", "num": i}])
i += 1
if __name__ == "__main__":
port = 8080
asyncio.run(main(port))
Environment:
linux, py38