or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdfile-filtering.mdfile-watching.mdindex.mdprocess-management.md

file-filtering.mddocs/

0

# File Filtering

1

2

Flexible filtering system to control which file changes are monitored and reported. Provides built-in filters for common use cases and extensible base classes for custom filtering logic.

3

4

## Capabilities

5

6

### Base Filter Class

7

8

Foundation class for creating custom file filters with support for directory ignoring, pattern matching, and path exclusion.

9

10

```python { .api }

11

class BaseFilter:

12

"""

13

Base class for creating file filters.

14

15

Supports ignoring files through:

16

- Full directory names (ignore_dirs)

17

- Regex patterns for file/directory names (ignore_entity_patterns)

18

- Full path exclusions (ignore_paths)

19

"""

20

21

ignore_dirs: Sequence[str] = ()

22

ignore_entity_patterns: Sequence[str] = ()

23

ignore_paths: Sequence[Union[str, Path]] = ()

24

25

def __init__(self) -> None:

26

"""

27

Initialize filter by compiling regex patterns and processing paths.

28

"""

29

30

def __call__(self, change: Change, path: str) -> bool:

31

"""

32

Filter callable that determines if a file change should be included.

33

34

Parameters:

35

- change: Type of change (Change.added, Change.modified, Change.deleted)

36

- path: Raw path of the file or directory that changed

37

38

Returns:

39

bool: True if file should be included, False if ignored

40

"""

41

```

42

43

**Custom Filter Example:**

44

45

```python

46

from watchfiles import BaseFilter, Change

47

import re

48

49

class LogFilter(BaseFilter):

50

# Ignore common log directories

51

ignore_dirs = ('logs', 'tmp', '__pycache__')

52

53

# Ignore log files and temporary files

54

ignore_entity_patterns = (

55

r'\.log$', # Log files

56

r'\.tmp$', # Temporary files

57

r'^\.#', # Emacs temp files

58

r'~$', # Backup files

59

)

60

61

# Ignore specific paths

62

ignore_paths = ('/var/log', '/tmp')

63

64

# Use custom filter

65

from watchfiles import watch

66

67

for changes in watch('./src', watch_filter=LogFilter()):

68

print(f'Non-log changes: {changes}')

69

```

70

71

### Default Filter

72

73

Standard filter that ignores common development files and directories that typically shouldn't trigger reloads.

74

75

```python { .api }

76

class DefaultFilter(BaseFilter):

77

"""

78

Default filter ignoring common development artifacts.

79

"""

80

81

ignore_dirs: Sequence[str] = (

82

'__pycache__', # Python bytecode cache

83

'.git', # Git repository

84

'.hg', # Mercurial repository

85

'.svn', # Subversion repository

86

'.tox', # Tox testing environments

87

'.venv', # Python virtual environment

88

'.idea', # IntelliJ/PyCharm

89

'node_modules', # Node.js dependencies

90

'.mypy_cache', # MyPy type checker cache

91

'.pytest_cache', # Pytest cache

92

'.hypothesis', # Hypothesis testing cache

93

)

94

95

ignore_entity_patterns: Sequence[str] = (

96

r'\.py[cod]$', # Python bytecode files (.pyc, .pyo, .pyd)

97

r'\.___jb_...___$', # JetBrains temp files

98

r'\.sw.$', # Vim swap files

99

'~$', # Backup files

100

r'^\.\#', # Emacs temp files

101

r'^\.DS_Store$', # macOS metadata

102

r'^flycheck_', # Emacs flycheck temp files

103

)

104

105

def __init__(

106

self,

107

*,

108

ignore_dirs: Optional[Sequence[str]] = None,

109

ignore_entity_patterns: Optional[Sequence[str]] = None,

110

ignore_paths: Optional[Sequence[Union[str, Path]]] = None,

111

) -> None:

112

"""

113

Initialize DefaultFilter with optional overrides.

114

115

Parameters:

116

- ignore_dirs: Override default ignore_dirs if provided

117

- ignore_entity_patterns: Override default patterns if provided

118

- ignore_paths: Override default ignore_paths if provided

119

"""

120

```

121

122

**Usage Examples:**

123

124

```python

125

from watchfiles import watch, DefaultFilter

126

127

# Use default filter (this is the default behavior)

128

for changes in watch('./src'):

129

print(changes)

130

131

# Customize default filter

132

custom_filter = DefaultFilter(

133

ignore_dirs=('__pycache__', '.git', 'custom_ignore'),

134

ignore_entity_patterns=(r'\.pyc$', r'\.log$'),

135

ignore_paths=['/tmp/ignore_this']

136

)

137

138

for changes in watch('./src', watch_filter=custom_filter):

139

print(changes)

140

141

# Disable all filtering

142

for changes in watch('./src', watch_filter=None):

143

print(changes) # Will include all changes

144

```

