diff --git a/README.md b/README.md index 9980f17..6120b82 100644 --- a/README.md +++ b/README.md @@ -327,7 +327,7 @@ We welcome contributions! Here's how you can help: 2. Install dependencies: ```bash - poetry install --all-extras + `poetry install --all-extras` ``` ### Available Commands diff --git a/poetry.lock b/poetry.lock index 9d2a8f6..07c122a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -351,24 +351,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "coloredlogs" -version = "15.0.1" -description = "Colored terminal output for Python's logging module" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, - {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, -] - -[package.dependencies] -humanfriendly = ">=9.1" - -[package.extras] -cron = ["capturer (>=2.4)"] - [[package]] name = "cryptography" version = "44.0.1" @@ -549,21 +531,6 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] zstd = ["zstandard (>=0.18.0)"] -[[package]] -name = "humanfriendly" -version = "10.0" -description = "Human friendly output for text interfaces using Python" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -groups = ["main"] -files = [ - {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, - {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, -] - -[package.dependencies] -pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} - [[package]] name = "idna" version = "3.10" @@ -1493,22 +1460,6 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" -[[package]] -name = "pyreadline3" -version = "3.5.4" -description = "A python implementation of GNU readline." -optional = false -python-versions = ">=3.8" -groups = ["main"] -markers = "sys_platform == \"win32\"" -files = [ - {file = "pyreadline3-3.5.4-py3-none-any.whl", hash = "sha256:eaf8e6cc3c49bcccf145fc6067ba8643d1df34d604a1ec0eccbf7a18e6d3fae6"}, - {file = "pyreadline3-3.5.4.tar.gz", hash = "sha256:8d57d53039a1c75adba8e50dd3d992b28143480816187ea5efbd5c78e6c885b7"}, -] - -[package.extras] -dev = ["build", "flake8", "mypy", "pytest", "twine"] - [[package]] name = "pytest" version = "7.4.4" @@ -1734,20 +1685,19 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)" [[package]] name = "redisvl" -version = "0.5.1" +version = "0.7.0" description = "Python client library and CLI for using Redis as a vector database" optional = false python-versions = "<3.14,>=3.9" groups = ["main"] files = [ - {file = "redisvl-0.5.1-py3-none-any.whl", hash = "sha256:dc8d71982b84ab4fe1136a62db8ad4af6b6a4117f47f9ecfad7f5cd68c87f34c"}, - {file = "redisvl-0.5.1.tar.gz", hash = "sha256:f3e1e45abe4fb42d7531cc9e4cb127be7f39fb41940e9d63fb3def6455931302"}, + {file = "redisvl-0.7.0-py3-none-any.whl", hash = "sha256:4b3b729da71b0f98d7add55d10ad5f1bc8a97747e704f4d311b510cbf6af3039"}, + {file = "redisvl-0.7.0.tar.gz", hash = "sha256:d5964911ecc0ba72827f22f7f63cfc102d4f03836c71e3cbfdbb0c18d8fcb85d"}, ] [package.dependencies] -coloredlogs = ">=15.0,<16.0" jsonpath-ng = ">=1.5.0,<2.0.0" -ml-dtypes = ">=0.4.0,<0.5.0" +ml-dtypes = ">=0.4.0,<1.0.0" numpy = [ {version = ">=1,<2", markers = "python_version < \"3.12\""}, {version = ">=1.26.0,<3", markers = "python_version >= \"3.12\""}, @@ -1755,8 +1705,7 @@ numpy = [ pydantic = ">=2,<3" python-ulid = ">=3.0.0,<4.0.0" pyyaml = ">=5.4,<7.0" -redis = ">=5.0,<6.0" -tabulate = ">=0.9.0,<0.10.0" +redis = ">=5.0,<7.0" tenacity = ">=8.2.2" [package.extras] @@ -1923,21 +1872,6 @@ files = [ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, ] -[[package]] -name = "tabulate" -version = "0.9.0" -description = "Pretty-print tabular data" -optional = false -python-versions = ">=3.7" -groups = ["main"] -files = [ - {file = "tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f"}, - {file = "tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c"}, -] - -[package.extras] -widechars = ["wcwidth"] - [[package]] name = "tenacity" version = "9.0.0" @@ -2489,4 +2423,4 @@ cffi = ["cffi (>=1.11)"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<3.14" -content-hash = "f26b8d531e0d4652c8a0e902dff6167a41dd5f5615b4e62151f69c7d578b6306" +content-hash = "1b7fc919479c445e255db957685bd9bd02077abd8134f35931b683cbda7f8b41" diff --git a/pyproject.toml b/pyproject.toml index ce1419b..f34b1cb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ packages = [{ include = "langgraph" }] [tool.poetry.dependencies] python = ">=3.9,<3.14" langgraph-checkpoint = "^2.0.24" -redisvl = "^0.5.1" +redisvl = ">=0.5.1,<0.8.0" redis = "^5.2.1" python-ulid = "^3.0.0" diff --git a/tests/test_interruption.py b/tests/test_interruption.py index 2bc36d1..a0a0dbf 100644 --- a/tests/test_interruption.py +++ b/tests/test_interruption.py @@ -24,7 +24,7 @@ class InterruptionError(Exception): pass -class MockRedis: +class MockRedis(Redis): """Mock Redis class that can simulate interruptions during operations.""" def __init__(self, real_redis: Redis, interrupt_on: str = None) -> None: @@ -34,14 +34,36 @@ def __init__(self, real_redis: Redis, interrupt_on: str = None) -> None: real_redis: The real Redis client to delegate to interrupt_on: Operation name to interrupt on (e.g., 'json().set', 'Pipeline.execute') """ + # Copy connection info from real_redis to satisfy Redis base class + super().__init__( + connection_pool=real_redis.connection_pool, + single_connection_client=real_redis.single_connection_client, + ) self.real_redis = real_redis self.interrupt_on = interrupt_on self.operations_count = {} self.interrupt_after_count = {} - def __getattr__(self, name): + def __getattribute__(self, name): """Proxy attribute access to the real Redis client, but track operations.""" - attr = getattr(self.real_redis, name) + # For special attributes we've set in __init__, use the parent implementation + if name in [ + "real_redis", + "interrupt_on", + "operations_count", + "interrupt_after_count", + ]: + return super().__getattribute__(name) + + # For Redis base class attributes + if name in ["connection_pool", "single_connection_client", "_parser", "_lock"]: + return super().__getattribute__(name) + + try: + attr = getattr(self.real_redis, name) + except AttributeError: + # Fall back to parent class + return super().__getattribute__(name) # For methods we want to potentially interrupt if callable(attr) and name == self.interrupt_on: diff --git a/tests/test_shallow_sync.py b/tests/test_shallow_sync.py index 02944cf..ef40076 100644 --- a/tests/test_shallow_sync.py +++ b/tests/test_shallow_sync.py @@ -269,7 +269,10 @@ def test_from_conn_string_errors(redis_url: str) -> None: saver.setup() # Test with empty URL - with pytest.raises(ValueError, match="REDIS_URL env var not set"): + # Handle both old and new RedisVL error message formats + with pytest.raises( + ValueError, match="REDIS_URL (env var|environment variable) not set" + ): with ShallowRedisSaver.from_conn_string("") as saver: saver.setup() diff --git a/tests/test_sync.py b/tests/test_sync.py index 303af29..95b72e5 100644 --- a/tests/test_sync.py +++ b/tests/test_sync.py @@ -451,7 +451,10 @@ def test_from_conn_string_errors() -> None: saver.setup() # Test with empty URL - with pytest.raises(ValueError, match="REDIS_URL env var not set"): + # Handle both old and new RedisVL error message formats + with pytest.raises( + ValueError, match="REDIS_URL (env var|environment variable) not set" + ): with RedisSaver.from_conn_string("") as saver: saver.setup()