or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-backend.mdcommands.mdcore-classes.mdcore-setup.mdexceptions.mdindex.mdpkg-resources.mdutilities.md

utilities.mddocs/

0

# Utilities

1

2

Additional utility functions for archive handling, file operations, and other common setuptools operations. These utilities provide helpful functionality for package building, file management, and specialized string handling.

3

4

## Capabilities

5

6

### Archive Utilities

7

8

Functions for extracting and handling various archive formats commonly used in Python packaging.

9

10

```python { .api }

11

def unpack_archive(filename, extract_dir='.', drivers=None):

12

"""

13

Extract various archive formats to a directory.

14

15

Automatically detects archive format and extracts using the

16

appropriate method. Supports zip, tar, tar.gz, tar.bz2, and other formats.

17

18

Parameters:

19

- filename (str): Path to archive file to extract

20

- extract_dir (str): Directory to extract files to (default: current directory)

21

- drivers (list, optional): List of extraction drivers to try

22

23

Returns:

24

None

25

26

Raises:

27

UnpackError: If extraction fails

28

"""

29

30

def unpack_zipfile(filename, extract_dir='.'):

31

"""

32

Extract ZIP archive to a directory.

33

34

Specialized function for extracting ZIP files with proper

35

handling of file permissions and directory structure.

36

37

Parameters:

38

- filename (str): Path to ZIP file

39

- extract_dir (str): Directory to extract to (default: current directory)

40

41

Returns:

42

None

43

44

Raises:

45

UnpackError: If ZIP extraction fails

46

"""

47

48

def unpack_tarfile(filename, extract_dir='.'):

49

"""

50

Extract TAR archive (including compressed variants) to a directory.

51

52

Handles tar, tar.gz, tar.bz2, and tar.xz files with proper

53

permission and timestamp preservation.

54

55

Parameters:

56

- filename (str): Path to TAR file

57

- extract_dir (str): Directory to extract to (default: current directory)

58

59

Returns:

60

None

61

62

Raises:

63

UnpackError: If TAR extraction fails

64

"""

65

66

def default_filter(src, dst):

67

"""

68

Default filter function for archive extraction.

69

70

Provides security filtering for archive extraction to prevent

71

directory traversal attacks and other security issues.

72

73

Parameters:

74

- src (str): Source path within archive

75

- dst (str): Destination path for extraction

76

77

Returns:

78

str: Filtered destination path, or None to skip file

79

80

This function is used internally by the unpack functions to

81

ensure safe extraction by filtering out dangerous paths.

82

"""

83

84

def unpack_directory(filename, extract_dir='.'):

85

"""

86

Process a directory as if it were an archive.

87

88

Simply copies directory contents, used internally by unpack_archive

89

when the "archive" is actually a directory.

90

91

Parameters:

92

- filename (str): Path to directory to process

93

- extract_dir (str): Directory to copy contents to

94

95

Returns:

96

None

97

"""

98

```

99

100

### File Utilities

101

102

Functions for file system operations and comparisons.

103

104

```python { .api }

105

def newer(source, target):

106

"""

107

Check if source file is newer than target file.

108

109

Parameters:

110

- source (str): Path to source file

111

- target (str): Path to target file

112

113

Returns:

114

bool: True if source is newer than target or target doesn't exist

115

"""

116

117

def newer_pairwise(sources_and_targets):

118

"""

119

Check if each source is newer than its corresponding target.

120

121

Parameters:

122

- sources_and_targets (list): List of (source, target) tuples

123

124

Returns:

125

list[bool]: List of boolean results for each pair

126

"""

127

128

def newer_group(sources, target, missing='error'):

129

"""

130

Check if any source file is newer than target.

131

132

Parameters:

133

- sources (list): List of source file paths

134

- target (str): Path to target file

135

- missing (str): How to handle missing source files ('error', 'ignore', 'newer')

136

137

Returns:

138

bool: True if any source is newer than target

139

"""

140

141

def newer_pairwise_group(sources_and_targets):

142

"""

143

Check if any source is newer than any target in groups.

144

145

Parameters:

146

- sources_and_targets (list): List of (sources_list, targets_list) tuples

147

148

Returns:

149

list[bool]: List of boolean results for each group

150

"""

151

```

