or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-and-integrations.mdfile-watching.mdindex.mdserver.md

file-watching.mddocs/

0

# File Watching System

1

2

Cross-platform file system monitoring with support for files, directories, glob patterns, and efficient change detection using polling and platform-specific optimizations.

3

4

## Capabilities

5

6

### Watcher Initialization

7

8

Create file watcher instances with automatic cross-platform backend selection.

9

10

```python { .api }

11

class Watcher:

12

def __init__(self):

13

"""

14

Initialize file watcher with default configuration.

15

16

Sets up internal data structures for tracking file modifications,

17

configures default ignored directories (.git, .hg, .svn, .cvs),

18

and prepares for file system monitoring.

19

"""

20

21

def get_watcher_class():

22

"""

23

Get appropriate watcher class based on system capabilities.

24

25

Returns:

26

class: INotifyWatcher on Linux with pyinotify available,

27

otherwise standard Watcher class

28

"""

29

```

30

31

**Usage Examples:**

32

33

```python

34

from livereload.watcher import get_watcher_class

35

36

# Get best available watcher for current system

37

WatcherClass = get_watcher_class()

38

watcher = WatcherClass()

39

40

# Direct instantiation

41

from livereload.watcher import Watcher

42

watcher = Watcher()

43

```

44

45

### Watch Registration

46

47

Register paths for monitoring with optional callbacks, delays, and ignore functions.

48

49

```python { .api }

50

def watch(self, path, func=None, delay=0, ignore=None):

51

"""

52

Add a watching task for specified path.

53

54

Args:

55

path (str): File path, directory path, or glob pattern to monitor

56

func (callable): Callback function when changes detected (optional)

57

delay (float): Delay in seconds before triggering callback (default: 0)

58

ignore (callable): Custom function to determine ignored files (optional)

59

"""

60

```

61

62

**Usage Examples:**

63

64

```python

65

# Watch single file

66

watcher.watch('config.py')

67

68

# Watch directory

69

watcher.watch('templates/')

70

71

# Watch with glob pattern

72

watcher.watch('**/*.py')

73

watcher.watch('static/**/*.css')

74

75

# Watch with callback

76

def on_change():

77

print("Files changed, rebuilding...")

78

79

watcher.watch('src/', on_change)

80

81

# Watch with delay

82

watcher.watch('large_files/', delay=2.0)

83

84

# Watch with custom ignore function

85

def ignore_build_files(filename):

86

return filename.endswith(('.pyc', '.pyo', '.tmp'))

87

88

watcher.watch('project/', ignore=ignore_build_files)

89

```

90

91

### Change Detection

92

93

Monitor file system changes and execute associated callbacks.

94

95

```python { .api }

96

def start(self, callback):

97

"""

98

Start the watcher with given callback function.

99

100

Args:

101

callback (callable): Function to call when any watched changes occur

102

103

Returns:

104

bool: True if async watching is supported, False for polling mode

105

"""

106

107

def examine(self):

108

"""

109

Check for changes and run associated tasks.

110

111

Returns:

112

tuple or None: (modified_filepath, reload_delay) if changes found,

113

None if no changes detected

114

"""

115

116

def is_changed(self, path, ignore=None):

117

"""

118

Check if any files have been added, modified, or removed.

119

120

Args:

121

path (str): Path to check for changes

122

ignore (callable): Custom ignore function (optional)

123

124

Returns:

125

bool: True if changes detected, False otherwise

126

"""

127

```

128

129

**Usage Examples:**

130

131

```python

132

# Start watching with global callback

133

def global_callback():

134

print("Changes detected!")

135

136

# Returns True if using inotify, False if polling

137

supports_async = watcher.start(global_callback)

138

139

# Manual change examination

140

result = watcher.examine()

141

if result:

142

filepath, delay = result

143

print(f"File {filepath} changed, delay: {delay}s")

144

145

# Check specific path for changes

146

if watcher.is_changed('config/'):

147

print("Configuration files changed")

148

```

149

150

### Ignore Configuration

151

152

Configure which files and directories should be ignored during monitoring.

153

154

```python { .api }

155

def ignore_dirs(self, *args):

156

"""

157

Add directories to ignore list.

158

159

Args:

160

*args: Variable number of directory names to ignore

161

"""

162

163

def remove_dirs_from_ignore(self, *args):

164

"""

165

Remove directories from ignore list.

166

167

Args:

168

*args: Variable number of directory names to stop ignoring

169

"""

170

171

def ignore(self, filename):

172

"""

173

Check if filename should be ignored based on default rules.

174

175

Args:

176

filename (str): File name to check

177

178

Returns:

179

bool: True if file should be ignored, False otherwise

180

"""

181

```

182

183

**Usage Examples:**

184

185

```python

186

# Add directories to ignore

187

watcher.ignore_dirs('node_modules', '__pycache__', '.venv')

188

189

# Remove directory from ignore list

190

watcher.remove_dirs_from_ignore('.git') # Now watch .git changes

191

192

# Check if file would be ignored

193

should_ignore = watcher.ignore('temp.pyc') # Returns True

194

195

# Custom ignore patterns combined with defaults

196

def custom_ignore(filename):

197

# Use default ignore rules

198

if watcher.ignore(filename):

199

return True

200

# Add custom rules

201

return filename.startswith('temp_') or filename.endswith('.bak')

202

203

watcher.watch('project/', ignore=custom_ignore)

204

```

205

206

### Advanced Change Detection

207

208

Detailed file system change detection with granular control over monitoring behavior.

209

210

