or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

arguments.mdcolored-text.mdenglish.mdindex.mdprogress.mdprompts.mdresources.mdtext-output.mdutilities.mdvalidation.md

utilities.mddocs/

0

# Unix Pipes and Utilities

1

2

Unix pipe detection, path expansion utilities, collection testing, and directory creation helpers. This module provides essential utility functions for file system operations, data type checking, and string manipulation commonly needed in CLI applications.

3

4

## Capabilities

5

6

### Unix Pipe Detection

7

8

Detect and read data piped to the application via stdin, enabling CLI tools to work in Unix pipe chains.

9

10

```python { .api }

11

def piped_in():

12

"""

13

Detect and return data piped to the application via stdin.

14

15

Returns:

16

str or None: Content from stdin if data is piped, None otherwise

17

18

Usage:

19

Enables CLI applications to work in Unix pipe chains like:

20

cat file.txt | python app.py

21

echo "data" | python app.py

22

"""

23

```

24

25

**Usage Examples:**

26

27

```python

28

from clint.pipes import piped_in

29

from clint.textui import puts

30

31

# Check for piped input

32

input_data = piped_in()

33

if input_data:

34

puts(f"Received piped data: {len(input_data)} characters")

35

# Process the piped data

36

for line in input_data.splitlines():

37

puts(f"Processing: {line}")

38

else:

39

puts("No piped input detected")

40

41

# CLI tool that works with or without pipes

42

def main():

43

piped_data = piped_in()

44

if piped_data:

45

# Process piped data

46

process_input(piped_data)

47

else:

48

# Interactive mode or file processing

49

filename = input("Enter filename: ")

50

with open(filename) as f:

51

process_input(f.read())

52

```

53

54

### Path Expansion

55

56

Expand user paths, environment variables, directories, and glob patterns into complete file lists.

57

58

```python { .api }

59

def expand_path(path):

60

"""

61

Expand directories and globs in given path to list of files.

62

63

Args:

64

path (str): Path with potential user shortcuts, env vars, directories, or globs

65

66

Returns:

67

list: List of expanded file paths matching the input pattern

68

69

Expansion includes:

70

- User home directory (~)

71

- Environment variables ($HOME, etc.)

72

- Directory traversal (returns all files in directory)

73

- Glob patterns (*.txt, **/*.py, etc.)

74

"""

75

```

76

77

**Usage Examples:**

78

79

```python

80

from clint.utils import expand_path

81

82

# Expand user home directory

83

files = expand_path('~/Documents/*.txt')

84

# Returns: ['/home/user/Documents/file1.txt', '/home/user/Documents/file2.txt']

85

86

# Expand environment variables

87

files = expand_path('$HOME/projects/**/*.py')

88

# Returns all Python files in projects directory and subdirectories

89

90

# Expand directory to all contained files

91

files = expand_path('/etc/nginx/')

92

# Returns: ['/etc/nginx/nginx.conf', '/etc/nginx/sites-available/default', ...]

93

94

# Glob patterns

95

files = expand_path('/var/log/*.log')

96

# Returns: ['/var/log/system.log', '/var/log/app.log', ...]

97

98

# Use in CLI applications

99

import sys

100

from clint.arguments import Args

101

102

args = Args()

103

for pattern in args.all:

104

for filepath in expand_path(pattern):

105

print(f"Processing: {filepath}")

106

# Process each file

107

```

108

109

### Collection Testing

110

111

Test whether an object is a collection type, excluding strings which are treated as atomic values.

112

113

```python { .api }

114

def is_collection(obj):

115

"""

116

Test if an object is a collection. Strings don't count as collections.

117

118

Args:

119

obj: Any Python object to test

120

121

Returns:

122

bool: True if object is a collection (list, tuple, set, etc.) but not a string

123

124

Note:

125

Strings are explicitly excluded because they are iterable but typically

126

treated as atomic values in CLI contexts rather than collections.

127

"""

128

```

129

130

**Usage Examples:**

131

132

```python

133

from clint.utils import is_collection

134

135

# Test various types

136

print(is_collection([1, 2, 3])) # True - list

137

print(is_collection((1, 2, 3))) # True - tuple

138

print(is_collection({1, 2, 3})) # True - set

139

print(is_collection({'a': 1, 'b': 2})) # True - dict

140

print(is_collection("hello")) # False - string

141

print(is_collection(42)) # False - int

142

print(is_collection(range(5))) # True - range object

143

144

# Use in argument processing

145

def process_args(*args):

146

for arg in args:

147

if is_collection(arg):

148

# Handle collections (lists, tuples, etc.)

149

for item in arg:

150

process_item(item)

151

else:

152

# Handle atomic values (strings, numbers, etc.)

153

process_item(arg)

154

155

# CLI application usage

156

from clint.arguments import Args

157

args = Args()

158

159

for arg_value in args.all:

160

if is_collection(arg_value):

161

print(f"Collection with {len(arg_value)} items")

162

else:

163

print(f"Single value: {arg_value}")

164

```

165

166

### Directory Creation

167

168

Create directories recursively, similar to the Unix `mkdir -p` command.

169

170

```python { .api }

171

def mkdir_p(path):

172

"""

173

Create directory and any necessary parent directories (like 'mkdir -p').

174

175

Args:

176

path (str): Directory path to create

177

178

Side Effects:

179

Creates the directory and all parent directories as needed

180

Does nothing if directory already exists (no error)

181

182

Raises:

183

OSError: If directory creation fails for reasons other than already existing

184

"""

185

```

186

187

**Usage Examples:**

188

189

