or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bitmap-operations.mdcore-clients.mdgeneric-operations.mdgeospatial-operations.mdhash-operations.mdindex.mdlist-operations.mdlua-scripting.mdpubsub-operations.mdserver-management.mdserver-operations.mdset-operations.mdsorted-set-operations.mdstack-extensions.mdstream-operations.mdstring-operations.mdtransaction-operations.mdvalkey-support.md

index.mddocs/

0

# FakeRedis

1

2

A comprehensive Python implementation of the Redis API that provides enhanced versions of the redis-py Python bindings for Redis. It enables running tests requiring Redis, Valkey, DragonflyDB, or KeyDB servers without an actual server. FakeRedis supports all Redis functionality including advanced features such as RedisJSON, RedisBloom, GeoCommands, Time Series, and more.

3

4

## Package Information

5

6

- **Package Name**: fakeredis

7

- **Language**: Python

8

- **Installation**: `pip install fakeredis`

9

- **License**: BSD-3-Clause

10

- **Documentation**: https://fakeredis.moransoftware.ca/

11

12

## Core Imports

13

14

```python

15

import fakeredis

16

```

17

18

Common usage patterns:

19

20

```python

21

from fakeredis import FakeRedis, FakeServer

22

```

23

24

For async support:

25

26

```python

27

from fakeredis import FakeAsyncRedis

28

```

29

30

For Redis Stack extensions:

31

32

```python

33

from fakeredis.stack import JSONCommandsMixin

34

```

35

36

## Basic Usage

37

38

```python

39

import fakeredis

40

41

# Create a fake Redis client (drop-in replacement for redis.Redis)

42

redis_client = fakeredis.FakeRedis()

43

44

# Basic key-value operations

45

redis_client.set('key', 'value')

46

value = redis_client.get('key')

47

print(value.decode()) # 'value'

48

49

# Hash operations

50

redis_client.hmset('user:1', {'name': 'John', 'email': 'john@example.com'})

51

user_data = redis_client.hgetall('user:1')

52

53

# List operations

54

redis_client.lpush('tasks', 'task1', 'task2', 'task3')

55

tasks = redis_client.lrange('tasks', 0, -1)

56

57

# Set operations

58

redis_client.sadd('tags', 'python', 'redis', 'testing')

59

tags = redis_client.smembers('tags')

60

61

# Async usage

62

import asyncio

63

async def async_example():

64

async_client = fakeredis.FakeAsyncRedis()

65

await async_client.set('async_key', 'async_value')

66

value = await async_client.get('async_key')

67

return value

68

69

# Run async example

70

# result = asyncio.run(async_example())

71

```

72

73

## Architecture

74

75

FakeRedis follows a modular architecture that ensures Redis compatibility:

76

77

- **FakeServer**: Central server instance managing databases, connections, script cache, and pub/sub state

78

- **FakeRedis/FakeAsyncRedis**: Main client classes inheriting from redis-py with fake connection handling

79

- **Command Mixins**: Modular implementation of Redis commands organized by data type (strings, hashes, lists, etc.)

80

- **Data Models**: Redis-compatible data structures (Hash, ZSet, XStream, TimeSeries, etc.)

81

- **Stack Extensions**: Optional modules providing RedisStack functionality (JSON, Bloom filters, Time Series, etc.)

82

- **Protocol Layer**: RESP protocol implementation with socket emulation for full compatibility

83

84

This architecture allows FakeRedis to maintain exact Redis behavior while providing a lightweight, dependency-minimal solution for testing Redis-dependent applications.

85

86

## Capabilities

87

88

### Core Redis Clients

89

90

Main client classes that provide drop-in replacements for redis-py clients with full Redis command compatibility and server emulation.

91

92

```python { .api }

93

class FakeRedis(redis.Redis):

94

def __init__(

95

self,

96

server: Optional[FakeServer] = None,

97

version: VersionType = (7,),

98

server_type: ServerType = "redis",

99

lua_modules: Optional[Dict[str, Any]] = None,

100

**kwargs

101

): ...

102

103

@classmethod

104

def from_url(cls, url: str, **kwargs) -> Self: ...

105

106

class FakeAsyncRedis(redis.asyncio.Redis):

107

def __init__(

108

self,

109

server: Optional[FakeServer] = None,

110

version: VersionType = (7,),

111

server_type: ServerType = "redis",

112

lua_modules: Optional[Dict[str, Any]] = None,

113

**kwargs

114

): ...

115

116

@classmethod

117

def from_url(cls, url: str, **kwargs) -> Self: ...

118

119

class FakeStrictRedis(redis.StrictRedis):

120

def __init__(self, **kwargs): ...

121

122

@classmethod

123

def from_url(cls, url: str, **kwargs) -> Self: ...

124

```

