or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-operations.mdcontainer-methods.mdcontext-operations.mdconversions.mdcore-containers.mddevelopment-tools.mdfunctional-utilities.mdindex.mditeration-utilities.mdpointfree.mdtrampolines.mdunsafe-operations.md

development-tools.mddocs/

0

# Development Tools

1

2

Integration tools for testing frameworks (pytest, hypothesis), static analysis (mypy), and development workflows with functional containers. These tools enhance the development experience when working with Returns.

3

4

## Capabilities

5

6

### Pytest Integration

7

8

Testing utilities and assertions specifically designed for functional containers.

9

10

```python { .api }

11

# Pytest plugin automatically loaded

12

from returns.contrib.pytest import ReturnsAsserts

13

14

class ReturnsAsserts:

15

"""Custom assertions for Returns containers"""

16

17

def assert_success(self, container: Result[T, E], expected: T) -> None:

18

"""Assert Result is Success with expected value"""

19

20

def assert_failure(self, container: Result[T, E]) -> None:

21

"""Assert Result is Failure"""

22

23

def assert_failure_with(self, container: Result[T, E], expected_error: E) -> None:

24

"""Assert Result is Failure with specific error"""

25

26

def assert_some(self, container: Maybe[T], expected: T) -> None:

27

"""Assert Maybe is Some with expected value"""

28

29

def assert_nothing(self, container: Maybe[T]) -> None:

30

"""Assert Maybe is Nothing"""

31

32

# Additional test utilities

33

def raises_failure(exception_type: type[Exception]) -> Callable:

34

"""Context manager for testing exception-based failures"""

35

36

def returns_success(expected_value: T) -> Callable:

37

"""Decorator to test function returns Success with value"""

38

39

def returns_failure() -> Callable:

40

"""Decorator to test function returns Failure"""

41

```

42

43

Usage examples:

44

45

```python

46

import pytest

47

from returns.contrib.pytest import ReturnsAsserts

48

from returns.result import Success, Failure, safe

49

from returns.maybe import Some, Nothing

50

51

class TestMyFunctions(ReturnsAsserts):

52

"""Test class with Returns assertions"""

53

54

def test_successful_operation(self):

55

result = Success(42)

56

self.assert_success(result, 42)

57

58

def test_failed_operation(self):

59

result = Failure("error occurred")

60

self.assert_failure(result)

61

self.assert_failure_with(result, "error occurred")

62

63

def test_maybe_operations(self):

64

some_value = Some(42)

65

nothing_value = Nothing

66

67

self.assert_some(some_value, 42)

68

self.assert_nothing(nothing_value)

69

70

# Testing with decorators and context managers

71

@safe

72

def divide(a: int, b: int) -> float:

73

return a / b

74

75

def test_safe_division():

76

"""Test safe division function"""

77

# Test successful case

78

result = divide(10, 2)

79

assert isinstance(result, Success)

80

assert result.unwrap() == 5.0

81

82

# Test failure case

83

result = divide(10, 0)

84

assert isinstance(result, Failure)

85

assert isinstance(result.failure(), ZeroDivisionError)

86

87

# Using pytest fixtures

88

@pytest.fixture

89

def sample_data():

90

return [Success(1), Failure("error"), Success(3)]

91

92

def test_with_fixture(sample_data):

93

successes = [r for r in sample_data if isinstance(r, Success)]

94

assert len(successes) == 2

95

```

96

97

### Hypothesis Integration

98

99

Property-based testing strategies for generating test data for functional containers.

100

101

```python { .api }

102

from returns.contrib.hypothesis import get_strategies

103

104

# Strategy generators

105

def get_strategies(container_type: type) -> dict[str, SearchStrategy]:

106

"""Get Hypothesis strategies for container types"""

107

108

# Pre-defined strategies

109

success_strategy = strategies.success(strategies.integers())

110

failure_strategy = strategies.failure(strategies.text())

111

result_strategy = strategies.result(strategies.integers(), strategies.text())

112

113

some_strategy = strategies.some(strategies.integers())

114

nothing_strategy = strategies.nothing()

115

maybe_strategy = strategies.maybe(strategies.integers())

116

117

io_strategy = strategies.io(strategies.integers())

118

future_strategy = strategies.future(strategies.integers())

119

```

120

121

Usage examples:

122

123

