Skip to content

Inconsistency with table.update() in Python with Dicts #1268

Closed
@choandrew

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

Metadata

Assignees

Labels

PythonbugConcrete, reproducible bugs

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions