or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-functions.mdexceptions.mdindex.mdrepository-holders.mdutilities.mdversion-handling.md

exceptions.mddocs/

0

# Exception Handling

1

2

Custom exception classes for specific error conditions encountered during version discovery and file operations. These exceptions provide structured error handling and enable applications to respond appropriately to different failure scenarios.

3

4

## Capabilities

5

6

### API and Authentication Errors

7

8

Exception classes for handling API-related errors and authentication failures across different platforms.

9

10

```python { .api }

11

class ApiCredentialsError(Exception):

12

"""

13

Raised when there's an API error related to credentials or authentication.

14

15

This exception occurs when:

16

- API tokens are invalid or expired

17

- Rate limits are exceeded due to unauthenticated requests

18

- Private repositories require authentication

19

- API endpoints require elevated permissions

20

21

Common scenarios:

22

- GitHub API rate limiting without token

23

- GitLab private project access

24

- Enterprise instance authentication failures

25

"""

26

27

def __init__(self, message: str, platform: str = None):

28

"""

29

Initialize API credentials error.

30

31

Parameters:

32

- message: Descriptive error message

33

- platform: Platform where error occurred (github, gitlab, etc.)

34

"""

35

```

36

37

### Project and Repository Errors

38

39

Exception for handling cases where specified projects or repositories cannot be found or accessed.

40

41

```python { .api }

42

class BadProjectError(Exception):

43

"""

44

Raised when no such project exists or cannot be accessed.

45

46

This exception occurs when:

47

- Repository does not exist on specified platform

48

- Project has been deleted or made private

49

- Invalid repository identifier format

50

- Platform does not host the specified project

51

- Network issues prevent project access

52

53

Common scenarios:

54

- Typos in repository names

55

- Projects moved between platforms

56

- Private repositories without access

57

- Deleted or archived projects

58

"""

59

60

def __init__(self, message: str, repo: str = None):

61

"""

62

Initialize bad project error.

63

64

Parameters:

65

- message: Descriptive error message

66

- repo: Repository identifier that caused the error

67

"""

68

```

69

70

### Security and File Operation Errors

71

72

Exception for security-related errors during file operations, particularly archive extraction.

73

74

```python { .api }

75

class TarPathTraversalException(Exception):

76

"""

77

Custom exception for path traversal attempts during tar extraction.

78

79

This exception is raised when archive extraction detects potentially

80

malicious archive contents that attempt to write files outside the

81

intended extraction directory.

82

83

Security concerns addressed:

84

- Path traversal attacks using "../" sequences

85

- Absolute path entries in archives

86

- Symbolic link attacks

87

- Archive bombs (deeply nested directories)

88

89

Prevention measures:

90

- All paths are validated before extraction

91

- Relative paths are enforced

92

- Symbolic links are restricted or resolved safely

93

"""

94

95

def __init__(self, message: str, path: str = None):

96

"""

97

Initialize path traversal exception.

98

99

Parameters:

100

- message: Descriptive error message

101

- path: Problematic path that triggered the security check

102

"""

103

```

104

105

## Usage Examples

106

107

### API Credentials Error Handling

108

109

```python

110

from lastversion import latest

111

from lastversion.exceptions import ApiCredentialsError

112

113

def get_version_with_auth_handling(repo):

114

"""Get version with proper authentication error handling."""

115

try:

116

return latest(repo)

117

except ApiCredentialsError as e:

118

print(f"Authentication required for {repo}")

119

print("To resolve:")

120

print("1. Set GITHUB_TOKEN environment variable")

121

print("2. Use personal access token for private repos")

122

print(f"Error details: {e}")

123

return None

124

125

# Example usage

126

version = get_version_with_auth_handling("private-org/private-repo")

127

if version:

128

print(f"Version: {version}")

129

else:

130

print("Could not retrieve version due to authentication issues")

131

```

132

133

### Project Not Found Handling

134

135

```python

136

from lastversion import latest

137

from lastversion.exceptions import BadProjectError

138

139

def find_project_across_platforms(project_name):

140

"""Try to find project across multiple platforms."""

141

platforms = ['github', 'gitlab', 'pip', 'sf']

142

143

for platform in platforms:

144

try:

145

version = latest(project_name, at=platform)

146

if version:

147

print(f"Found {project_name} on {platform}: {version}")

148

return version, platform

149

except BadProjectError:

150

print(f"{project_name} not found on {platform}")

151

continue

152

except Exception as e:

153

print(f"Error checking {platform}: {e}")

154

continue

155

156

raise BadProjectError(f"Project {project_name} not found on any platform")

157

158

# Example usage

159

try:

160

version, platform = find_project_across_platforms("some-project")

161

print(f"Successfully found project on {platform}")

162

except BadProjectError as e:

163

print(f"Project search failed: {e}")

164

```

165

166

### Safe Archive Extraction

167

168

```python

169

from lastversion.utils import extract_file

170

from lastversion.exceptions import TarPathTraversalException

171

import os

172

173

def safe_extract_with_error_handling(url, extract_dir):

174

"""Safely extract archive with comprehensive error handling."""

175

try:

176

# Ensure extraction directory exists

177

os.makedirs(extract_dir, exist_ok=True)

178

179

# Attempt extraction

180

result = extract_file(url, extract_dir)

181

print(f"Successfully extracted to {extract_dir}")

182

return result

183

184

except TarPathTraversalException as e:

185

print(f"Security error: Archive contains unsafe paths")

186

print(f"Blocked path: {e}")

187

print("This archive may be malicious and was not extracted")

188

return None

189

190

except Exception as e:

191

print(f"Extraction failed: {e}")

192

return None

193

194

# Example usage

195

url = "https://example.com/suspicious-archive.tar.gz"

196

result = safe_extract_with_error_handling(url, "/tmp/safe-extract")

197

```

198

199

### Comprehensive Error Handling

200

201

```python

202

from lastversion import latest, has_update

203

from lastversion.exceptions import (

204

ApiCredentialsError,

205

BadProjectError,

206

TarPathTraversalException

207

)

208

from packaging.version import InvalidVersion

209

210

def robust_version_check(repo, current_version=None):

211

"""Comprehensive version checking with full error handling."""

212

try:

213

# Get latest version

214

latest_version = latest(repo)

215

216

if current_version:

217

# Check for updates

218

update = has_update(repo, current_version)

219

return {

220

'latest': latest_version,

221

'current': current_version,

222

'update_available': bool(update),

223

'newer_version': update if update else None,

224

'status': 'success'

225

}

226

else:

227

return {

228

'latest': latest_version,

229

'status': 'success'

230

}

231

232

except ApiCredentialsError as e:

233

return {

234

'status': 'auth_error',

235

'error': str(e),

236

'suggestion': 'Set appropriate API token environment variable'

237

}

238

239

except BadProjectError as e:

240

return {

241

'status': 'not_found',

242

'error': str(e),

243

'suggestion': 'Check repository name and platform'

244

}

245

246

except InvalidVersion as e:

247

return {

248

'status': 'version_error',

249

'error': f"Invalid version format: {e}",

250

'suggestion': 'Check version string format'

251

}

252

253

except Exception as e:

254

return {

255

'status': 'unknown_error',

256

'error': str(e),

257

'suggestion': 'Check network connectivity and repository access'

258

}

259

260

# Example usage

261

result = robust_version_check("kubernetes/kubernetes", "1.28.0")

262

263

if result['status'] == 'success':

264

print(f"Latest: {result['latest']}")

265

if result.get('update_available'):

266

print(f"Update available: {result['current']} → {result['newer_version']}")

267

else:

268

print(f"Error ({result['status']}): {result['error']}")

269

print(f"Suggestion: {result['suggestion']}")

270

```

271

272

### Exception Chaining and Context

273

274

```python

275

from lastversion import latest

276

from lastversion.exceptions import BadProjectError, ApiCredentialsError

277

278

class VersionDiscoveryError(Exception):

279

"""High-level exception for version discovery failures."""

280

pass

281

282

def enterprise_version_check(internal_repo, fallback_repo=None):

283

"""Check enterprise repository with fallback handling."""

284

try:

285

# Try internal/enterprise repository first

286

version = latest(internal_repo, at='github')

287

return version, 'enterprise'

288

289

except ApiCredentialsError as e:

290

print(f"Enterprise auth failed: {e}")

291

292

if fallback_repo:

293

try:

294

# Fallback to public repository

295

version = latest(fallback_repo)

296

return version, 'public_fallback'

297

except BadProjectError as fallback_error:

298

# Chain exceptions to preserve error context

299

raise VersionDiscoveryError(

300

f"Both enterprise and fallback failed"

301

) from fallback_error

302

else:

303

raise VersionDiscoveryError(

304

"Enterprise access failed and no fallback configured"

305

) from e

306

307

except BadProjectError as e:

308

raise VersionDiscoveryError(

309

f"Enterprise repository not found: {internal_repo}"

310

) from e

311

312

# Example usage with exception chaining

313

try:

314

version, source = enterprise_version_check(

315

"internal/secret-project",

316

"public/open-project"

317

)

318

print(f"Version {version} from {source}")

319

320

except VersionDiscoveryError as e:

321

print(f"Version discovery failed: {e}")

322

# Access original exception via __cause__

323

if e.__cause__:

324

print(f"Root cause: {e.__cause__}")

325

```

326

327

### Exception-Based Control Flow

328

329

```python

330

from lastversion import latest

331

from lastversion.exceptions import BadProjectError, ApiCredentialsError

332

333

def get_version_with_retries(repo, max_retries=3):

334

"""Get version with retry logic based on exception types."""

335

import time

336

337

for attempt in range(max_retries):

338

try:

339

return latest(repo)

340

341

except ApiCredentialsError:

342

# Don't retry auth errors

343

raise

344

345

except BadProjectError:

346

# Don't retry not found errors

347

raise

348

349

except Exception as e:

350

# Retry network/temporary errors

351

if attempt < max_retries - 1:

352

wait_time = 2 ** attempt # Exponential backoff

353

print(f"Attempt {attempt + 1} failed: {e}")

354

print(f"Retrying in {wait_time} seconds...")

355

time.sleep(wait_time)

356

else:

357

print(f"All {max_retries} attempts failed")

358

raise

359

360

# Example usage

361

try:

362

version = get_version_with_retries("kubernetes/kubernetes")

363

print(f"Retrieved version: {version}")

364

except (BadProjectError, ApiCredentialsError) as e:

365

print(f"Permanent error: {e}")

366

except Exception as e:

367

print(f"Failed after retries: {e}")

368

```