125

126

[Core Redis Clients](./core-clients.md)

127

128

### Server Management

129

130

Server instances that manage Redis state, databases, and connections with support for different Redis-compatible server types.

131

132

```python { .api }

133

class FakeServer:

134

def __init__(

135

self,

136

version: VersionType = (7,),

137

server_type: ServerType = "redis",

138

config: Optional[Dict[bytes, bytes]] = None

139

): ...

140

141

def get_server(self) -> FakeServer: ...

142

def get_next_client_id(self) -> int: ...

143

144

class TcpFakeServer:

145

def __init__(

146

self,

147

server_address: Tuple[str, int],

148

server_type: ServerType = "redis",

149

server_version: VersionType = (8, 0)

150

): ...

151

```

152

153

[Server Management](./server-management.md)

154

155

### String Operations

156

157

Redis string data type operations including get/set, increment/decrement, and multi-key operations.

158

159

```python { .api }

160

def get(self, name: KeyT) -> Optional[bytes]: ...

161

def set(

162

self,

163

name: KeyT,

164

value: EncodableT,

165

ex: Optional[ExpiryT] = None,

166

px: Optional[ExpiryT] = None,

167

nx: bool = False,

168

xx: bool = False,

169

keepttl: bool = False,

170

get: bool = False,

171

exat: Optional[AbsExpiryT] = None,

172

pxat: Optional[AbsExpiryT] = None

173

) -> Optional[bytes]: ...

174

def mget(self, keys: Sequence[KeyT]) -> List[Optional[bytes]]: ...

175

def mset(self, mapping: Mapping[AnyKeyT, EncodableT]) -> bool: ...

176

def incr(self, name: KeyT, amount: int = 1) -> int: ...

177

def decr(self, name: KeyT, amount: int = 1) -> int: ...

178

```

179

180

[String Operations](./string-operations.md)

181

182

### Bitmap Operations

183

184

Redis bitmap operations for efficient bit-level manipulation of string values with counting, positioning, and bitwise operations.

185

186

```python { .api }

187

def getbit(self, key: KeyT, offset: int) -> int: ...

188

def setbit(self, key: KeyT, offset: int, value: int) -> int: ...

189

def bitpos(self, key: KeyT, bit: int, *args: bytes) -> int: ...

190

def bitcount(self, key: KeyT, *args: bytes) -> int: ...

191

def bitop(self, op_name: bytes, dst: KeyT, *keys: KeyT) -> int: ...

192

def bitfield(self, key: KeyT, *args: bytes) -> List[Optional[int]]: ...

193

```

194

195

[Bitmap Operations](./bitmap-operations.md)

196

197

### Hash Operations

198

199

Redis hash data type operations for field-value mappings within keys.

200

201

```python { .api }

202

def hget(self, name: KeyT, key: str) -> Optional[bytes]: ...

203

def hgetall(self, name: KeyT) -> Dict[bytes, bytes]: ...

204

def hset(

205

self,

206

name: KeyT,

207

key: Optional[str] = None,

208

value: Optional[EncodableT] = None,

209

mapping: Optional[Mapping[AnyKeyT, EncodableT]] = None

210

) -> int: ...

211

def hmget(self, name: KeyT, keys: Sequence[str]) -> List[Optional[bytes]]: ...

212

def hincrby(self, name: KeyT, key: str, amount: int = 1) -> int: ...

213

def hdel(self, name: KeyT, *keys: str) -> int: ...

214

```

215

216

[Hash Operations](./hash-operations.md)

217

218

### List Operations

219

220

Redis list data type operations for ordered collections with push/pop operations from both ends.

221

222

