or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

chooser.mdcommand-line.mdconfiguration.mddiff-utilities.mdfile-utilities.mdformatters.mdgit-integration.mdindex.mdmain-functions.mdpreprocessors.mdverification.md

file-utilities.mddocs/

0

# File and Path Utilities

1

2

Helper functions for working with files, directories, and path filtering. These utilities support project discovery, configuration file location, and file filtering based on include/exclude patterns.

3

4

## Capabilities

5

6

### Project Configuration Discovery

7

8

Functions for finding project configuration files and roots.

9

10

```python { .api }

11

def find_pyproject_toml(path_search_start: tuple[str, ...]) -> str | None:

12

"""

13

Find the absolute filepath to a pyproject.toml if it exists.

14

15

Searches upward from the given starting paths to locate the project

16

root and check for pyproject.toml configuration.

17

18

Parameters:

19

- path_search_start: Tuple of starting paths to search from

20

21

Returns:

22

Absolute path to pyproject.toml file, or None if not found

23

"""

24

```

25

26

### File Filtering Constants

27

28

Pre-compiled regular expressions for filtering Python files and excluding common directories.

29

30

```python { .api }

31

DEFAULT_EXCLUDE_RE: Pattern[str]

32

"""

33

Regular expression for default exclusion patterns.

34

35

Excludes common directories like:

36

- .git, .hg, .svn (version control)

37

- .mypy_cache, .pytest_cache, .ruff_cache (tool caches)

38

- .tox, .nox (testing environments)

39

- __pycache__, .eggs (Python artifacts)

40

- build, dist, _build (build outputs)

41

- .venv, venv (virtual environments)

42

- .vscode, .direnv (editor/tool directories)

43

"""

44

45

DEFAULT_INCLUDE_RE: Pattern[str]

46

"""

47

Regular expression for default inclusion patterns.

48

49

Includes files with extensions:

50

- .py (Python files)

51

- .pyi (Python stub files)

52

- .ipynb (Jupyter notebooks)

53

"""

54

```

55

56

### Path Processing Functions

57

58

Functions for processing and filtering file paths.

59

60

```python { .api }

61

def filter_python_files_directory(

62

paths: Collection[Path],

63

root: Path,

64

include: Pattern[str],

65

exclude: Pattern[str],

66

extend_exclude: Pattern[str] | None,

67

force_exclude: Pattern[str] | None,

68

formatter: BaseFormatter,

69

) -> Iterator[Path]:

70

"""

71

Filter Python files in directories based on include/exclude patterns.

72

73

Parameters:

74

- paths: Collection of file/directory paths to process

75

- root: Root directory for relative path calculations

76

- include: Pattern for files to include

77

- exclude: Pattern for files/directories to exclude

78

- extend_exclude: Additional exclusion pattern

79

- force_exclude: Pattern that overrides all inclusion rules

80

- formatter: Formatter instance for additional filtering

81

82

Yields:

83

Path objects for Python files that match the filtering criteria

84

"""

85

86

def gen_python_files(

87

paths: Collection[Path],

88

root: Path,

89

include: Pattern[str],

90

exclude: Pattern[str],

91

extend_exclude: Pattern[str] | None = None,

92

force_exclude: Pattern[str] | None = None,

93

) -> Iterator[Path]:

94

"""

95

Generate Python file paths from given directories and files.

96

97

Parameters:

98

- paths: Paths to files/directories to process

99

- root: Project root directory

100

- include: Pattern for files to include

101

- exclude: Pattern for files/directories to exclude

102

- extend_exclude: Additional exclusion pattern

103

- force_exclude: Pattern that overrides inclusion rules

104

105

Yields:

106

Path objects for Python files matching the criteria

107

"""

108

```

109

110

## Usage Examples

111

112

### Finding Project Configuration

113

114

```python

115

from darker.files import find_pyproject_toml

116

117

# Find pyproject.toml starting from current directory

118

config_path = find_pyproject_toml((".",))

119

120

if config_path:

121

print(f"Found project config: {config_path}")

122

123

# Read configuration

124

import tomllib

125

with open(config_path, 'rb') as f:

126

config = tomllib.load(f)

127

128

darker_config = config.get('tool', {}).get('darker', {})

129

print(f"Darker config: {darker_config}")

130

else:

131

print("No pyproject.toml found")

132

```

