Skip to content

Commit

Permalink
add LRANGE and ZRANGE (#7)
Browse files Browse the repository at this point in the history
* start adding lrange

* improve stack code

* add lrange

* add more tests

* add more tests

* add zrange

* finalize 0.4.0 changelog
  • Loading branch information
JosuaKrause authored Nov 17, 2023
1 parent 7362342 commit dc1869d
Show file tree
Hide file tree
Showing 16 changed files with 720 additions and 274 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

All notable changes to this project will be documented in this file.

## [Unreleased]
## [0.4.0] - 2023-11-17

### Breaking

- Scripts now need explicitly named arguments. ([#3])
- Script errors are now `ValueError` instead of `redis.exceptions.ResponseError`. ([#3])
- Add name argument to `redipy.plugin.LuaRedisPatch`. ([#7])

### Added

- Added ZRANGE (partially) and LRANGE. ([#7])
- Inferring backend in Redis constructor. ([#3])
- Allow access to raw runtime and redis connections. ([#3])
- Executing scripts from a pipeline. ([#3])
Expand All @@ -29,6 +31,7 @@ All notable changes to this project will be documented in this file.

### Notable Internal Changes

- Remove usage of `nil` in lua scripts (in favor of `cjson.null`).
- Removed some usage of `nil` in lua scripts (in favor of `cjson.null`). ([#3])

[#3]: https://github.com/JosuaKrause/redipy/pull/3
[#7]: https://github.com/JosuaKrause/redipy/pull/7
37 changes: 17 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,6 @@ class RStack:
"""
return f"{base}:{name}"

def init(self, base: str) -> None:
"""
Initializes the stack.
Args:
base (str): The base key.
"""
self._rt.set(self.key(base, "size"), "0")

def push_frame(self, base: str) -> None:
"""
Pushes a new stack frame.
Expand All @@ -216,7 +207,7 @@ class RStack:
"""
self._rt.incrby(self.key(base, "size"), 1)

def pop_frame(self, base: str) -> dict[str, str] | None:
def pop_frame(self, base: str) -> dict[str, str]:
"""
Pops the current stack frame and returns its values.
Expand All @@ -233,7 +224,7 @@ class RStack:
},
args={})
if res is None:
return None
return {}
return cast(dict, res)

def set_value(self, base: str, field: str, value: str) -> None:
Expand Down Expand Up @@ -300,7 +291,7 @@ class RStack:
rframe = RedisHash(Strs(
ctx.add_key("frame"),
":",
ToIntStr(rsize.get(no_adjust=True))))
ToIntStr(rsize.get(default=0))))
field = ctx.add_arg("field")
value = ctx.add_arg("value")
ctx.add(rframe.hset({
Expand All @@ -315,7 +306,7 @@ class RStack:
rframe = RedisHash(Strs(
ctx.add_key("frame"),
":",
ToIntStr(rsize.get(no_adjust=True))))
ToIntStr(rsize.get(default=0))))
field = ctx.add_arg("field")
ctx.set_return_value(rframe.hget(field))
return self._rt.register_script(ctx)
Expand All @@ -324,10 +315,14 @@ class RStack:
ctx = FnContext()
rsize = RedisVar(ctx.add_key("size"))
rframe = RedisHash(
Strs(ctx.add_key("frame"), ":", ToIntStr(rsize.get())))
Strs(ctx.add_key("frame"), ":", ToIntStr(rsize.get(default=0))))
lcl = ctx.add_local(rframe.hgetall())
ctx.add(rframe.delete())
ctx.add(rsize.incrby(-1))

b_then, b_else = ctx.if_(ToNum(rsize.get(default=0)).gt_(0))
b_then.add(rsize.incrby(-1))
b_else.add(rsize.delete())

ctx.set_return_value(lcl)
return self._rt.register_script(ctx)

Expand All @@ -336,7 +331,7 @@ class RStack:
rsize = RedisVar(ctx.add_key("size"))
base = ctx.add_local(ctx.add_key("frame"))
field = ctx.add_arg("field")
pos = ctx.add_local(ToNum(rsize.get()))
pos = ctx.add_local(ToNum(rsize.get(default=0)))
res = ctx.add_local(None)
cur = ctx.add_local(None)
rframe = RedisHash(cur)
Expand Down Expand Up @@ -445,7 +440,8 @@ For a full implementation follow these steps:

1. Add the signature of the function to `redipy.api.RedisAPI`. Adjust as
necessary from the redis spec to get a pythonic feel. Also, add the signature
to `redipy.api.PipelineAPI` but with `None` as return value.
to `redipy.api.PipelineAPI` but with `None` as return value. Additionally,
add the redirect to the backend in `redipy.main.Redis`.
2. Implement the function in `redipy.redis.conn.RedisConnection` and
`redipy.redis.conn.PipelineConnection`. This should
be straightforward as there are not too many changes expected. Don't forget
Expand All @@ -466,9 +462,10 @@ For a full implementation follow these steps:
a class in `redipy.memory.rfun`.
7. Add the approriate class or method in the right `redipy.symbolic.r...py`
file. If it is a new class / file add an import to `redipy.script`.
8. Add a new test to verify the new function works inside a script for all
backends. You can run `make pytest FILE=test/...py` to execute the test and
`make coverage-report` to verify that the new code is executed.
8. Add a new test in `test/test_api.py` to verify the new function works inside
a script for all backends. You can run `make pytest FILE=test/test_api.py`
to execute the test and `make coverage-report` to verify that the new code
is executed.
9. Make sure `make lint-all` passes, as well as, all tests (`make pytest`)
run without issue.

Expand Down
Loading

0 comments on commit dc1869d

Please sign in to comment.