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

Dict.toObject and fix Dict and List conversion #72

Merged
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
48 changes: 43 additions & 5 deletions js/dict.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,52 @@ export class Dict {

async values() {
const values = await this._client.hVals(this._key);
return values.map((x) => JSON.parse(x)); // Parse the values
return values.map((x) => {
const value = JSON.parse(x);
if (typeof value === "string") {
if (value.startsWith("znsocket.List:")) {
const refKey = value.split(/:(.+)/)[1];
return new ZnSocketList({ client: this._client,socket: this._socket , key: refKey});
} else if (value.startsWith("znsocket.Dict:")) {
const refKey = value.split(/:(.+)/)[1];
return new Dict({ client: this._client, socket: this._socket , key: refKey});
}
}
return value;
});
}

async entries() { // Renamed from items to entries
async entries() {
const entries = await this._client.hGetAll(this._key);
return Object.entries(entries).map(
([key, value]) => [key, JSON.parse(value)]
);
return Object.entries(entries).map(([key, value]) => {
const parsedValue = JSON.parse(value);

if (typeof parsedValue === "string") {
if (parsedValue.startsWith("znsocket.List:")) {
const refKey = parsedValue.split(/:(.+)/)[1];
return [key, new ZnSocketList({ client: this._client, socket: this._socket, key: refKey })];
} else if (parsedValue.startsWith("znsocket.Dict:")) {
const refKey = parsedValue.split(/:(.+)/)[1];
return [key, new Dict({ client: this._client, socket: this._socket, key: refKey })];
}
}

return [key, parsedValue];
});
}

async toObject() {
const entries = await this.entries();
// go through all and if one of them is a Dict or List, call toObject on it
const obj = {};
for (const [key, value] of entries) {
if (value instanceof Dict || value instanceof ZnSocketList) {
obj[key] = await value.toObject();
} else {
obj[key] = value;
}
}
return obj;
}

onRefresh(callback) {
Expand Down
3 changes: 2 additions & 1 deletion js/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ export class Dict {
clear(): Promise<any>;
keys(): Promise<string[]>;
values(): Promise<any[]>;
entries(): Promise<[string, any][]>; // Renamed from items to entries
entries(): Promise<[string, any][]>;
toObject(): Promise<Record<string, any>>;

onRefresh(callback: (data: { keys?: string[]; indices?: number[] }) => void): void;
offRefresh(): void;
Expand Down
21 changes: 21 additions & 0 deletions js_tests/native.dict.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ test("native_dict_in_dict", async () => {
expect(dictValue._key).toBe(dct1._key);
const helloValue2 = await dictValue.get("Hello");
expect(helloValue2).toBe("World");

const dct2Values = await dct2.values();
expect(await dct2Values[0]["Hello"]).toEqual("World");

const dct2Entries = await dct2.entries();
expect(await dct2Entries[0][1]["Hello"]).toEqual("World");
expect(await dct2Entries[0][0]).toEqual("dict");
});

test("native_dict_with_list", async () => {
Expand All @@ -251,3 +258,17 @@ test("native_dict_with_list", async () => {
expect(await listInstance.get(0)).toBe("A");
expect(await listInstance.get(1)).toBe("B");
});


test("native_dict_to_object", async () => {
let dct1 = new Dict({ client: client, key: "dict:test:1" });
let dct2 = new Dict({ client: client, key: "dict:test:2" });

await dct1.set("Hello", "World");
await dct2.set("dict", dct1);

// convert to object
const obj = await dct2.toObject();
expect(obj).toEqual({ dict: { Hello: "World" } });

});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "znsocket",
"version": "0.2.5",
"version": "0.2.6",
"description": "JS interface for the python znsocket package",
"main": "js/index.js",
"types": "js/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "znsocket"
version = "0.2.5"
version = "0.2.6"
description = "Python implementation of a Redis-compatible API using websockets."
authors = ["Fabian Zills <[email protected]>"]
license = "Apache-2.0"
Expand Down
25 changes: 21 additions & 4 deletions znsocket/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def __init__(
callbacks: dict[str, Callable]
optional function callbacks for methods
which modify the database.
repr_type: str
repr_type: "keys"|"minimal"|"full"
Control the `repr` appearance of the object.
Reduce for better performance.

Expand Down Expand Up @@ -374,7 +374,7 @@ def __getitem__(self, key: str) -> t.Any:
value = List(r=self.redis, key=key)
elif value.startswith("znsocket.Dict:"):
key = value.split(":", 1)[1]
value = Dict(r=self.redis, key=key)
value = Dict(r=self.redis, key=key, repr_type=self.repr_type)
return value

def __setitem__(self, key: str, value: t.Any) -> None:
Expand Down Expand Up @@ -415,13 +415,30 @@ def keys(self) -> list[str]:
def values(self) -> list[t.Any]:
response = []
for v in self.redis.hvals(self.key):
response.append(_decode(self, v))
value = _decode(self, v)
if isinstance(value, str):
if value.startswith("znsocket.List:"):
key = value.split(":", 1)[1]
value = List(r=self.redis, key=key)
elif value.startswith("znsocket.Dict:"):
key = value.split(":", 1)[1]
value = Dict(r=self.redis, key=key, repr_type=self.repr_type)
response.append(value)
return response

def items(self) -> list[t.Tuple[str, t.Any]]:
response = []
for k, v in self.redis.hgetall(self.key).items():
response.append((k, _decode(self, v)))
value = _decode(self, v)
if isinstance(value, str):
if value.startswith("znsocket.List:"):
key = value.split(":", 1)[1]
value = List(r=self.redis, key=key)
elif value.startswith("znsocket.Dict:"):
key = value.split(":", 1)[1]
value = Dict(r=self.redis, key=key, repr_type=self.repr_type)

response.append((k, value))
return response

def __contains__(self, key: str) -> bool:
Expand Down
Loading