or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-migration.mdcore-time-travel.mdescape-hatch.mdindex.mdpytest-integration.md

escape-hatch.mddocs/

0

# Escape Hatch

1

2

The escape hatch provides access to real time functions during time travel, enabling tests to access actual system time when needed. This is essential for performance measurements, external API calls, or any operations requiring real timestamps.

3

4

## Capabilities

5

6

### Escape Hatch Object

7

8

The global `escape_hatch` object provides access to real time functions and travel status checking.

9

10

```python { .api }

11

class _EscapeHatch:

12

def is_travelling(self) -> bool:

13

"""

14

Check if time travel is currently active.

15

16

Returns:

17

True if time travel is active, False otherwise

18

"""

19

20

time: _EscapeHatchTime

21

datetime: _EscapeHatchDatetime

22

```

23

24

```python { .api }

25

escape_hatch: _EscapeHatch

26

```

27

28

Usage examples:

29

30

```python

31

import time_machine

32

from datetime import datetime

33

34

# Check travel status

35

print(time_machine.escape_hatch.is_travelling()) # False

36

37

with time_machine.travel("2023-01-01"):

38

print(time_machine.escape_hatch.is_travelling()) # True

39

40

# Access real time during travel

41

real_time = time_machine.escape_hatch.time.time()

42

fake_time = time.time()

43

44

print(f"Real time: {real_time}")

45

print(f"Fake time: {fake_time}")

46

47

print(time_machine.escape_hatch.is_travelling()) # False

48

```

49

50

### Real Time Functions

51

52

Access to real time module functions that bypass time travel patching.

53

54

```python { .api }

55

class _EscapeHatchTime:

56

def clock_gettime(self, clk_id: int) -> float:

57

"""

58

Get real clock time for specified clock ID.

59

60

Parameters:

61

- clk_id: Clock identifier (e.g., time.CLOCK_REALTIME)

62

63

Returns:

64

Real clock time as float seconds

65

"""

66

67

def clock_gettime_ns(self, clk_id: int) -> int:

68

"""

69

Get real clock time in nanoseconds for specified clock ID.

70

71

Parameters:

72

- clk_id: Clock identifier

73

74

Returns:

75

Real clock time as int nanoseconds

76

"""

77

78

def gmtime(self, secs: float | None = None) -> struct_time:

79

"""

80

Get real GMT time struct.

81

82

Parameters:

83

- secs: Optional timestamp, uses real current time if None

84

85

Returns:

86

Real GMT time as struct_time

87

"""

88

89

def localtime(self, secs: float | None = None) -> struct_time:

90

"""

91

Get real local time struct.

92

93

Parameters:

94

- secs: Optional timestamp, uses real current time if None

95

96

Returns:

97

Real local time as struct_time

98

"""

99

100

def monotonic(self) -> float:

101

"""

102

Get real monotonic time (unaffected by system clock adjustments).

103

104

Returns:

105

Real monotonic time as float seconds

106

"""

107

108

def monotonic_ns(self) -> int:

109

"""

110

Get real monotonic time in nanoseconds.

111

112

Returns:

113

Real monotonic time as int nanoseconds

114

"""

115

116

def strftime(self, format: str, t: tuple | struct_time | None = None) -> str:

117

"""

118

Format real time using strftime.

119

120

Parameters:

121

- format: Format string

122

- t: Optional time tuple, uses real current time if None

123

124

Returns:

125

Formatted time string

126

"""

127

128

def time(self) -> float:

129

"""

130

Get real current time as Unix timestamp.

131

132

Returns:

133

Real current time as float seconds since Unix epoch

134

"""

135

136

def time_ns(self) -> int:

137

"""

138

Get real current time as nanosecond timestamp.

139

140

Returns:

141

Real current time as int nanoseconds since Unix epoch

142

"""

143

```

144

145

Usage examples:

146

147

```python

148

import time

149

import time_machine

150

151

with time_machine.travel("2023-01-01"):

152

# Fake time (2023)

153

fake_time = time.time()

154

155

# Real time (actual current time)

156

real_time = time_machine.escape_hatch.time.time()

157

158

print(f"Travel time: {fake_time}") # ~1672531200 (2023-01-01)

159

print(f"Real time: {real_time}") # Actual current timestamp

160

161

# Performance measurement using real monotonic time

162

start = time_machine.escape_hatch.time.monotonic()

163

# ... some operation ...

164

elapsed = time_machine.escape_hatch.time.monotonic() - start

165

print(f"Real elapsed time: {elapsed}")

166

```

