Skip to content

Make the client ready for the 1.3.0 release #58

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

Merged
merged 7 commits into from
Feb 27, 2025
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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
UPSTASH_REDIS_REST_URL="<UPSTASH_REDIS_REST_URL>"
UPSTASH_REDIS_REST_TOKEN="<UPSTASH_REDIS_REST_TOKEN>"
8 changes: 8 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ jobs:
- name: Set up Poetry environment
run: poetry install --no-root

- name: Run ruff
run: |
poetry run ruff check .

- name: Run ruff format
run: |
poetry run ruff format --check .

- name: Run mypy
run: |
poetry run mypy --show-error-codes .
Expand Down
15 changes: 8 additions & 7 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "upstash-redis"
version = "1.2.0"
version = "1.3.0"
description = "Serverless Redis SDK from Upstash"
license = "MIT"
authors = ["Upstash <[email protected]>", "Zgîmbău Tudor <[email protected]>"]
Expand All @@ -21,6 +21,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: Implementation :: CPython",
"Topic :: Database",
"Topic :: Database :: Front-Ends",
Expand All @@ -30,14 +31,14 @@ packages = [{ include = "upstash_redis" }]

[tool.poetry.dependencies]
python = "^3.8"
aiohttp = "^3.8.4"
requests = "^2.31.0"
httpx = ">=0.23.0, <1"

[tool.poetry.group.dev.dependencies]
pytest = "^7.3.0"
pytest-asyncio = "^0.21.0"
mypy = "^1.4.1"
types-requests = "^2.31.0"
pytest = "^8.3.4"
pytest-asyncio = "^0.24.0"
python-dotenv = "^1.0.1"
mypy = "^1.14.1"
ruff = "^0.9.7"