```python

124

import pytest

125

from hypothesis import given, strategies as st

126

from returns.contrib.hypothesis import get_strategies

127

from returns.result import Result, Success, Failure

128

from returns.maybe import Maybe, Some, Nothing

129

130

# Get strategies for specific types

131

result_strategies = get_strategies(Result)

132

maybe_strategies = get_strategies(Maybe)

133

134

@given(result_strategies['result'](st.integers(), st.text()))

135

def test_result_properties(result):

136

"""Property-based test for Result containers"""

137

# Test that mapping preserves container type

138

mapped = result.map(lambda x: x * 2)

139

140

if isinstance(result, Success):

141

assert isinstance(mapped, Success)

142

assert mapped.unwrap() == result.unwrap() * 2

143

else:

144

assert isinstance(mapped, Failure)

145

assert mapped.failure() == result.failure()

146

147

@given(maybe_strategies['maybe'](st.integers()))

148

def test_maybe_properties(maybe):

149

"""Property-based test for Maybe containers"""

150

# Test that binding with identity preserves value

151

identity_bound = maybe.bind(lambda x: Some(x))

152

153

if isinstance(maybe, Some):

154

assert isinstance(identity_bound, Some)

155

assert identity_bound.unwrap() == maybe.unwrap()

156

else:

157

assert isinstance(identity_bound, Nothing)

158

159

# Custom property tests

160

@given(st.lists(st.integers(), min_size=1))

161

def test_collection_processing(numbers):

162

"""Test collection processing properties"""

163

from returns.iterables import sequence

164

from returns.result import safe

165

166

@safe

167

def process_number(n: int) -> int:

168

return n * 2

169

170

results = [process_number(n) for n in numbers]

171

sequenced = sequence(results)

172

173

# Property: if all operations succeed, sequence succeeds

174

assert isinstance(sequenced, Success)

175

assert sequenced.unwrap() == [n * 2 for n in numbers]

176

```

177

178

### MyPy Integration

179

180

Static analysis plugin and type checking enhancements for Returns containers.

181

182

```python { .api }

183

# MyPy plugin configuration (in mypy.ini or setup.cfg)

184

"""

185

[mypy]

186

plugins = returns.contrib.mypy.returns_plugin

187

188

[tool:mypy-returns.*]

189

ignore_errors = True

190

"""

191

192

# Type transformation utilities

193

from returns.contrib.mypy import plugin_helpers

194

195

def transform_container_type(container_type: type) -> type:

196

"""Transform container types for better inference"""

197

198

def infer_generic_args(container: Container) -> tuple[type, ...]:

199

"""Infer generic type arguments from container instance"""

200

201

# Enhanced type stubs

202

def bind(self: Container[T], func: Callable[[T], Container[U]]) -> Container[U]: ...

203

def map(self: Container[T], func: Callable[[T], U]) -> Container[U]: ...

204

```

205

206

Configuration example:

207

208

```ini

209

# mypy.ini

210

[mypy]

211

plugins = returns.contrib.mypy.returns_plugin

212

strict_optional = True

213

warn_redundant_casts = True

214

warn_unused_ignores = True

215

disallow_any_generics = True

216

217

# Enable Returns-specific type checking

218

[mypy-returns.*]

219

check_untyped_defs = True

220

disallow_incomplete_defs = True

221

```

222

223

Usage examples:

224

225

```python

226

# Type-safe container usage with mypy checking

227

from returns.result import Result, Success, Failure

228

from returns.maybe import Maybe, Some, Nothing

229

230

def process_data(data: str) -> Result[int, ValueError]:

231

"""MyPy will enforce return type matches Success/Failure types"""

232

try:

233

value = int(data)

234

if value < 0:

235

return Failure(ValueError("Negative values not allowed"))

236

return Success(value)

237

except ValueError as e:

238

return Failure(e)

239

240

# MyPy will catch type mismatches

241

def chain_operations(x: int) -> Result[str, ValueError]:

242

return (

243

process_data(str(x))

244

.bind(lambda n: Success(n * 2)) # Result[int, ValueError]

245

.map(str) # Result[str, ValueError]

246

)

247

248

# Generic type inference

249

def generic_processor[T, E](

250

container: Result[T, E],

251

transform: Callable[[T], str]

252

) -> Result[str, E]:

253

"""MyPy infers correct generic types"""

254

return container.map(transform)

255

```

256

257

### Testing Utilities

258

259

Additional utilities for testing functional code patterns.

260

261

```python { .api }

262

def assert_container_equals(actual: Container[T], expected: Container[T]) -> None:

263

"""Deep equality assertion for containers"""

264

265

def mock_container(container_type: type, value: T) -> Container[T]:

266

"""Create mock container for testing"""

267

268

def container_test_case(container: Container[T]) -> TestCase:

269

"""Generate test cases for container operations"""

270

271

class ContainerTestMixin:

272

"""Mixin class providing container testing utilities"""

273

274

def run_container_laws(self, container: Container[T]) -> None:

275

"""Verify container follows mathematical laws"""

276

277

def test_functor_laws(self, container: Functor[T]) -> None:

278

"""Test functor laws (identity, composition)"""

279

280

def test_monad_laws(self, container: Monad[T]) -> None:

281

"""Test monad laws (left identity, right identity, associativity)"""

282

```