152

153

### Globbing Functions

154

155

Pattern matching functions for file discovery.

156

157

```python { .api }

158

def glob(pathname, *, root_dir=None, dir_fd=None, recursive=False):

159

"""

160

Find pathnames matching a shell-style pattern.

161

162

Enhanced version of standard glob.glob with setuptools-specific behavior.

163

164

Parameters:

165

- pathname (str): Pattern to match (supports *, ?, [seq], **/)

166

- root_dir (str, optional): Root directory for relative patterns

167

- dir_fd (int, optional): File descriptor for directory

168

- recursive (bool): Whether ** matches directories recursively

169

170

Returns:

171

list[str]: List of matching paths

172

"""

173

174

def iglob(pathname, *, root_dir=None, dir_fd=None, recursive=False):

175

"""

176

Iterator version of glob().

177

178

Parameters: Same as glob()

179

180

Returns:

181

Iterator[str]: Iterator over matching paths

182

"""

183

184

def escape(pathname):

185

"""

186

Escape special characters in pathname for literal matching.

187

188

Parameters:

189

- pathname (str): Path that may contain special glob characters

190

191

Returns:

192

str: Escaped pathname for literal matching

193

"""

194

```

195

196

### Configuration Functions

197

198

Functions for parsing and handling setuptools configuration files.

199

200

```python { .api }

201

def parse_configuration(filepath):

202

"""

203

Parse setup.cfg configuration file.

204

205

DEPRECATED: Use pyproject.toml instead of setup.cfg for new projects.

206

207

Parameters:

208

- filepath (str): Path to setup.cfg file

209

210

Returns:

211

dict: Parsed configuration data

212

213

Raises:

214

DistutilsFileError: If configuration file cannot be read

215

"""

216

217

def read_configuration(filepath, find_others=False, ignore_option_errors=False):

218

"""

219

Read and parse setup.cfg and other configuration files.

220

221

DEPRECATED: Use pyproject.toml instead of setup.cfg for new projects.

222

223

Parameters:

224

- filepath (str): Path to main configuration file

225

- find_others (bool): Whether to find and parse related config files

226

- ignore_option_errors (bool): Whether to ignore invalid options

227

228

Returns:

229

dict: Combined configuration from all sources

230

"""

231

```

232

233

### String Utilities

234

235

Specialized string classes for setuptools operations.

236

237

```python { .api }

238

class sic(str):

239

"""

240

String class for literal treatment.

241

242

A string subclass that signals to setuptools that the string

243

should be treated literally without any special processing or

244

interpretation. Used internally for certain setuptools operations

245

where exact string preservation is required.

246

247

Example:

248

literal_string = sic("some_literal_value")

249

"""

250

251

def __new__(cls, s=''):

252

"""

253

Create new sic string instance.

254

255

Parameters:

256

- s (str): String value to wrap

257

258

Returns:

259

sic: New sic string instance

260

"""

261

```

262

263

### Version Information

264

265

Access to setuptools version information.

266

267

```python { .api }

268

__version__: str

269

"""

270

Current setuptools version string.

271

272

Example: "68.2.2"

273

This can be used to check setuptools version at runtime

274

and implement version-specific behavior.

275

"""

276

```

277

278

### Package Discovery Classes

279

280

Advanced package discovery classes that power the find_packages functions.

281

282

```python { .api }

283

class PackageFinder:

284

"""

285

Standard package discovery class.

286

287

Provides the underlying implementation for find_packages()

288

with methods for discovering regular Python packages.

289

"""

290

291

@staticmethod

292

def find(where='.', exclude=(), include=('*',)):

293

"""

294

Find Python packages in directory tree.

295

296

Parameters:

297

- where (str): Root directory to search

298

- exclude (tuple): Patterns to exclude

299

- include (tuple): Patterns to include

300

301

Returns:

302

list: List of package names

303

"""

304

305

class PEP420PackageFinder:

306

"""

307

PEP 420 namespace package discovery class.

308

309

Provides the underlying implementation for find_namespace_packages()

310

with methods for discovering implicit namespace packages.

311

"""

312

313

@staticmethod

314

def find(where='.', exclude=(), include=('*',)):

315

"""

316

Find PEP 420 namespace packages in directory tree.

317

318

Parameters:

319

- where (str): Root directory to search

320

- exclude (tuple): Patterns to exclude

321

- include (tuple): Patterns to include

322

323

Returns:

324

list: List of namespace package names

325

"""

326

```