```python { .api }

223

def lpush(self, name: KeyT, *values: EncodableT) -> int: ...

224

def rpush(self, name: KeyT, *values: EncodableT) -> int: ...

225

def lpop(self, name: KeyT, count: Optional[int] = None) -> Union[Optional[bytes], List[bytes]]: ...

226

def rpop(self, name: KeyT, count: Optional[int] = None) -> Union[Optional[bytes], List[bytes]]: ...

227

def lrange(self, name: KeyT, start: int, end: int) -> List[bytes]: ...

228

def llen(self, name: KeyT) -> int: ...

229

def blpop(self, keys: Sequence[KeyT], timeout: int = 0) -> Optional[Tuple[bytes, bytes]]: ...

230

def brpop(self, keys: Sequence[KeyT], timeout: int = 0) -> Optional[Tuple[bytes, bytes]]: ...

231

```

232

233

[List Operations](./list-operations.md)

234

235

### Set Operations

236

237

Redis set data type operations for unordered collections of unique elements with set algebra operations.

238

239

```python { .api }

240

def sadd(self, name: KeyT, *values: EncodableT) -> int: ...

241

def smembers(self, name: KeyT) -> Set[bytes]: ...

242

def sismember(self, name: KeyT, value: EncodableT) -> bool: ...

243

def srem(self, name: KeyT, *values: EncodableT) -> int: ...

244

def scard(self, name: KeyT) -> int: ...

245

def sinter(self, keys: Sequence[KeyT]) -> Set[bytes]: ...

246

def sunion(self, keys: Sequence[KeyT]) -> Set[bytes]: ...

247

def sdiff(self, keys: Sequence[KeyT]) -> Set[bytes]: ...

248

```

249

250

[Set Operations](./set-operations.md)

251

252

### Sorted Set Operations

253

254

Redis sorted set data type operations for ordered collections with numeric scores enabling range queries and ranking.

255

256

```python { .api }

257

def zadd(

258

self,

259

name: KeyT,

260

mapping: Mapping[AnyKeyT, EncodableT],

261

nx: bool = False,

262

xx: bool = False,

263

ch: bool = False,

264

incr: bool = False,

265

gt: bool = False,

266

lt: bool = False

267

) -> Union[int, Optional[float]]: ...

268

def zrange(

269

self,

270

name: KeyT,

271

start: int,

272

end: int,

273

desc: bool = False,

274

withscores: bool = False,

275

score_cast_func: Callable[[bytes], Any] = float,

276

byscore: bool = False,

277

bylex: bool = False,

278

offset: Optional[int] = None,

279

num: Optional[int] = None

280

) -> Union[List[bytes], List[Tuple[bytes, float]]]: ...

281

def zrank(self, name: KeyT, value: EncodableT) -> Optional[int]: ...

282

def zscore(self, name: KeyT, value: EncodableT) -> Optional[float]: ...

283

```

284

285

[Sorted Set Operations](./sorted-set-operations.md)

286

287

### Stream Operations

288

289

Redis 5.0+ streams for append-only log data structures with consumer group support for distributed processing.

290

291

```python { .api }

292

def xadd(

293

self,

294

name: KeyT,

295

fields: Dict[AnyKeyT, EncodableT],

296

id: str = "*",

297

maxlen: Optional[int] = None,

298

approximate: bool = True,

299

nomkstream: bool = False,

300

minid: Optional[str] = None,

301

limit: Optional[int] = None

302

) -> str: ...

303

def xread(

304

self,

305

streams: Dict[KeyT, Union[str, int]],

306

count: Optional[int] = None,

307

block: Optional[int] = None

308

) -> List[Tuple[bytes, List[Tuple[bytes, Dict[bytes, bytes]]]]]: ...

309

def xgroup_create(

310

self,

311

name: KeyT,

312

groupname: str,

313

id: str = "$",

314

mkstream: bool = False,

315

entries_read: Optional[int] = None

316

) -> bool: ...

317

```

318

319

[Stream Operations](./stream-operations.md)

320

321

### Pub/Sub Operations

322

323

Redis publish/subscribe messaging with support for channels, pattern subscriptions, and shard channels.

324

325

