Skip to content

Commit ccfc0cb

Browse files
authored
Merge branch 'master' into truncate-pipeline-exception
2 parents 0bd8365 + daf6655 commit ccfc0cb

31 files changed

+223
-3227
lines changed

.github/wordlist.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ ConnectionPool
1212
CoreCommands
1313
EVAL
1414
EVALSHA
15-
GraphCommands
1615
Grokzen's
1716
INCR
1817
IOError
@@ -39,7 +38,6 @@ RedisCluster
3938
RedisClusterCommands
4039
RedisClusterException
4140
RedisClusters
42-
RedisGraph
4341
RedisInstrumentor
4442
RedisJSON
4543
RedisTimeSeries

.github/workflows/install_and_test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ cd ${TESTDIR}
4040
# install, run tests
4141
pip install ${PKG}
4242
# Redis tests
43-
pytest -m 'not onlycluster and not graph'
43+
pytest -m 'not onlycluster'
4444
# RedisCluster tests
4545
CLUSTER_URL="redis://localhost:16379/0"
4646
CLUSTER_SSL_URL="rediss://localhost:27379/0"
47-
pytest -m 'not onlynoncluster and not redismod and not ssl and not graph' \
47+
pytest -m 'not onlynoncluster and not redismod and not ssl' \
4848
--redis-url="${CLUSTER_URL}" --redis-ssl-url="${CLUSTER_SSL_URL}"

.github/workflows/stale-issues.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@ jobs:
2121
days-before-close: 30
2222
stale-issue-label: "Stale"
2323
stale-pr-label: "Stale"
24-
operations-per-run: 10
24+
operations-per-run: 20
2525
remove-stale-when-updated: true