```python { .api }

211

def is_file_removed(self):

212

"""

213

Check if any files have been removed since last check.

214

215

Returns:

216

bool: True if files were removed, False otherwise

217

"""

218

219

def is_file_changed(self, path, ignore=None):

220

"""

221

Check if specific file has been added or modified.

222

223

Args:

224

path (str): File path to check

225

ignore (callable): Custom ignore function (optional)

226

227

Returns:

228

bool: True if file changed, False otherwise

229

"""

230

231

def is_folder_changed(self, path, ignore=None):

232

"""

233

Check if directory has any changed files.

234

235

Args:

236

path (str): Directory path to check

237

ignore (callable): Custom ignore function (optional)

238

239

Returns:

240

bool: True if folder contents changed, False otherwise

241

"""

242

243

def get_changed_glob_files(self, path, ignore=None):

244

"""

245

Get list of changed files matching glob pattern.

246

247

Args:

248

path (str): Glob pattern to check

249

ignore (callable): Custom ignore function (optional)

250

251

Returns:

252

list: List of changed files matching pattern

253

"""

254

```

255

256

**Usage Examples:**

257

258

```python

259

# Check for removed files

260

if watcher.is_file_removed():

261

print("Some files were deleted")

262

263

# Check specific file

264

if watcher.is_file_changed('config.py'):

265

print("Configuration changed")

266

267

# Check directory

268

if watcher.is_folder_changed('templates/'):

269

print("Template files changed")

270

271

# Get changed files matching pattern

272

changed_py_files = watcher.get_changed_glob_files('**/*.py')

273

for file in changed_py_files:

274

print(f"Python file changed: {file}")

275

```

276

277

### Linux inotify Optimization

278

279

Enhanced file watching using Linux inotify for efficient, event-driven monitoring.

280

281

```python { .api }

282

class INotifyWatcher(Watcher):

283

def __init__(self):

284

"""

285

Initialize inotify-based watcher (Linux only).

286

287

Requires pyinotify package. Provides event-driven file monitoring

288

instead of polling for better performance and lower resource usage.

289

"""

290

291

def watch(self, path, func=None, delay=None, ignore=None):

292

"""

293

Add path to inotify watch list with recursive monitoring.

294

295

Args:

296

path (str): Path to monitor with inotify (supports glob patterns)

297

func (callable): Callback function (optional)

298

delay (float): Delay before callback (optional)

299

ignore (callable): Ignore function (optional)

300

"""

301

302

def start(self, callback):

303

"""

304

Start inotify-based watching with Tornado async integration.

305

306

Args:

307

callback (callable): Function to call on changes

308

309

Returns:

310

bool: Always True (supports async watching)

311

"""

312

313

def inotify_event(self, event):

314

"""

315

Internal event handler for inotify events.

316

317

Args:

318

event: PyInotify event object

319

"""

320

```

321

322

**Usage Examples:**

323

324

```python

325

# Only available on Linux with pyinotify

326

try:

327

from livereload.watcher import INotifyWatcher

328

watcher = INotifyWatcher()

329

print("Using efficient inotify watching")

330

except ImportError:

331

from livereload.watcher import Watcher

332

watcher = Watcher()

333

print("Using polling-based watching")

334

335

# Same API as regular Watcher

336

watcher.watch('project/')

337

watcher.start(lambda: print("Files changed!"))

338

```

339

340

## Advanced Usage

341

342

### Custom Watch Workflows

343

344

```python

345

from livereload.watcher import get_watcher_class

346

import time

347

348

# Create custom watching workflow

349

WatcherClass = get_watcher_class()

350

watcher = WatcherClass()

351

352

# Set up multiple watch targets

353

watcher.watch('src/*.py', delay=0.5)

354

watcher.watch('tests/*.py', delay=1.0)

355

watcher.watch('docs/*.md', delay=2.0)

356

357

# Custom ignore function

358

def ignore_build_artifacts(filename):

359

ignore_patterns = ['.pyc', '.pyo', '.pyd', '__pycache__', '.pytest_cache']

360

return any(pattern in filename for pattern in ignore_patterns)

361

362

watcher.watch('project/', ignore=ignore_build_artifacts)

363

364

# Start monitoring

365

def handle_changes():

366

result = watcher.examine()

367

if result:

368

filepath, delay = result

369

print(f"Change detected in {filepath}, waiting {delay}s")

370

time.sleep(delay)

371

print("Processing change...")

372

373

# Manual polling loop

374

while True:

375

handle_changes()

376

time.sleep(0.1)

377

```

378

379

### Integration with Build Systems

380

381

```python

382

import subprocess

383

from livereload.watcher import get_watcher_class

384

385

def create_build_watcher():

386

WatcherClass = get_watcher_class()

387

watcher = WatcherClass()

388

389

def run_tests():

390

print("Running tests...")

391

subprocess.run(['python', '-m', 'pytest'])

392

393

def compile_assets():

394

print("Compiling assets...")

395

subprocess.run(['npm', 'run', 'build'])

396

397

def generate_docs():

398

print("Generating documentation...")

399

subprocess.run(['sphinx-build', 'docs/', 'docs/_build/'])

400

401

# Watch different file types with different actions

402

watcher.watch('tests/', run_tests, delay=1.0)

403

watcher.watch('assets/', compile_assets, delay=2.0)

404

watcher.watch('docs/', generate_docs, delay=3.0)

405

406

return watcher

407

408

# Use in development workflow

409

build_watcher = create_build_watcher()

410

build_watcher.start(lambda: print("Build system active"))

411

```