[build-system]
requires = ["poetry-core"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_arrappend"
value: JSONValueT = {"int": 1, "array": [], "object": {"array": [ 1 ]}}
value: JSONValueT = {"int": 1, "array": [], "object": {"array": [1]}}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand All @@ -18,30 +18,34 @@ def test_arrappend_single_element(redis: Redis):
path = "$.array"

assert redis.json.arrappend(key, path, 1) == [1]
assert redis.json.arrappend(key, path, 'new val') == [2]
assert redis.json.arrappend(key, path, "new val") == [2]
assert redis.json.arrappend(key, path, 1.5) == [3]
assert redis.json.arrappend(key, path, True) == [4]
assert redis.json.arrappend(key, path, [1]) == [5]
assert redis.json.arrappend(key, path, {"key": "value"}) == [6]
assert redis.json.get(key, path) == [[1, 'new val', 1.5, True, [1], {"key": "value"} ]]
assert redis.json.get(key, path) == [
[1, "new val", 1.5, True, [1], {"key": "value"}]
]


def test_arrappend_multiple_elements(redis: Redis):
key = "json_arrappend"
path = "$.array"
new_values: List[JSONValueT] = [1, 'new val', 1.5, True, [1], {"key": "value"}]
new_values: List[JSONValueT] = [1, "new val", 1.5, True, [1], {"key": "value"}]

assert redis.json.arrappend(key, path, *new_values) == [6]
assert redis.json.get(key, path) == [[1, 'new val', 1.5, True, [1], {"key": "value"}]]
assert redis.json.get(key, path) == [
[1, "new val", 1.5, True, [1], {"key": "value"}]
]


def test_arrappend_nonarray_path(redis: Redis):
key = "json_arrappend"
path = "$.int"
new_value = 9

assert redis.json.arrappend(key, path, new_value) == [ None ]
assert redis.json.get(key, path) == [ 1 ]
assert redis.json.arrappend(key, path, new_value) == [None]
assert redis.json.get(key, path) == [1]


def test_arrappend_wildcard(redis: Redis):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_arrindex"
value: JSONValueT = {"array": [1, 'test', ['a'], 1.5, {'test': 1}], "int": 1, "object": {"array": [ 0, 1 ]}}
value: JSONValueT = {
"array": [1, "test", ["a"], 1.5, {"test": 1}],
"int": 1,
"object": {"array": [0, 1]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)


def test_arrindex_existing_element(redis: Redis):
key = "json_arrindex"
path = "$.array"

assert redis.json.arrindex(key, path, 1) == [0]
assert redis.json.arrindex(key, path, 'test') == [1]
assert redis.json.arrindex(key, path, ['a']) == [2]
assert redis.json.arrindex(key, path, "test") == [1]
assert redis.json.arrindex(key, path, ["a"]) == [2]
assert redis.json.arrindex(key, path, 1.5) == [3]
assert redis.json.arrindex(key, path, {'test': 1}) == [4]
assert redis.json.arrindex(key, path, {"test": 1}) == [4]


def test_arrindex_nonexisting_element(redis: Redis):
key = "json_arrindex"
Expand All @@ -28,13 +34,15 @@ def test_arrindex_nonexisting_element(redis: Redis):

assert redis.json.arrindex(key, path, value) == [-1]


def test_arrindex_nonarray_path(redis: Redis):
key = "json_arrindex"
path = "$.int"
value = 4

assert redis.json.arrindex(key, path, value) == [None]


def test_arrindex_wildcard(redis: Redis):
key = "json_arrindex"
path = "$..array"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ def test_arrinsert_single_element(redis: Redis):
key = "json_arrinsert"
path = "$.array"

assert redis.json.arrinsert(key, path, 0,1) == [1]
assert redis.json.arrinsert(key, path, 0, 'new val') == [2]
assert redis.json.arrinsert(key, path, 0, 1.5) == [3]
assert redis.json.arrinsert(key, path, 0, True) == [4]
assert redis.json.arrinsert(key, path, 0, [1]) == [5]
assert redis.json.arrinsert(key, path, 0, {"key": "value"}) == [6]
assert redis.json.get(key, path) == [[ {"key": "value"}, [1],True , 1.5, 'new val', 1 ]]
assert redis.json.arrinsert(key, path, 0, 1) == [1]
assert redis.json.arrinsert(key, path, 0, "new val") == [2]
assert redis.json.arrinsert(key, path, 0, 1.5) == [3]
assert redis.json.arrinsert(key, path, 0, True) == [4]
assert redis.json.arrinsert(key, path, 0, [1]) == [5]
assert redis.json.arrinsert(key, path, 0, {"key": "value"}) == [6]
assert redis.json.get(key, path) == [
[{"key": "value"}, [1], True, 1.5, "new val", 1]
]


def test_arrinsert_multiple_elements(redis: Redis):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,35 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_arrlen"
value: JSONValueT = {"array": [1, 2, 3, 4], "int": 1, "object": {"array": [1, 2, 3]}}
value: JSONValueT = {
"array": [1, 2, 3, 4],
"int": 1,
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)


def test_arrlen_existing_element(redis: Redis):
key = "json_arrlen"
path = "$.array"

length = redis.json.arrlen(key, path)
assert length == [4]


def test_arrlen_nonarray_path(redis: Redis):
key = "json_arrlen"
path = "$.int"

length = redis.json.arrlen(key, path)
assert length == [None]


def test_arrlen_wildcard(redis: Redis):
key = "json_arrlen"
path = "$..array"

length = redis.json.arrlen(key, path)
assert length == [3, 4]
assert length == [3, 4]
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_arrpop"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [5, 6, 7]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [5, 6, 7]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_arrtrim"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [5, 6, 7]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [5, 6, 7]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_clear"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand All @@ -18,7 +22,9 @@ def test_clear_single_element(redis: Redis):

removed_element = redis.json.clear(key, path)
assert removed_element == 1
assert redis.json.get(key) == [{"int": 1, "array": [], "object": {"array": [1, 2, 3]}}]
assert redis.json.get(key) == [
{"int": 1, "array": [], "object": {"array": [1, 2, 3]}}
]


def test_clear_wildcard(redis: Redis):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_delete"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_forget"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_get"
value: JSONValueT = {"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)
Expand All @@ -15,7 +19,9 @@ def setup_json(redis: Redis):
def test_get(redis: Redis):
key = "json_get"

assert redis.json.get(key) == [{"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}]
assert redis.json.get(key) == [
{"int": 1, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}}
]


def test_get_path(redis: Redis):
Expand All @@ -27,7 +33,11 @@ def test_get_path(redis: Redis):
def test_get_multiple_path(redis: Redis):
key = "json_get"
paths = ["$.array", "$.object", "$.int"]
assert redis.json.get(key, *paths) == {"$.array": [[1, 2, 3, 4]], "$.object": [{"array": [1, 2, 3]}], "$.int": [1]}
assert redis.json.get(key, *paths) == {
"$.array": [[1, 2, 3, 4]],
"$.object": [{"array": [1, 2, 3]}],
"$.int": [1],
}


def test_get_nonexisting_key(redis: Redis):
Expand Down
43 changes: 43 additions & 0 deletions tests/commands/json/test_json_merge.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pytest

from upstash_redis import Redis
from upstash_redis.typing import JSONValueT


@pytest.fixture(autouse=True)
def setup_json(redis: Redis):
json_key = "json_merge"
value: JSONValueT = {
"int": 1,
"array": [1, 2, 3, 4],
"object": {"array": [1, 2, 3]},
}
redis.json.set(json_key, "$", value)
yield
redis.delete(json_key)


def test_merge(redis: Redis):
key = "json_merge"

assert redis.json.merge(key, "$", {"str": "test", "int": 2}) is True
assert redis.json.get(key) == [
{"int": 2, "array": [1, 2, 3, 4], "object": {"array": [1, 2, 3]}, "str": "test"}
]


def test_merge_nonexisting_key(redis: Redis):
key = "json_merge_nonexisting"

assert redis.json.merge(key, "$", {"str": "test", "int": 2}) is True
assert redis.json.get(key) == [{"int": 2, "str": "test"}]


def test_merge_wildcard(redis: Redis):
key = "json_merge"
path = "$..array"

assert redis.json.merge(key, path, [2, 2, 3, 4]) is True
assert redis.json.get(key) == [
{"int": 1, "array": [2, 2, 3, 4], "object": {"array": [2, 2, 3, 4]}}
]
Loading