```python

190

from clint.utils import mkdir_p

191

192

# Create nested directories

193

mkdir_p('/tmp/my-app/data/logs') # Creates all intermediate directories

194

195

# Safe to call on existing directories

196

mkdir_p('/tmp/my-app/data/logs') # No error, does nothing

197

198

# Use in application setup

199

import os

200

from clint import resources

201

202

def setup_app_directories():

203

app_base = os.path.expanduser('~/.myapp')

204

mkdir_p(os.path.join(app_base, 'config'))

205

mkdir_p(os.path.join(app_base, 'cache'))

206

mkdir_p(os.path.join(app_base, 'logs'))

207

mkdir_p(os.path.join(app_base, 'plugins'))

208

209

# Error handling

210

try:

211

mkdir_p('/root/protected/directory')

212

except OSError as e:

213

print(f"Failed to create directory: {e}")

214

```

215

216

### String Manipulation

217

218

Advanced string splitting and chunking utilities for text processing.

219

220

```python { .api }

221

def tsplit(string, delimiters):

222

"""

223

Split string using multiple delimiters (like str.split but with multiple delimiters).

224

225

Args:

226

string (str): String to split

227

delimiters (tuple or list): Multiple delimiter characters/strings

228

229

Returns:

230

list: List of string parts split by any of the delimiters

231

"""

232

233

def schunk(string, size):

234

"""

235

Split string into fixed-size chunks.

236

237

Args:

238

string (str): String to split into chunks

239

size (int): Size of each chunk

240

241

Returns:

242

list: List of string chunks, each of specified size (last may be shorter)

243

"""

244

```

245

246

**Usage Examples:**

247

248

```python

249

from clint.utils import tsplit, schunk

250

251

# Split by multiple delimiters

252

text = "apple,banana;orange:grape"

253

parts = tsplit(text, (',', ';', ':'))

254

# Returns: ['apple', 'banana', 'orange', 'grape']

255

256

# Parse CSV-like data with multiple separators

257

data = "name=John|age=25;city=NYC,country=USA"

258

fields = tsplit(data, ('|', ';', ','))

259

# Returns: ['name=John', 'age=25', 'city=NYC', 'country=USA']

260

261

# Process log entries with various separators

262

log_line = "2023-01-01 12:00:00 ERROR: Database connection failed"

263

parts = tsplit(log_line, (' ', ':', '-'))

264

# Returns: ['2023', '01', '01', '12', '00', '00', 'ERROR', '', 'Database', 'connection', 'failed']

265

266

# Chunk large strings for processing

267

large_text = "A" * 1000

268

chunks = schunk(large_text, 100)

269

# Returns: ['A' * 100, 'A' * 100, ..., remaining A's]

270

271

# Process data in fixed-size blocks

272

def process_in_chunks(data, chunk_size=1024):

273

chunks = schunk(data, chunk_size)

274

for i, chunk in enumerate(chunks):

275

print(f"Processing chunk {i+1}/{len(chunks)}: {len(chunk)} characters")

276

# Process each chunk

277

278

# Format data for display

279

def format_hex_dump(data, width=16):

280

hex_chars = data.encode('hex') if hasattr(data, 'encode') else data.hex()

281

chunks = schunk(hex_chars, width * 2) # 2 hex chars per byte

282

for i, chunk in enumerate(chunks):

283

offset = i * width

284

formatted_hex = ' '.join(schunk(chunk, 2))

285

print(f"{offset:08x}: {formatted_hex}")

286

```

287

288

## Complete Usage Examples

289

290

### CLI Tool with Pipe Support

291

292

```python

293

#!/usr/bin/env python

294

from clint.pipes import piped_in

295

from clint.utils import expand_path, is_collection

296

from clint.arguments import Args

297

from clint.textui import puts, colored

298

299

def main():

300

args = Args()

301

302

# Check for piped input first

303

piped_data = piped_in()

304

if piped_data:

305

puts(colored.green("Processing piped data..."))

306

process_text(piped_data)

307

return

308

309

# Process file arguments

310

if args.files:

311

for file_pattern in args.files:

312

file_paths = expand_path(file_pattern)

313

for file_path in file_paths:

314

puts(f"Processing: {file_path}")

315

with open(file_path) as f:

316

process_text(f.read())

317

else:

318

puts(colored.red("No input provided. Use: program < file.txt or program *.txt"))

319

320

def process_text(text):

321

# Process the text data

322

lines = text.splitlines()

323

puts(f"Processing {len(lines)} lines of text")

324

325

if __name__ == '__main__':

326

main()

327

```

328

329

### Application Setup Utility

330

331

```python

332

from clint.utils import mkdir_p, expand_path, is_collection

333

from clint import resources

334

import os

335

336

def setup_application(app_name, config_files=None):

337

"""Set up application directories and copy configuration files."""

338

339

# Initialize application directories

340

resources.init("MyCompany", app_name)

341

342

# Create additional subdirectories

343

mkdir_p(resources.user.path + "/plugins")

344

mkdir_p(resources.user.path + "/themes")

345

mkdir_p(resources.cache.path + "/downloads")

346

347

# Copy configuration files if provided

348

if config_files:

349

if not is_collection(config_files):

350

config_files = [config_files]

351

352

for config_pattern in config_files:

353

config_paths = expand_path(config_pattern)

354

for config_path in config_paths:

355

filename = os.path.basename(config_path)

356

with open(config_path) as f:

357

resources.user.write(f"config/{filename}", f.read())

358

print(f"Copied config: {filename}")

359

360

# Usage

361

setup_application("MyApp", ["~/.myapp-configs/*.ini", "/etc/myapp/defaults/*"])

362

```