327

328

### Requirement Management

329

330

Classes for handling package requirements and dependencies.

331

332

```python { .api }

333

class Require:

334

"""

335

Represents a prerequisite for building or installing a distribution.

336

337

This class encapsulates information about required packages or

338

modules and provides methods to check their availability and versions.

339

340

Attributes:

341

- name (str): Requirement name

342

- requested_version (str): Requested version specification

343

- module_name (str): Python module name to check

344

- homepage (str): Homepage URL for the requirement

345

- attribute (str): Module attribute to check for version

346

- format (str): Version format specification

347

"""

348

349

def __init__(self, name, requested_version, module_name, homepage='',

350

attribute=None, format=None):

351

"""

352

Initialize requirement specification.

353

354

Parameters:

355

- name (str): Human-readable name of requirement

356

- requested_version (str): Version specification (e.g., ">=1.0")

357

- module_name (str): Python module name to import and check

358

- homepage (str): URL for requirement homepage

359

- attribute (str): Module attribute containing version info

360

- format (str): Format string for version extraction

361

"""

362

363

def version_ok(self, version):

364

"""

365

Check if a version satisfies this requirement.

366

367

Parameters:

368

- version (str): Version string to check

369

370

Returns:

371

bool: True if version satisfies requirement

372

"""

373

374

def get_version(self, paths=None, default='unknown'):

375

"""

376

Get version of installed requirement.

377

378

Parameters:

379

- paths (list, optional): Paths to search for module

380

- default (str): Default version if not found

381

382

Returns:

383

str: Version string of installed requirement

384

"""

385

386

def is_present(self, paths=None):

387

"""

388

Check if requirement is present (importable).

389

390

Parameters:

391

- paths (list, optional): Paths to search for module

392

393

Returns:

394

bool: True if requirement is present

395

"""

396

397

def is_current(self, paths=None):

398

"""

399

Check if requirement is present and version is current.

400

401

Parameters:

402

- paths (list, optional): Paths to search for module

403

404

Returns:

405

bool: True if requirement is present and satisfies version

406

"""

407

```

408

409

## Usage Examples

410

411

### Archive Extraction

412

413

```python

414

from setuptools.archive_util import unpack_archive, unpack_zipfile, unpack_tarfile

415

416

# Extract any supported archive format

417

unpack_archive('package-1.0.tar.gz', 'extracted/')

418

419

# Extract specific formats

420

unpack_zipfile('package-1.0.zip', 'build/zip_contents/')

421

unpack_tarfile('package-1.0.tar.gz', 'build/tar_contents/')

422

423

# Extract to current directory

424

unpack_archive('dependency.tar.bz2')

425

```

426

427

### Custom Package Discovery

428

429

```python

430

from setuptools.discovery import PackageFinder, PEP420PackageFinder

431

432

# Use package finders directly

433

finder = PackageFinder()

434

packages = finder.find(where='src', exclude=['tests*'])

435

436

namespace_finder = PEP420PackageFinder()

437

ns_packages = namespace_finder.find(where='src', include=['company.*'])

438

439

print(f"Regular packages: {packages}")

440

print(f"Namespace packages: {ns_packages}")

441

```

442

443

### Requirement Checking

444

445