145

146

### Python Filter

147

148

Specialized filter that only watches Python files while also applying the standard default ignores.

149

150

```python { .api }

151

class PythonFilter(DefaultFilter):

152

"""

153

Filter for Python files only.

154

155

Inherits all default ignores and additionally filters to only

156

include files with Python extensions: .py, .pyx, .pyd

157

"""

158

159

extensions: tuple # Set in __init__ to ('.py', '.pyx', '.pyd') + extra_extensions

160

161

def __init__(

162

self,

163

*,

164

ignore_paths: Optional[Sequence[Union[str, Path]]] = None,

165

extra_extensions: Sequence[str] = (),

166

) -> None:

167

"""

168

Initialize PythonFilter.

169

170

Parameters:

171

- ignore_paths: Additional paths to ignore

172

- extra_extensions: Additional file extensions to include beyond Python defaults

173

174

Note:

175

Only ignore_paths can be customized. Directory and pattern ignores

176

use the DefaultFilter defaults.

177

"""

178

179

def __call__(self, change: Change, path: str) -> bool:

180

"""

181

Filter that only includes Python files and applies default ignores.

182

183

Returns:

184

bool: True only if file has Python extension AND passes default filter

185

"""

186

```

187

188

**Usage Examples:**

189

190

```python

191

from watchfiles import watch, PythonFilter

192

193

# Watch only Python files

194

for changes in watch('./src', watch_filter=PythonFilter()):

195

print(f'Python file changes: {changes}')

196

197

# Include additional extensions

198

py_filter = PythonFilter(extra_extensions=('.pyi', '.pyx'))

199

200

for changes in watch('./src', watch_filter=py_filter):

201

print(f'Extended Python changes: {changes}')

202

203

# Ignore specific paths

204

py_filter = PythonFilter(ignore_paths=['./src/generated'])

205

206

for changes in watch('./src', watch_filter=py_filter):

207

print(f'Filtered Python changes: {changes}')

208

```

209

210

### Custom Callable Filters

211

212

Any callable that accepts `(Change, str)` and returns `bool` can be used as a filter:

213

214

```python

215

from watchfiles import watch, Change

216

217

def only_added_files(change: Change, path: str) -> bool:

218

"""Only watch for newly added files."""

219

return change == Change.added

220

221

def only_python_or_js(change: Change, path: str) -> bool:

222

"""Only watch Python and JavaScript files."""

223

return path.endswith(('.py', '.js', '.ts'))

224

225

def size_filter(change: Change, path: str) -> bool:

226

"""Only watch files under 1MB."""

227

try:

228

import os

229

return os.path.getsize(path) < 1024 * 1024

230

except (OSError, FileNotFoundError):

231

return True # Include if we can't check size

232

233

# Use custom filters

234

for changes in watch('./src', watch_filter=only_added_files):

235

print(f'New files: {changes}')

236

237

for changes in watch('./src', watch_filter=only_python_or_js):

238

print(f'Python/JS changes: {changes}')

239

```

240

241

### CLI Filter Integration

242

243

The CLI supports filter specification via command line arguments:

244

245

```bash

246

# Use default filter

247

watchfiles my_module.main ./src

248

249

# Use Python filter

250

watchfiles --filter python my_module.main ./src

251

252

# Use no filter (watch all files)

253

watchfiles --filter all my_module.main ./src

254

255

# Use custom filter class

256

watchfiles --filter mypackage.filters.CustomFilter my_module.main ./src

257

258

# Ignore specific paths (works with default and python filters)

259

watchfiles --filter python --ignore-paths "logs,tmp" my_module.main ./src

260

```

261

262

## Filter Implementation Details

263

264

### Pattern Matching

265

- `ignore_entity_patterns` are compiled as regular expressions

266

- Patterns match against the file/directory name only (not full path)

267

- Use raw strings (`r''`) for regex patterns to avoid escaping issues

268

269

### Path Matching

270

- `ignore_paths` uses `str.startswith()` for prefix matching

271

- Paths are converted to strings for comparison

272

- Both absolute and relative paths are supported

273

274

### Directory Matching

275

- `ignore_dirs` matches exact directory names in the path hierarchy

276

- Checks each component of the path, so subdirectories are also ignored

277

- Case-sensitive matching

278

279

### Performance Considerations

280

- Filters are called for every file change event

281

- Regex compilation happens once during filter initialization

282

- Directory and path checks are optimized for common cases

283

- More complex filters may impact performance with high-frequency changes

284

285

## Types

286

287

```python { .api }

288

# Type annotations for filter functions

289

FilterCallable = Callable[[Change, str], bool]

290

```