```python { .api }

326

def publish(self, channel: KeyT, message: EncodableT) -> int: ...

327

def pubsub_channels(self, pattern: str = "*") -> List[bytes]: ...

328

def pubsub_numsub(self, *args: KeyT) -> List[Tuple[bytes, int]]: ...

329

330

class PubSub:

331

def subscribe(self, *args: KeyT) -> None: ...

332

def psubscribe(self, *args: str) -> None: ...

333

def unsubscribe(self, *args: KeyT) -> None: ...

334

def punsubscribe(self, *args: str) -> None: ...

335

def get_message(self, ignore_subscribe_messages: bool = False, timeout: float = 0.0) -> Optional[Dict[str, Any]]: ...

336

```

337

338

[Pub/Sub Operations](./pubsub-operations.md)

339

340

### Geospatial Operations

341

342

Redis geospatial operations for location-based data with geographic indexing and radius queries.

343

344

```python { .api }

345

def geoadd(

346

self,

347

name: KeyT,

348

values: Sequence[Union[Tuple[float, float, EncodableT], Tuple[EncodableT, float, float]]],

349

nx: bool = False,

350

xx: bool = False,

351

ch: bool = False

352

) -> int: ...

353

def geodist(

354

self,

355

name: KeyT,

356

place1: EncodableT,

357

place2: EncodableT,

358

unit: Optional[str] = None

359

) -> Optional[float]: ...

360

def georadius(

361

self,

362

name: KeyT,

363

longitude: float,

364

latitude: float,

365

radius: float,

366

unit: str = "m",

367

withdist: bool = False,

368

withcoord: bool = False,

369

withhash: bool = False,

370

count: Optional[int] = None,

371

sort: Optional[str] = None,

372

store: Optional[KeyT] = None,

373

store_dist: Optional[KeyT] = None

374

) -> List[Union[bytes, List[Union[bytes, float, Tuple[float, float], int]]]]: ...

375

```

376

377

[Geospatial Operations](./geospatial-operations.md)

378

379

### Generic Key Operations

380

381

Generic Redis operations that work across all data types including expiration, pattern matching, and key management.

382

383

```python { .api }

384

def delete(self, *names: KeyT) -> int: ...

385

def exists(self, *names: KeyT) -> int: ...

386

def expire(self, name: KeyT, time: ExpiryT) -> bool: ...

387

def expireat(self, name: KeyT, when: AbsExpiryT) -> bool: ...

388

def keys(self, pattern: str = "*") -> List[bytes]: ...

389

def rename(self, src: KeyT, dst: KeyT) -> bool: ...

390

def ttl(self, name: KeyT) -> int: ...

391

def type(self, name: KeyT) -> bytes: ...

392

def scan(

393

self,

394

cursor: int = 0,

395

match: Optional[str] = None,

396

count: Optional[int] = None,

397

_type: Optional[str] = None

398

) -> Tuple[int, List[bytes]]: ...

399

```

400

401

[Generic Key Operations](./generic-operations.md)

402

403

### Transaction Operations

404

405

Redis transaction support with MULTI/EXEC commands and optimistic locking via WATCH.

406

407

```python { .api }

408

def multi(self) -> None: ...

409

def execute(self) -> List[Any]: ...

410

def discard(self) -> None: ...

411

def watch(self, *names: KeyT) -> bool: ...

412

def unwatch(self) -> bool: ...

413

414

class Pipeline:

415

def __enter__(self) -> Pipeline: ...

416

def __exit__(self, exc_type, exc_val, exc_tb) -> None: ...

417

def execute(self, raise_on_error: bool = True) -> List[Any]: ...

418

```

419

420

[Transaction Operations](./transaction-operations.md)

421

422

### Lua Scripting

423

424

Redis Lua scripting support with script caching and execution.

425

426

```python { .api }

427

def eval(

428

self,

429

script: str,

430

numkeys: int,

431

*keys_and_args: KeyT

432

) -> Any: ...

433

def evalsha(

434

self,

435

sha: str,

436

numkeys: int,

437

*keys_and_args: KeyT

438

) -> Any: ...

439

def script_load(self, script: str) -> str: ...

440

def script_exists(self, *args: str) -> List[bool]: ...

441

def script_flush(self, sync_type: Optional[str] = None) -> bool: ...

442

```

443

444

[Lua Scripting](./lua-scripting.md)

445

446

### Server Operations

447

448

Redis server management commands including database operations, configuration, and information retrieval.

449

450

