Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b334fe7
refactor:code
cunla Mar 30, 2025
44f6771
refactor:code
cunla Mar 30, 2025
95224f2
refactor:code
cunla Mar 30, 2025
f8311c3
Merge branch 'master' into dragonfly-tests
cunla Mar 31, 2025
6d1ba02
doc:updated comment with issue
cunla Apr 16, 2025
1d710f5
ruff
cunla Apr 16, 2025
2938362
Merge branch 'master' into dragonfly-tests
cunla May 3, 2025
518ea9d
Merge branch 'master' into dragonfly-tests
cunla May 12, 2025
c3257c8
merge
cunla May 14, 2025
777d1c0
merge
cunla May 14, 2025
8794b37
merge
cunla May 14, 2025
d348793
Merge branch 'master' into dragonfly-tests
cunla May 16, 2025
a22ab1c
Merge branch 'master' into dragonfly-tests
cunla May 25, 2025
92c85fe
Merge branch 'master' into dragonfly-tests
cunla May 28, 2025
5199bfa
wip
cunla May 28, 2025
22c9966
Merge branch 'master' into dragonfly-tests
cunla Jun 2, 2025
cba80b7
Merge branch 'master' into dragonfly-tests
cunla Jun 30, 2025
7733592
chore:update deps
cunla Jun 30, 2025
eb26fda
refactor tests
cunla Jun 30, 2025
cc58ac8
refactor tests
cunla Jun 30, 2025
c164e1f
Merge branch 'master' into dragonfly-tests
cunla Jun 30, 2025
ab5a333
Merge branch 'master' into dragonfly-tests
cunla Jun 30, 2025
5a2d160
tests
cunla Jul 16, 2025
8390b13
Merge branch 'master' into dragonfly-tests
cunla Aug 10, 2025
06a3003
fix:tests now supported by dragonfly
cunla Aug 10, 2025
860c0dc
fix:tests now supported by dragonfly
cunla Aug 10, 2025
3af20af
fix:tests now supported by dragonfly
cunla Aug 10, 2025
72d0d53
fix:tests now supported by dragonfly
cunla Aug 10, 2025
2f859f2
Merge branch 'master' into dragonfly-tests
cunla Aug 13, 2025
c379c1e
wip
cunla Aug 13, 2025
032b218
wip
cunla Aug 15, 2025
de418c2
wip
cunla Aug 15, 2025
25b64d1
wip
cunla Aug 18, 2025
7f230bb
chore:update deps
cunla Aug 18, 2025
b0dea4c
chore:update deps
cunla Aug 29, 2025
879d2c4
Merge branch 'master' into dragonfly-tests
cunla Aug 31, 2025
c0f6a8d
wip
cunla Aug 31, 2025
80816f1
Merge branch 'master' into dragonfly-tests
cunla Sep 2, 2025
6c3dbc8
Merge branch 'master' into dragonfly-tests
cunla Sep 25, 2025
6229a78
Merge branch 'master' into dragonfly-tests
cunla Oct 2, 2025
b6530c0
Merge branch 'master' into dragonfly-tests
cunla Oct 12, 2025
7769bc1
Merge branch 'master' into dragonfly-tests
cunla Nov 3, 2025
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
14 changes: 7 additions & 7 deletions .github/workflows/test-dragonfly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ name: Test Dragonfly

on:
workflow_dispatch:

pull_request:
branches:
- master

concurrency:
group: dragon-fly-${{ github.workflow }}-${{ github.ref }}
Expand All @@ -19,13 +21,9 @@ jobs:
- "test_json"
- "test_mixins"
- "test_stack"
- "test_connection.py"
- "test_hypothesis"
- "test_asyncredis.py"
- "test_general.py"
- "test_scan.py"
- "test_zadd.py"
- "test_translations.py"
- "test_sortedset_commands.py"
permissions:
pull-requests: write
services:
Expand All @@ -43,6 +41,8 @@ jobs:
- uses: actions/checkout@v5
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@v6
- uses: actions/setup-python@v6
with:
cache-dependency-path: uv.lock
Expand All @@ -51,7 +51,7 @@ jobs:
env:
PYTHON_KEYRING_BACKEND: keyring.backends.null.Keyring
run: |
uv sync --extra json --extra bf --extra lua --extra cf
uv sync --all-extras