133

134

### Using Default Filter Patterns

135

136

```python

137

from darker.files import DEFAULT_INCLUDE_RE, DEFAULT_EXCLUDE_RE

138

from pathlib import Path

139

140

# Test if files match default patterns

141

test_files = [

142

"src/module.py",

143

"tests/test_module.py",

144

"setup.py",

145

"README.md",

146

".git/config",

147

"__pycache__/module.pyc",

148

"dist/package.whl"

149

]

150

151

for file_path in test_files:

152

path = Path(file_path)

153

154

# Check inclusion

155

includes = DEFAULT_INCLUDE_RE.search(str(path))

156

157

# Check exclusion

158

excludes = DEFAULT_EXCLUDE_RE.search(str(path))

159

160

if includes and not excludes:

161

print(f"✓ Would process: {file_path}")

162

else:

163

reason = "excluded" if excludes else "not Python file"

164

print(f"✗ Would skip: {file_path} ({reason})")

165

```

166

167

### Custom File Filtering

168

169

```python

170

import re

171

from darker.files import gen_python_files

172

from pathlib import Path

173

174

# Create custom patterns

175

custom_include = re.compile(r'(\.py|\.pyx)$') # Include Cython files

176

custom_exclude = re.compile(r'/(build|dist|\.tox)/')

177

custom_extend_exclude = re.compile(r'/legacy/') # Skip legacy code

178

179

# Find Python files with custom filters

180

root = Path(".")

181

paths = [Path("src"), Path("tests")]

182

183

python_files = list(gen_python_files(

184

paths=paths,

185

root=root,

186

include=custom_include,

187

exclude=custom_exclude,

188

extend_exclude=custom_extend_exclude

189

))

190

191

print(f"Found {len(python_files)} Python files:")

192

for file_path in python_files:

193

print(f" {file_path}")

194

```

195

196

### Integration with Formatter Filtering

197

198

```python

199

from darker.files import filter_python_files_directory

200

from darker.formatters import create_formatter

201

from pathlib import Path

202

import re

203

204

# Set up formatter and patterns

205

formatter = create_formatter("black")

206

root = Path(".")

207

paths = [Path("src"), Path("tests")]

208

209

include_pattern = re.compile(r'\.pyi?$')

210

exclude_pattern = re.compile(r'/(\.git|__pycache__|\.pytest_cache)/')

211

212

# Filter files that the formatter can process

213

filtered_files = list(filter_python_files_directory(

214

paths=paths,

215

root=root,

216

include=include_pattern,

217

exclude=exclude_pattern,

218

extend_exclude=None,

219

force_exclude=None,

220

formatter=formatter

221

))

222

223

print(f"Files to format with {formatter.name}:")

224

for file_path in filtered_files:

225

print(f" {file_path}")

226

```

227

228

### Recursive Directory Processing

229

230

```python

231

from darker.files import gen_python_files, DEFAULT_INCLUDE_RE, DEFAULT_EXCLUDE_RE

232

from pathlib import Path

233

234

def find_all_python_files(start_path: Path) -> list[Path]:

235

"""Find all Python files recursively from a starting path."""

236

237

if start_path.is_file():

238

# Single file

239

if DEFAULT_INCLUDE_RE.search(str(start_path)):

240

return [start_path]

241

else:

242

return []

243

244

# Directory - search recursively

245

return list(gen_python_files(

246

paths=[start_path],

247

root=start_path,

248

include=DEFAULT_INCLUDE_RE,

249

exclude=DEFAULT_EXCLUDE_RE

250

))

251

252

# Usage examples

253

project_files = find_all_python_files(Path("src"))

254

test_files = find_all_python_files(Path("tests"))

255

single_file = find_all_python_files(Path("setup.py"))

256

257

print(f"Project files: {len(project_files)}")

258

print(f"Test files: {len(test_files)}")

259

print(f"Single file: {len(single_file)}")

260

```