167

168

### Real DateTime Functions

169

170

Access to real datetime module functions that bypass time travel patching.

171

172

```python { .api }

173

class _EscapeHatchDatetime:

174

datetime: _EscapeHatchDatetimeDatetime

175

176

class _EscapeHatchDatetimeDatetime:

177

def now(self, tz: dt.tzinfo | None = None) -> dt.datetime:

178

"""

179

Get real current datetime.

180

181

Parameters:

182

- tz: Optional timezone info

183

184

Returns:

185

Real current datetime object

186

"""

187

188

def utcnow(self) -> dt.datetime:

189

"""

190

Get real current UTC datetime (naive).

191

192

Returns:

193

Real current UTC datetime without timezone info

194

"""

195

```

196

197

Usage examples:

198

199

```python

200

import time_machine

201

from datetime import datetime, timezone

202

203

with time_machine.travel("2023-01-01"):

204

# Fake datetime (2023)

205

fake_now = datetime.now()

206

207

# Real datetime (actual current time)

208

real_now = time_machine.escape_hatch.datetime.datetime.now()

209

210

print(f"Travel time: {fake_now}") # 2023-01-01 00:00:00

211

print(f"Real time: {real_now}") # Actual current datetime

212

213

# Real UTC time

214

real_utc = time_machine.escape_hatch.datetime.datetime.utcnow()

215

print(f"Real UTC: {real_utc}")

216

217

# Real time with timezone

218

real_tz = time_machine.escape_hatch.datetime.datetime.now(timezone.utc)

219

print(f"Real UTC+TZ: {real_tz}")

220

```

221

222

### Common Use Cases

223

224

#### Performance Measurement

225

226

```python

227

import time_machine

228

229

def test_performance():

230

with time_machine.travel("2023-01-01"):

231

# Use real monotonic time for accurate performance measurement

232

start = time_machine.escape_hatch.time.monotonic()

233

234

# Operation being timed

235

slow_operation()

236

237

elapsed = time_machine.escape_hatch.time.monotonic() - start

238

assert elapsed < 1.0 # Should complete within 1 second

239

```

240

241

#### External API Testing

242

243

```python

244

import time_machine

245

import requests

246

247

def test_api_with_real_timestamps():

248

with time_machine.travel("2023-01-01"):

249

# API expects real timestamps in headers

250

real_timestamp = time_machine.escape_hatch.time.time()

251

252

response = requests.post("https://api.example.com/data",

253

headers={"X-Timestamp": str(real_timestamp)},

254

json={"created_at": time.time()}) # Uses fake time

255

256

assert response.status_code == 200

257

```

258

259

#### Logging with Real Timestamps

260

261

```python

262

import time_machine

263

import logging

264

265

def test_with_real_log_timestamps():

266

# Custom formatter using real time

267

class RealTimeFormatter(logging.Formatter):

268

def formatTime(self, record, datefmt=None):

269

real_time = time_machine.escape_hatch.time.time()

270

return super().formatTime(

271

type('Record', (), {'created': real_time})(), datefmt

272

)

273

274

with time_machine.travel("2023-01-01"):

275

logger = logging.getLogger("test")

276

handler = logging.StreamHandler()

277

handler.setFormatter(RealTimeFormatter())

278

logger.addHandler(handler)

279

280

logger.info("This log has real timestamp despite time travel")

281

```

282

283

#### Conditional Logic Based on Travel Status

284

285

```python

286

import time_machine

287

288

def get_current_time():

289

"""Get current time, using real time in production, fake time in tests."""

290

if time_machine.escape_hatch.is_travelling():

291

# In tests - use travel time

292

return datetime.now()

293

else:

294

# In production - use real time

295

return time_machine.escape_hatch.datetime.datetime.now()

296

297

def test_conditional_time():

298

# Outside travel - uses real time

299

real_time = get_current_time()

300

301

with time_machine.travel("2023-01-01"):

302

# Inside travel - uses fake time

303

fake_time = get_current_time()

304

assert fake_time.year == 2023

305

```

306

307

## Type Definitions

308

309

```python { .api }

310

from time import struct_time

311

from datetime import datetime as dt

312

313

_TimeTuple = tuple[int, int, int, int, int, int, int, int, int]

314

```