```python

446

from setuptools.depends import Require

447

448

# Define a requirement

449

numpy_req = Require(

450

name='NumPy',

451

requested_version='>=1.19.0',

452

module_name='numpy',

453

homepage='https://numpy.org',

454

attribute='__version__'

455

)

456

457

# Check if requirement is satisfied

458

if numpy_req.is_present():

459

version = numpy_req.get_version()

460

if numpy_req.version_ok(version):

461

print(f"NumPy {version} is available and satisfies requirement")

462

else:

463

print(f"NumPy {version} is available but doesn't satisfy requirement")

464

else:

465

print("NumPy is not available")

466

467

# Check current status

468

if numpy_req.is_current():

469

print("NumPy requirement is fully satisfied")

470

else:

471

print("NumPy requirement is not satisfied")

472

```

473

474

### Version Checking

475

476

```python

477

import setuptools

478

479

# Check setuptools version

480

print(f"Using setuptools version: {setuptools.__version__}")

481

482

# Version-specific behavior

483

from packaging import version

484

if version.parse(setuptools.__version__) >= version.parse("61.0"):

485

print("Using modern setuptools with pyproject.toml support")

486

# Use modern features

487

else:

488

print("Using legacy setuptools")

489

# Fall back to legacy behavior

490

```

491

492

### Literal String Handling

493

494

```python

495

from setuptools import sic

496

497

# Create literal strings for special setuptools processing

498

literal_value = sic("--global-option")

499

processed_value = "processed_value"

500

501

# The sic class signals that the string should not be modified

502

# by setuptools internal processing

503

options = [literal_value, processed_value]

504

```

505

506

### Custom Archive Handling

507

508

```python

509

from setuptools.archive_util import unpack_archive, default_filter

510

import os

511

512

def safe_extract_with_filtering(archive_path, extract_dir):

513

"""Safely extract archive with custom filtering."""

514

515

def custom_filter(src, dst):

516

"""Custom filter to prevent certain extractions."""

517

# Use default security filtering

518

filtered_dst = default_filter(src, dst)

519

if filtered_dst is None:

520

return None

521

522

# Additional custom filtering

523

if src.startswith('dangerous/'):

524

print(f"Skipping dangerous path: {src}")

525

return None

526

527

return filtered_dst

528

529

# Extract with custom filtering

530

os.makedirs(extract_dir, exist_ok=True)

531

unpack_archive(archive_path, extract_dir)

532

print(f"Safely extracted {archive_path} to {extract_dir}")

533

```

534

535

### Build-time Archive Processing

536

537

```python

538

from setuptools import setup, Command

539

from setuptools.archive_util import unpack_archive

540

import tempfile

541

import shutil

542

543

class ExtractDataCommand(Command):

544

"""Custom command to extract data archives during build."""

545

546

description = 'Extract data archives'

547

user_options = [

548

('data-archive=', 'd', 'Path to data archive'),

549

('extract-dir=', 'e', 'Directory to extract to'),

550

]

551

552

def initialize_options(self):

553

self.data_archive = None

554

self.extract_dir = 'data'

555

556

def finalize_options(self):

557

if self.data_archive is None:

558

raise ValueError("data-archive option is required")

559

560

def run(self):

561

"""Extract data archive during build."""

562

self.announce(f'Extracting {self.data_archive} to {self.extract_dir}')

563

564

# Create extraction directory

565

os.makedirs(self.extract_dir, exist_ok=True)

566

567

# Extract archive

568

unpack_archive(self.data_archive, self.extract_dir)

569

570

self.announce(f'Extraction completed')

571

572

setup(

573

name='my-package',

574

cmdclass={

575

'extract_data': ExtractDataCommand,

576

},

577

)

578

```

579

580

### Development Utilities

581

582

```python

583

from setuptools import setup, find_packages

584

from setuptools.discovery import PackageFinder

585

import os

586

587

def find_packages_with_debug():

588

"""Find packages with debugging information."""

589

finder = PackageFinder()

590

591

# Find packages with detailed logging

592

print("Searching for packages...")

593

packages = finder.find(where='src')

594

595

for package in packages:

596

package_path = os.path.join('src', package.replace('.', os.sep))

597

print(f"Found package: {package} at {package_path}")

598

599

return packages

600

601

# Use in setup

602

setup(

603

name='my-package',

604

packages=find_packages_with_debug(),

605

)

606

```