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

Unpin redis #130

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
28 changes: 28 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Test

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

env:
PIP_BREAK_SYSTEM_PACKAGES: "1"

jobs:
test_redis:

strategy:
matrix:
redis-package-version: ["2.*", "3.*", "4.*", "5.*"]
os: ["ubuntu-24.04", "ubuntu-22.04", "ubuntu-20.04"]

runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- name: Start Redis
uses: superchargejs/redis-github-action@1.1.0
- name: Install redis package
run: python3 -m pip install redis==${{ matrix.redis-package-version }}
- name: Run test
run: python3 -m unittest discover python/tests/
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@
*.app

bin/minqlx.zip
*.pyc
48 changes: 47 additions & 1 deletion python/minqlx/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with minqlx. If not, see <http://www.gnu.org/licenses/>.

import minqlx
try:
import minqlx
except ImportError:
pass

import redis

# ====================================================================
Expand Down Expand Up @@ -313,3 +317,45 @@ def close(self):
if Redis._pool:
Redis._pool.disconnect()
Redis._pool = None

if redis.VERSION > (3,):
def zincrby(self, name, value, amount=1):
return self.r.zincrby(name, amount, value)

def zadd(self, name, *args, **kwargs):
if len(args) == 1 and isinstance(args[0], dict):
# redis >= 3.* arguments given
return self.r.zadd(name, *args, **kwargs)

if len(args) > 0 and len(args) % 2 != 0:
raise redis.RedisError("ZADD requires an equal number of values and scores")

mapping = {}
for i in range(0, len(args), 2):
mapping[args[i + 1]] = args[i]

return self.r.zadd(name, mapping, **kwargs)

def msetnx(self, *args, **kwargs):
mapping = {}
if args:
if len(args) != 1 or not isinstance(args[0], dict):
raise redis.RedisError("MSETNX requires **kwargs or a single dict arg")
mapping.update(args[0])

if kwargs:
mapping.update(kwargs)

return self.r.msetnx(mapping)

def mset(self, *args, **kwargs):
mapping = {}
if args:
if len(args) != 1 or not isinstance(args[0], dict):
raise redis.RedisError("MSET requires **kwargs or a single dict arg")
mapping.update(args[0])

if kwargs:
mapping.update(kwargs)

return self.r.mset(mapping)
1 change: 1 addition & 0 deletions python/tests/database.py
154 changes: 154 additions & 0 deletions python/tests/test_database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import random
import string
from time import sleep
from unittest import TestCase

import redis

import database


def random_string():
return "".join([random.choice(string.ascii_letters) for x in range(10)])


class RedisRegressionTestCase(TestCase):
def setUp(self):
self.c = database.Redis(None)
self.c.connect("127.0.0.1:6379")

def test_zadd_01(self):
c = self.c
key = "zadd_01_key_" + random_string()

c.zadd(key, 5, "player1", 6, "player2")
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["player1"], 5)
self.assertEqual(res["player2"], 6)

c.zadd(key, 2, "player1")
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["player1"], 2)
self.assertEqual(res["player2"], 6)

c.zadd(key, 4, "player2")
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["player1"], 2)
self.assertEqual(res["player2"], 4)

def test_zadd_02(self):
c = self.c
key = "zadd_02_key_" + random_string()

# redis-py 3.* introduced xx, nx, ch and incr kwarg params
# this codes deliberately does not work in redis-py 2.*
if redis.VERSION < (3,):
self.skipTest("Old version of redis package: %s" % (redis.VERSION,))
c.zadd(key, 5, "player1", 6, "player2")
c.zadd(key, {"player1": 3}, xx=True)
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["player1"], 3)

c.zadd(key, 3, "player_does_not_exist", xx=True)
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertNotIn("player_does_not_exist", res)

def test_zincrby_01(self):
key = "zincrby_01_key_" + random_string()
c = self.c

c.zincrby(key, "FIELD1")
c.zincrby(key, "FIELD2", 2)
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["FIELD1"], 1)
self.assertEqual(res["FIELD2"], 2)

c.zincrby(key, "FIELD1")
c.zincrby(key, "FIELD2", 3)
res = dict(c.zrange(key, 0, -1, withscores=True))
self.assertEqual(res["FIELD1"], 2)
self.assertEqual(res["FIELD2"], 5)

def test_lrem_01(self):
key = "lrem_01_key_" + random_string()
c = self.c

c.rpush(
key,
"Cat",
"Dog",
"Horse",
"Cat",
"Dog",
"Cat",
"Monkey",
"Dog",
"Cat",
"Dog",
"Buffalo",
)
c.lrem(key, 2, "Cat")
result = c.lrange(key, 0, -1)
self.assertEqual(
result,
["Dog", "Horse", "Dog", "Cat", "Monkey", "Dog", "Cat", "Dog", "Buffalo"],
)

def test_setex_01(self):
key = "setex_01_key_" + random_string()
c = self.c
test_value = "test value"
timeout = 1

c.setex(key, timeout, test_value)
self.assertEqual(c.get(key), test_value, "Too small timeout value?")
sleep(timeout + 0.5)
self.assertEqual(c.get(key), None)

def test_mset_01(self):
c = self.c
c.mset(field1="example1", field2="example2")
self.assertEqual(["example1", "example2"], c.mget("field1", "field2"))

def test_mset_02(self):
c = self.c
c.mset({"field3": "example1", "field4": "example2"})
self.assertEqual(["example1", "example2"], c.mget("field3", "field4"))

def test_msetnx_01_kwargs(self):
c = self.c
prefix = "msetnx_01_key_" + random_string()
key1 = prefix + "_field1"
key2 = prefix + "_field2"
d = {
key1: "example1",
key2: "example2",
}
c.msetnx(**d)
self.assertEqual(["example1", "example2"], c.mget(key1, key2))

d = {
key1: "value should not be used",
key2: "same here",
}
c.msetnx(**d)
self.assertEqual(["example1", "example2"], c.mget(key1, key2))

def test_msetnx_02_dict(self):
c = self.c
prefix = "msetnx_02_key_" + random_string()
key1 = prefix + "_field1"
key2 = prefix + "_field2"
d = {
key1: "example1",
key2: "example2",
}
c.msetnx(d)
self.assertEqual(["example1", "example2"], c.mget(key1, key2))

d = {
key1: "value should not be used",
key2: "same here",
}
c.msetnx(d)
self.assertEqual(["example1", "example2"], c.mget(key1, key2))
Loading