283

284

Usage examples:

285

286

```python

287

import unittest

288

from returns.contrib.pytest import ContainerTestMixin

289

from returns.result import Success, Failure

290

from returns.maybe import Some, Nothing

291

292

class TestContainerLaws(unittest.TestCase, ContainerTestMixin):

293

"""Test that containers follow mathematical laws"""

294

295

def test_result_monad_laws(self):

296

"""Test Result follows monad laws"""

297

success = Success(42)

298

failure = Failure("error")

299

300

self.test_monad_laws(success)

301

self.test_monad_laws(failure)

302

303

def test_maybe_functor_laws(self):

304

"""Test Maybe follows functor laws"""

305

some = Some(42)

306

nothing = Nothing

307

308

self.test_functor_laws(some)

309

self.test_functor_laws(nothing)

310

311

# Mock containers for testing

312

def test_with_mock_containers():

313

"""Test using mock containers"""

314

from unittest.mock import Mock

315

316

# Mock a Result container

317

mock_result = Mock(spec=Success)

318

mock_result.bind.return_value = Success(84)

319

mock_result.map.return_value = Success("42")

320

321

# Test interaction

322

def double(x: int) -> Success[int]:

323

return Success(x * 2)

324

325

result = mock_result.bind(double)

326

assert result.unwrap() == 84

327

```

328

329

### Debugging and Inspection

330

331

Tools for debugging and inspecting functional container operations.

332

333

```python { .api }

334

def trace_container(container: Container[T], label: str = "") -> Container[T]:

335

"""Log container operations for debugging"""

336

337

def inspect_container(container: Container[T]) -> dict[str, Any]:

338

"""Get detailed inspection info about container"""

339

340

def debug_pipeline(*operations: Callable) -> Callable:

341

"""Debug a pipeline of operations"""

342

343

class ContainerDebugger:

344

"""Debugger for container operations"""

345

346

def __init__(self, enabled: bool = True): ...

347

def trace(self, container: Container[T], operation: str) -> Container[T]: ...

348

def dump_trace(self) -> list[dict]: ...

349

```

350

351

Usage examples:

352

353

```python

354

from returns.contrib.debug import trace_container, debug_pipeline

355

from returns.result import Success

356

from returns.pipeline import flow

357

358

# Trace individual operations

359

result = (

360

Success(42)

361

.bind(lambda x: trace_container(Success(x * 2), "double"))

362

.map(lambda x: trace_container(x + 1, "add_one"))

363

)

364

365

# Debug entire pipeline

366

@debug_pipeline

367

def process_data(x: int) -> int:

368

return flow(

369

x,

370

lambda n: n * 2,

371

lambda n: n + 1,

372

lambda n: n / 2

373

)

374

375

result = process_data(10) # Logs each step

376

```

377

378

## Development Workflow Patterns

379

380

### Test-Driven Development

381

382

```python

383

import pytest

384

from returns.contrib.pytest import ReturnsAsserts

385

from returns.result import Result, Success, Failure

386

387

class TestUserService(ReturnsAsserts):

388

"""TDD example with Returns containers"""

389

390

def test_create_user_success(self):

391

# Test first, implement later

392

user_data = {"name": "John", "email": "john@example.com"}

393

result = create_user(user_data)

394

395

self.assert_success(result, User(name="John", email="john@example.com"))

396

397

def test_create_user_invalid_email(self):

398

user_data = {"name": "John", "email": "invalid-email"}

399

result = create_user(user_data)

400

401

self.assert_failure_with(result, ValidationError("Invalid email"))

402

403

# Implementation follows tests

404

def create_user(data: dict) -> Result[User, ValidationError]:

405

# Implementation guided by tests

406

pass

407

```

408

409

### Property-Based Testing

410

411

```python

412

from hypothesis import given, strategies as st

413

from returns.contrib.hypothesis import get_strategies

414

415

@given(st.lists(st.integers()))

416

def test_fold_properties(numbers):

417

"""Property-based testing of fold operations"""

418

from returns.iterables import Fold

419

from returns.result import Success

420

421

def add(a: int, b: int) -> Success[int]:

422

return Success(a + b)

423

424

results = [Success(n) for n in numbers]

425

folded = Fold.loop(results, Success(0), add)

426

427

# Property: folding should equal sum

428

assert folded.unwrap() == sum(numbers)

429

```

430

431

Development tools in Returns provide comprehensive support for testing, type checking, and debugging functional code, enabling robust development workflows while maintaining the benefits of functional programming patterns.