- name: Test without coverage
run: |
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ on:
push:
branches:
- master
pull_request:
branches:
- master
# pull_request:
# branches:
# - master

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
Expand Down
6 changes: 5 additions & 1 deletion fakeredis/commands_mixins/bitmap_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,12 @@ def _bitfield_set(
return new_value if value is None else ans

@command(fixed=(Key(bytes),), repeat=(bytes,))
def bitfield(self, key: CommandItem, *args: bytes) -> List[Optional[int]]:
def bitfield(self, key: CommandItem, *args: bytes) -> Optional[List[Optional[int]]]:
overflow = b"WRAP"
results: List[Optional[int]] = []
i = 0
if len(args) == 0 and self._server.server_type == "dragonfly":
raise SimpleError(msgs.WRONG_ARGS_MSG6.format("bitfield"))
while i < len(args):
if casematch(args[i], b"overflow") and i + 1 < len(args):
overflow = args[i + 1].upper()
Expand Down Expand Up @@ -269,4 +271,6 @@ def bitfield(self, key: CommandItem, *args: bytes) -> List[Optional[int]]:
else:
raise SimpleError(msgs.SYNTAX_ERROR_MSG)

if len(results) == 0 and self._server.server_type == "dragonfly":
return None
return results
5 changes: 5 additions & 0 deletions fakeredis/stack/_json_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from fakeredis._commands import Key, command, delete_keys, CommandItem, Int, Float
from fakeredis._helpers import SimpleString
from fakeredis.model import ZSet, ClientInfo
from fakeredis.typing import ServerType

JsonType = Union[str, int, float, bool, None, Dict[str, Any], List[Any]]

Expand Down Expand Up @@ -169,6 +170,7 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(*args, **kwargs)
self._db: helpers.Database
self._client_info: ClientInfo
self.server_type: ServerType

@staticmethod
def _get_single(
Expand Down Expand Up @@ -465,6 +467,9 @@ def check_index(value: JsonType) -> Optional[int]:

@command(name="JSON.STRLEN", fixed=(Key(),), repeat=(bytes,))
def json_strlen(self, key: CommandItem, *args: bytes) -> Union[List[Optional[int]], Optional[int]]:
if key.value is None:
msg = msgs.JSON_KEY_NOT_FOUND if self.server_type != "dragonfly" else msgs.NO_KEY_MSG
raise helpers.SimpleError(msg)
return _json_read_iterate(lambda val: len(val) if type(val) is str else None, key, *args)

@command(name="JSON.ARRLEN", fixed=(Key(),), repeat=(bytes,))
Expand Down
3 changes: 3 additions & 0 deletions test/test_hypothesis/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ class BaseTest:

command_strategy: SearchStrategy
create_command_strategy = st.nothing()
command_strategy_dragonfly = st.nothing()
command_strategy_redis7 = st.nothing()
command_strategy_redis_only = st.nothing()

Expand All @@ -334,6 +335,8 @@ def test(self):
class Machine(CommonMachine):
create_command_strategy = self.create_command_strategy
command_strategy = self.command_strategy
if server_type == "dragonfly":
command_strategy = command_strategy | self.command_strategy_dragonfly
if server_type == "redis":
command_strategy = command_strategy | self.command_strategy_redis_only
if server_type == "redis" and redis_ver >= (7,):
Expand Down
3 changes: 3 additions & 0 deletions test/test_hypothesis/test_hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class TestHash(BaseTest):
st.lists(fields, min_size=2, max_size=2, unique=True),
)
)
command_strategy_dragonfly = commands(
st.just("hexpiretime"), st.just("fields"), st.just(2), st.lists(fields, min_size=2, max_size=2)
) | commands(st.just("hpexpiretime"), st.just("fields"), st.just(2), st.lists(fields, min_size=2, max_size=2))
command_strategy_redis7 = (
commands(st.just("hpersist"), st.just("fields"), st.just(2), st.lists(fields, min_size=2, max_size=2))
| commands(st.just("hexpiretime"), st.just("fields"), st.just(2), st.lists(fields, min_size=2, max_size=2))
Expand Down
13 changes: 10 additions & 3 deletions test/test_hypothesis/test_server.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
from .base import BaseTest, commands, st, common_commands, keys, values
from .base import (
BaseTest,
commands,
values,
st,
keys,
common_commands,
)
from .test_string import string_commands


Expand All @@ -7,11 +14,11 @@ class TestServer(BaseTest):
# Find a better way to test this. commands(st.just('bgsave'))
server_commands = (
commands(st.just("dbsize"))
| commands(st.sampled_from(["flushdb", "flushall"]))
# TODO: result is non-deterministic
# | commands(st.just('lastsave'))
| commands(st.just("save"))
)
command_strategy_redis_only = commands(st.sampled_from(["flushdb", "flushall"]), st.sampled_from([[], "async"]))
command_strategy_dragonfly = commands(st.sampled_from(["flushdb", "flushall"]))
command_strategy_redis7 = commands(st.sampled_from(["flushdb", "flushall"]), st.sampled_from([[], "async"]))
create_command_strategy = commands(st.just("set"), keys, values)
command_strategy = server_commands | string_commands | common_commands
64 changes: 8 additions & 56 deletions test/test_json/test_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,65 +368,25 @@ def test_strappend(r: redis.Redis):
assert "foobar" == r.json().get("json-key", Path.root_path())

# Test multi
r.json().set(
"doc1",
Path.root_path(),
{
"a": "foo",
"nested1": {"a": "hello"},
"nested2": {"a": 31},
},
)
r.json().set("doc1", Path.root_path(), {"a": "foo", "nested1": {"a": "hello"}, "nested2": {"a": 31}})
assert r.json().strappend("doc1", "bar", "$..a") == [6, 8, None]
assert r.json().get("doc1") == {
"a": "foobar",
"nested1": {"a": "hellobar"},
"nested2": {"a": 31},
}
assert r.json().get("doc1") == {"a": "foobar", "nested1": {"a": "hellobar"}, "nested2": {"a": 31}}

# Test single
assert r.json().strappend(
"doc1",
"baz",
"$.nested1.a",
) == [11]
assert r.json().get("doc1") == {
"a": "foobar",
"nested1": {"a": "hellobarbaz"},
"nested2": {"a": 31},
}
assert r.json().strappend("doc1", "baz", "$.nested1.a") == [11]
assert r.json().get("doc1") == {"a": "foobar", "nested1": {"a": "hellobarbaz"}, "nested2": {"a": 31}}

# Test missing key
with pytest.raises(redis.exceptions.ResponseError):
r.json().strappend("non_existing_doc", "$..a", "err")

# Test multi
r.json().set(
"doc2",
Path.root_path(),
{
"a": "foo",
"nested1": {"a": "hello"},
"nested2": {"a": "hi"},
},
)
r.json().set("doc2", Path.root_path(), {"a": "foo", "nested1": {"a": "hello"}, "nested2": {"a": "hi"}})
assert r.json().strappend("doc2", "bar", "$.*.a") == [8, 5]
assert r.json().get("doc2") == {
"a": "foo",
"nested1": {"a": "hellobar"},
"nested2": {"a": "hibar"},
}
assert r.json().get("doc2") == {"a": "foo", "nested1": {"a": "hellobar"}, "nested2": {"a": "hibar"}}

# Test missing path
r.json().set(
"doc1",
Path.root_path(),
{
"a": "foo",
"nested1": {"a": "hello"},
"nested2": {"a": 31},
},
)
r.json().set("doc1", Path.root_path(), {"a": "foo", "nested1": {"a": "hello"}, "nested2": {"a": 31}})
with pytest.raises(redis.exceptions.ResponseError):
r.json().strappend("doc1", "add", "piu")

Expand Down Expand Up @@ -606,15 +566,7 @@ def test_objkeys(r: redis.Redis):

assert r.json().objkeys("fakekey") is None

r.json().set(
"doc1",
"$",
{
"nested1": {"a": {"foo": 10, "bar": 20}},
"a": ["foo"],
"nested2": {"a": {"baz": 50}},
},
)
r.json().set("doc1", "$", {"nested1": {"a": {"foo": 10, "bar": 20}}, "a": ["foo"], "nested2": {"a": {"baz": 50}}})

# Test single
keys = r.json().objkeys("doc1", "$.nested1.a")
Expand Down
Loading
Loading