```python { .api }

451

def info(self, section: Optional[str] = None) -> Dict[str, Any]: ...

452

def dbsize(self) -> int: ...

453

def flushdb(self, asynchronous: bool = False) -> bool: ...

454

def flushall(self, asynchronous: bool = False) -> bool: ...

455

def config_get(self, pattern: str = "*") -> Dict[bytes, bytes]: ...

456

def config_set(self, name: str, value: EncodableT) -> bool: ...

457

def time(self) -> Tuple[str, str]: ...

458

def client_list(self, _type: Optional[str] = None, client_id: Optional[int] = None) -> str: ...

459

```

460

461

[Server Operations](./server-operations.md)

462

463

### Redis Stack Extensions

464

465

Optional Redis Stack module implementations providing advanced data structures and capabilities.

466

467

```python { .api }

468

# JSON operations (requires jsonpath-ng)

469

def json_get(self, name: KeyT, *args: str) -> Any: ...

470

def json_set(self, name: KeyT, path: str, obj: Any, nx: bool = False, xx: bool = False) -> Optional[bool]: ...

471

472

# Bloom Filter operations (requires pyprobables)

473

def bf_add(self, key: KeyT, item: EncodableT) -> bool: ...

474

def bf_exists(self, key: KeyT, item: EncodableT) -> bool: ...

475

476

# Time Series operations

477

def ts_add(

478

self,

479

key: KeyT,

480

timestamp: Union[int, str],

481

value: float,

482

retention_msecs: Optional[int] = None,

483

uncompressed: Optional[bool] = None,

484

chunk_size: Optional[int] = None,

485

on_duplicate: Optional[str] = None

486

) -> int: ...

487

```

488

489

[Redis Stack Extensions](./stack-extensions.md)

490

491

### Valkey Support

492

493

Optional Valkey client implementations for compatibility with Valkey servers (requires valkey package).

494

495

```python { .api }

496

class FakeValkey(valkey.Valkey):

497

def __init__(self, **kwargs): ...

498

499

@classmethod

500

def from_url(cls, url: str, **kwargs) -> Self: ...

501

502

class FakeAsyncValkey(valkey.asyncio.Valkey):

503

def __init__(self, **kwargs): ...

504

505

@classmethod

506

def from_url(cls, url: str, **kwargs) -> Self: ...

507

```

508

509

[Valkey Support](./valkey-support.md)

510

511

## Types

512

513

```python { .api }

514

# Core type aliases

515

VersionType = Tuple[int, ...]

516

ServerType = Literal["redis", "dragonfly", "valkey"]

517

KeyT = Union[str, bytes]

518

EncodableT = Union[bytes, float, int, str]

519

ExpiryT = Union[int, timedelta]

520

AbsExpiryT = Union[datetime, int]

521

AnyKeyT = Union[str, bytes, memoryview]

522

523

# Server configuration

524

class FakeServer:

525

def __init__(

526

self,

527

version: VersionType = (7,),

528

server_type: ServerType = "redis",

529

config: Optional[Dict[bytes, bytes]] = None

530

): ...

531

532

# Response types

533

class SimpleString:

534

"""Redis simple string response type"""

535

pass

536

537

# Client info model

538

class ClientInfo:

539

id: int

540

addr: str

541

laddr: str

542

fd: int

543

name: str

544

idle: int

545

flags: str

546

db: int

547

sub: int

548

psub: int

549

ssub: int

550

multi: int

551

qbuf: int

552

qbuf_free: int

553

argv_mem: int

554

multi_mem: int

555

rbs: int

556

rbp: int

557

obl: int

558

oll: int

559

omem: int

560

tot_mem: int

561

events: str

562

cmd: str

563

user: str

564

redir: int

565

resp: int

566

567

# Stream models

568

class StreamEntryKey(NamedTuple):

569

millis_time: int

570

sequence_number: int

571

572

# Time series models

573

class TimeSeriesRule:

574

dest_key: str

575

aggregation_type: str

576

bucket_size_msec: int

577

alignment_timestamp: Optional[int] = None

578

579

# Access control

580

class AccessControlList:

581

def authenticate(self, username: str, password: str) -> bool: ...

582

def get_user(self, username: str) -> Optional[Dict[str, Any]]: ...

583

```