CHANGES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
* Removing support for RedisGraph module. RedisGraph support is deprecated since Redis Stack 7.2 (https://redis.com/blog/redisgraph-eol/)
12
* Fix lock.extend() typedef to accept float TTL extension
23
* Update URL in the readme linking to Redis University
34
* Move doctests (doc code examples) to main branch

docker-compose.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,3 @@ services:
105105
- standalone
106106
- all-stack
107107
- all
108-
109-
redis-stack-graph:
110-
image: redis/redis-stack-server:6.2.6-v15
111-
container_name: redis-stack-graph
112-
ports:
113-
- 6480:6379
114-
profiles:
115-
- graph

docs/redismodules.rst

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -51,39 +51,6 @@ These are the commands for interacting with the `RedisBloom module <https://redi
5151

5252
------
5353

54-
RedisGraph Commands
55-
*******************
56-
57-
These are the commands for interacting with the `RedisGraph module <https://redisgraph.io>`_. Below is a brief example, as well as documentation on the commands themselves.
58-
59-
**Create a graph, adding two nodes**
60-
61-
.. code-block:: python
62-
63-
import redis
64-
from redis.graph.node import Node
65-
66-
john = Node(label="person", properties={"name": "John Doe", "age": 33}
67-
jane = Node(label="person", properties={"name": "Jane Doe", "age": 34}
68-
69-
r = redis.Redis()
70-
graph = r.graph()
71-
graph.add_node(john)
72-
graph.add_node(jane)
73-
graph.add_node(pat)
74-
graph.commit()
75-
76-
.. automodule:: redis.commands.graph.node
77-
:members: Node
78-
79-
.. automodule:: redis.commands.graph.edge
80-
:members: Edge
81-
82-
.. automodule:: redis.commands.graph.commands
83-
:members: GraphCommands
84-
85-
------
86-
8754
RedisJSON Commands
8855
******************
8956

doctests/geo_index.py

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# EXAMPLE: geoindex
2+
import redis
3+
from redis.commands.json.path import Path
4+
from redis.commands.search.field import TextField, GeoField, GeoShapeField
5+
from redis.commands.search.indexDefinition import IndexDefinition, IndexType
6+
from redis.commands.search.query import Query
7+
8+
r = redis.Redis()
9+
# REMOVE_START
10+
try:
11+
r.ft("productidx").dropindex(True)
12+
except redis.exceptions.ResponseError:
13+
pass
14+
15+
try:
16+
r.ft("geomidx").dropindex(True)
17+
except redis.exceptions.ResponseError:
18+
pass
19+
20+
r.delete("product:46885", "product:46886", "shape:1", "shape:2", "shape:3", "shape:4")
21+
# REMOVE_END
22+
23+
# STEP_START create_geo_idx
24+
geo_schema = (
25+
GeoField("$.location", as_name="location")
26+
)
27+
28+
geo_index_create_result = r.ft("productidx").create_index(
29+
geo_schema,
30+
definition=IndexDefinition(
31+
prefix=["product:"], index_type=IndexType.JSON
32+
)
33+
)
34+
print(geo_index_create_result) # >>> True
35+
# STEP_END
36+
# REMOVE_START
37+
assert geo_index_create_result
38+
# REMOVE_END
39+
40+
# STEP_START add_geo_json
41+
prd46885 = {
42+
"description": "Navy Blue Slippers",
43+
"price": 45.99,
44+
"city": "Denver",
45+
"location": "-104.991531, 39.742043"
46+
}
47+
48+
json_add_result_1 = r.json().set("product:46885", Path.root_path(), prd46885)
49+
print(json_add_result_1) # >>> True
50+
51+
prd46886 = {
52+
"description": "Bright Green Socks",
53+
"price": 25.50,
54+
"city": "Fort Collins",
55+
"location": "-105.0618814,40.5150098"
56+
}
57+
58+
json_add_result_2 = r.json().set("product:46886", Path.root_path(), prd46886)
59+
print(json_add_result_2) # >>> True
60+
# STEP_END
61+
# REMOVE_START
62+
assert json_add_result_1
63+
assert json_add_result_2
64+
# REMOVE_END
65+
66+
# STEP_START geo_query
67+
geo_result = r.ft("productidx").search(
68+
"@location:[-104.800644 38.846127 100 mi]"
69+
)
70+
print(geo_result)
71+
# >>> Result{1 total, docs: [Document {'id': 'product:46885'...
72+
# STEP_END
73+
# REMOVE_START
74+
assert len(geo_result.docs) == 1
75+
assert geo_result.docs[0]["id"] == "product:46885"
76+
# REMOVE_END
77+
78+
# STEP_START create_gshape_idx
79+
geom_schema = (
80+
TextField("$.name", as_name="name"),
81+
GeoShapeField(
82+
"$.geom", as_name="geom", coord_system=GeoShapeField.FLAT
83+
)
84+
)
85+
86+
geom_index_create_result = r.ft("geomidx").create_index(
87+
geom_schema,
88+
definition=IndexDefinition(
89+
prefix=["shape:"], index_type=IndexType.JSON
90+
)
91+
)
92+
print(geom_index_create_result) # True
93+
# STEP_END
94+
# REMOVE_START
95+
assert geom_index_create_result
96+
# REMOVE_END
97+
98+
# STEP_START add_gshape_json
99+
shape1 = {
100+
"name": "Green Square",
101+
"geom": "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"
102+
}
103+
104+
gm_json_res_1 = r.json().set("shape:1", Path.root_path(), shape1)
105+
print(gm_json_res_1) # >>> True
106+
107+
shape2 = {
108+
"name": "Red Rectangle",
109+
"geom": "POLYGON ((2 2.5, 2 3.5, 3.5 3.5, 3.5 2.5, 2 2.5))"
110+
}
111+
112+
gm_json_res_2 = r.json().set("shape:2", Path.root_path(), shape2)
113+
print(gm_json_res_2) # >>> True
114+
115+
shape3 = {
116+
"name": "Blue Triangle",
117+
"geom": "POLYGON ((3.5 1, 3.75 2, 4 1, 3.5 1))"
118+
}
119+
120+
gm_json_res_3 = r.json().set("shape:3", Path.root_path(), shape3)
121+
print(gm_json_res_3) # >>> True
122+
123+
shape4 = {
124+
"name": "Purple Point",
125+
"geom": "POINT (2 2)"
126+
}
127+
128+
gm_json_res_4 = r.json().set("shape:4", Path.root_path(), shape4)
129+
print(gm_json_res_4) # >>> True
130+
# STEP_END
131+
# REMOVE_START
132+
assert gm_json_res_1
133+
assert gm_json_res_2
134+
assert gm_json_res_3
135+
assert gm_json_res_4
136+
# REMOVE_END
137+
138+
# STEP_START gshape_query
139+
geom_result = r.ft("geomidx").search(
140+
Query(
141+
"(-@name:(Green Square) @geom:[WITHIN $qshape])"
142+
).dialect(4).paging(0, 1),
143+
query_params={
144+
"qshape": "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"
145+
}
146+
)
147+
print(geom_result)
148+
# >>> Result{1 total, docs: [Document {'id': 'shape:4'...
149+
# STEP_END
150+
# REMOVE_START
151+
assert len(geom_result.docs) == 1
152+
assert geom_result.docs[0]["id"] == "shape:4"
153+
# REMOVE_END

pyproject.toml

Lines changed: 16 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,8 @@ description = "Python client for Redis database and key-value store"
99
readme = "README.md"
1010
license = "MIT"
1111
requires-python = ">=3.8"
12-
authors = [
13-
{ name = "Redis Inc.", email = "[email protected]" },
14-
]
15-
keywords = [
16-
"Redis",
17-
"database",
18-
"key-value-store",
19-
]
12+
authors = [{ name = "Redis Inc.", email = "[email protected]" }]
13+
keywords = ["Redis", "database", "key-value-store"]
2014
classifiers = [
2115
"Development Status :: 5 - Production/Stable",
2216
"Environment :: Console",
@@ -35,9 +29,7 @@ classifiers = [
3529
"Programming Language :: Python :: Implementation :: CPython",
3630
"Programming Language :: Python :: Implementation :: PyPy",
3731
]
38-
dependencies = [
39-
'async-timeout>=4.0.3; python_full_version<"3.11.3"',
40-
]
32+
dependencies = ['async-timeout>=4.0.3; python_full_version<"3.11.3"']
4133

4234
[project.optional-dependencies]
4335
hiredis = [
@@ -63,22 +55,15 @@ Homepage = "https://github.com/redis/redis-py"
6355
path = "redis/__init__.py"
6456

6557
[tool.hatch.build.targets.sdist]
66-
include = [
67-
"/redis",
68-
"/tests",
69-
"dev_requirements.txt",
70-
]
58+
include = ["/redis", "/tests", "dev_requirements.txt"]
7159

7260
[tool.hatch.build.targets.wheel]
73-
include = [
74-
"/redis",
75-
]
61+
include = ["/redis"]
7662

7763
[tool.pytest.ini_options]
7864
addopts = "-s"
7965
markers = [
8066
"redismod: run only the redis module tests",
81-
"graph: run only the redisgraph tests",
8267
"pipeline: pipeline tests",
8368
"onlycluster: marks tests to be run only with cluster mode redis",
8469
"onlynoncluster: marks tests to be run only with standalone redis",
@@ -93,7 +78,6 @@ asyncio_mode = "auto"
9378
timeout = 30
9479
filterwarnings = [
9580
"always",
96-
"ignore:RedisGraph support is deprecated as of Redis Stack 7.2:DeprecationWarning",
9781
# Ignore a coverage warning when COVERAGE_CORE=sysmon for Pythons < 3.12.
9882
"ignore:sys.monitoring isn't available:coverage.exceptions.CoverageWarning",
9983
]
@@ -118,32 +102,23 @@ exclude = [
118102

119103
[tool.ruff.lint]
120104
ignore = [
121-
"E501", # line too long (taken care of with ruff format)
122-
"E741", # ambiguous variable name
123-
"N818", # Errors should have Error suffix
105+
"E501", # line too long (taken care of with ruff format)
106+
"E741", # ambiguous variable name
107+
"N818", # Errors should have Error suffix
124108
]
125109

126-
select = [
127-
"E",
128-
"F",
129-
"FLY",
130-
"I",
131-
"N",
132-
"W",
133-
]
110+
select = ["E", "F", "FLY", "I", "N", "W"]
134111

135112
[tool.ruff.lint.per-file-ignores]
136113
"redis/commands/bf/*" = [
137114
# the `bf` module uses star imports, so this is required there.
138-
"F405", # name may be undefined, or defined from star imports
139-
]
140-
"redis/commands/{bf,timeseries,json,search}/*" = [
141-
"N",
115+
"F405", # name may be undefined, or defined from star imports
142116
]
117+
"redis/commands/{bf,timeseries,json,search}/*" = ["N"]
143118
"tests/*" = [
144-
"I", # TODO: could be enabled, plenty of changes
145-
"N801", # class name should use CapWords convention
146-
"N803", # argument name should be lowercase
147-
"N802", # function name should be lowercase
148-
"N806", # variable name should be lowercase
119+
"I", # TODO: could be enabled, plenty of changes
120+
"N801", # class name should use CapWords convention
121+
"N803", # argument name should be lowercase
122+
"N802", # function name should be lowercase
123+
"N806", # variable name should be lowercase
149124
]

redis/asyncio/cluster.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,29 +1518,28 @@ async def execute(
15181518
return []
15191519

15201520
try:
1521-
for _ in range(self._client.cluster_error_retry_attempts):
1522-
if self._client._initialize:
1523-
await self._client.initialize()
1524-
1521+
retry_attempts = self._client.cluster_error_retry_attempts
1522+
while True:
15251523
try:
1524+
if self._client._initialize:
1525+
await self._client.initialize()
15261526
return await self._execute(
15271527
self._client,
15281528
self._command_stack,
15291529
raise_on_error=raise_on_error,
15301530
allow_redirections=allow_redirections,
15311531
)
1532-
except BaseException as e:
1533-
if type(e) in self.__class__.ERRORS_ALLOW_RETRY:
1534-
# Try again with the new cluster setup.
1535-
exception = e
1532+
1533+
except self.__class__.ERRORS_ALLOW_RETRY as e:
1534+
if retry_attempts > 0:
1535+
# Try again with the new cluster setup. All other errors
1536+
# should be raised.
1537+
retry_attempts -= 1
15361538
await self._client.aclose()
15371539
await asyncio.sleep(0.25)
15381540
else:
15391541
# All other errors should be raised.
1540-
raise
1541-
1542-
# If it fails the configured number of times then raise an exception
1543-
raise exception
1542+
raise e
15441543
finally:
15451544
self._command_stack = []
15461545

0 commit comments

Comments
 (0)