or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-api.mdenums-constants.mdindex.mdnotification-components.mdresources.md

resources.mddocs/

0

# Resource Management

1

2

Classes for managing icons, sounds, and file attachments with support for both file paths, URIs, and system-named resources across different platforms.

3

4

## Capabilities

5

6

### Icon

7

8

Icon resource class supporting file paths, URIs, and system-named icons with automatic format conversion and platform compatibility.

9

10

```python { .api }

11

@dataclass(frozen=True)

12

class Icon(Resource):

13

path: Path | None = None

14

"""Local file system path to icon image file"""

15

16

uri: str | None = None

17

"""URI reference to icon resource (file://, http://, etc.)"""

18

19

name: str | None = None

20

"""System icon name (platform-specific named icons)"""

21

22

def as_uri(self) -> str:

23

"""

24

Convert resource to URI string format.

25

26

Returns:

27

str: URI representation of the icon resource

28

29

Raises:

30

AttributeError: If no path, URI, or name is provided

31

"""

32

33

def as_path(self) -> Path:

34

"""

35

Convert resource to Path object.

36

37

Note: URI scheme information is lost during conversion.

38

39

Returns:

40

Path: Path representation of the icon resource

41

42

Raises:

43

AttributeError: If no path or URI is provided

44

"""

45

46

def as_name(self) -> str:

47

"""

48

Get system icon name.

49

50

Returns:

51

str: System icon name

52

53

Raises:

54

AttributeError: If no name is provided

55

"""

56

57

def is_named(self) -> bool:

58

"""

59

Check if icon was initialized with system name.

60

61

Returns:

62

bool: True if using named system icon

63

"""

64

65

def is_file(self) -> bool:

66

"""

67

Check if icon was initialized with file path or URI.

68

69

Returns:

70

bool: True if using file-based icon

71

"""

72

```

73

74

### Sound

75

76

Sound resource class for notification audio with same interface as Icon, supporting file-based and system-named sounds.

77

78

```python { .api }

79

@dataclass(frozen=True)

80

class Sound(Resource):

81

path: Path | None = None

82

"""Local file system path to sound file"""

83

84

uri: str | None = None

85

"""URI reference to sound resource"""

86

87

name: str | None = None

88

"""System sound name (e.g., 'default', 'Tink', 'Blow')"""

89

90

def as_uri(self) -> str:

91

"""Convert sound resource to URI string format"""

92

93

def as_path(self) -> Path:

94

"""Convert sound resource to Path object"""

95

96

def as_name(self) -> str:

97

"""Get system sound name"""

98

99

def is_named(self) -> bool:

100

"""Check if using named system sound"""

101

102

def is_file(self) -> bool:

103

"""Check if using file-based sound"""

104

```

105

106

### Attachment

107

108

File attachment class for notification previews, limited to file paths and URIs (no system-named attachments).

109

110

```python { .api }

111

@dataclass(frozen=True)

112

class Attachment(FileResource):

113

path: Path | None = None

114

"""Local file system path to attachment file"""

115

116

uri: str | None = None

117

"""URI reference to attachment file"""

118

119

def as_uri(self) -> str:

120

"""

121

Convert attachment to URI string format.

122

123

Returns:

124

str: URI representation of the attachment

125

"""

126

127

def as_path(self) -> Path:

128

"""

129

Convert attachment to Path object.

130

131

Returns:

132

Path: Path representation of the attachment

133

"""

134

```

135

136

### Resource Base Classes

137

138

Base classes providing common resource management functionality.

139

140

```python { .api }

141

@dataclass(frozen=True)

142

class FileResource:

143

"""Base class for file-based resources (path or URI only)"""

144

145

path: Path | None = None

146

"""Local file system path"""

147

148

uri: str | None = None

149

"""URI reference to resource"""

150

151

def __post_init__(self) -> None:

152

"""Validates that only one field is set and at least one is provided"""

153

154

def as_uri(self) -> str:

155

"""Convert to URI string format"""

156

157

def as_path(self) -> Path:

158

"""Convert to Path object"""

159

160

@dataclass(frozen=True)

161

class Resource(FileResource):

162

"""Base class for resources supporting both files and system names"""

163

164

name: str | None = None

165

"""System resource name"""

166

167

def as_name(self) -> str:

168

"""Get system resource name"""

169

170

def is_named(self) -> bool:

171

"""Check if using system name"""

172

173

def is_file(self) -> bool:

174

"""Check if using file path or URI"""

175

```

176

177

### Default Resources

178

179

Pre-configured resource constants for common use cases.

180

181

```python { .api }

182

DEFAULT_ICON: Icon

183

"""Default Python icon included with the package"""

184

185

DEFAULT_SOUND: Sound

186

"""Default system notification sound (platform-appropriate)"""

187

```

188

189

## Usage Examples

190

191

### File-based Icons

192

193

```python

194

from desktop_notifier import Icon, DesktopNotifier

195

from pathlib import Path

196

197

# Icon from local file path

198

app_icon = Icon(path=Path("/path/to/app-icon.png"))

199

200

# Icon from URI (local or remote)

201

web_icon = Icon(uri="https://example.com/icon.png")

202

file_uri_icon = Icon(uri="file:///absolute/path/to/icon.png")

203

204

# Use with notifier

205

notifier = DesktopNotifier(app_name="My App", app_icon=app_icon)

206

207

# Or per-notification

208

await notifier.send(

209

title="Custom Icon",

210

message="This notification has a custom icon",

211

icon=Icon(path=Path("/path/to/notification-icon.png"))

212

)

213

```

214

215

### System Named Icons

216

217

```python

218

from desktop_notifier import Icon

219

220

# Common system icons (platform-dependent availability)

221

info_icon = Icon(name="info")

222

warning_icon = Icon(name="warning")

223

error_icon = Icon(name="error")

224

mail_icon = Icon(name="mail-unread")

225

226

# Check what type of icon

227

print(f"Using named icon: {info_icon.is_named()}") # True

228

print(f"Using file icon: {info_icon.is_file()}") # False

229

230

# Linux-specific system icons

231

linux_icons = [

232

Icon(name="dialog-information"),

233

Icon(name="dialog-warning"),

234

Icon(name="dialog-error"),

235

Icon(name="emblem-important"),

236

Icon(name="call-start"),

237

Icon(name="call-stop")

238

]

239

```

240

241

### Sound Resources

242

243

```python

244

from desktop_notifier import Sound, DEFAULT_SOUND

245

246

# System named sounds

247

default_sound = DEFAULT_SOUND # Sound(name="default")

248

custom_system_sound = Sound(name="Tink") # macOS system sound

249

alert_sound = Sound(name="Blow") # Another macOS sound

250

251

# File-based sounds

252

custom_sound = Sound(path=Path("/path/to/notification.wav"))

253

remote_sound = Sound(uri="https://example.com/chime.mp3")

254

255

# Use with notifications

256

await notifier.send(

257

title="Sound Test",

258

message="This plays a custom sound",

259

sound=custom_sound

260

)

261

262

# Platform-specific sound names

263

if platform.system() == "Darwin": # macOS

264

sounds = [

265

Sound(name="Basso"),

266

Sound(name="Blow"),

267

Sound(name="Bottle"),

268

Sound(name="Frog"),

269

Sound(name="Funk"),

270

Sound(name="Glass"),

271

Sound(name="Hero"),

272

Sound(name="Morse"),

273

Sound(name="Ping"),

274

Sound(name="Pop"),

275

Sound(name="Purr"),

276

Sound(name="Sosumi"),

277

Sound(name="Submarine"),

278

Sound(name="Tink")

279

]

280

elif platform.system() == "Windows":

281

sounds = [

282

Sound(name="ms-winsoundevent:Notification.Default"),

283

Sound(name="ms-winsoundevent:Notification.IM"),

284

Sound(name="ms-winsoundevent:Notification.Mail"),

285

Sound(name="ms-winsoundevent:Notification.Reminder"),

286

Sound(name="ms-winsoundevent:Notification.SMS")

287

]

288

```

289

290

### File Attachments

291

292

```python

293

from desktop_notifier import Attachment

294

295

# Image attachments for preview

296

image_attachment = Attachment(path=Path("/photos/vacation.jpg"))

297

screenshot = Attachment(uri="file:///tmp/screenshot.png")

298

299

# Document attachments

300

pdf_doc = Attachment(path=Path("/documents/report.pdf"))

301

text_file = Attachment(uri="file:///logs/error.log")

302

303

# Use with notifications

304

await notifier.send(

305

title="Photo Shared",

306

message="New vacation photos are ready",

307

attachment=image_attachment,

308

on_clicked=lambda: print("User wants to view photos")

309

)

310

311

# Platform support varies for attachment types:

312

# - macOS: Most image formats, PDFs, some video formats

313

# - Windows: Images (PNG, JPG, GIF), some video formats

314

# - Linux: Depends on notification daemon implementation

315

```

316

317

### Resource Conversion and Validation

318

319

```python

320

from desktop_notifier import Icon, Sound, Attachment

321

from pathlib import Path

322

323

# Resource conversion utilities

324

icon = Icon(path=Path("/app/icon.png"))

325

326

# Convert between formats

327

icon_uri = icon.as_uri() # "file:///app/icon.png"

328

icon_path = icon.as_path() # Path("/app/icon.png")

329

330

# Type checking

331

print(f"Is file-based: {icon.is_file()}") # True

332

print(f"Is named: {icon.is_named()}") # False

333

334

# System named resource

335

system_icon = Icon(name="dialog-information")

336

print(f"System name: {system_icon.as_name()}") # "dialog-information"

337

338

# Validation - only one field can be set

339

try:

340

invalid_icon = Icon(path=Path("/icon.png"), name="warning")

341

# Raises RuntimeError: "Only a single field can be set"

342

except RuntimeError as e:

343

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

344

345

try:

346

empty_icon = Icon()

347

# Raises RuntimeError: "Either of ['path', 'uri', 'name'] must be set"

348

except RuntimeError as e:

349

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

350

```

351

352

### Dynamic Resource Selection

353

354

```python

355

import platform

356

from desktop_notifier import Icon, Sound

357

from pathlib import Path

358

359

def get_platform_appropriate_icon(icon_type: str) -> Icon:

360

"""Select best icon based on platform capabilities"""

361

if platform.system() == "Linux":

362

# Use freedesktop.org standard icon names

363

icon_map = {

364

"info": "dialog-information",

365

"warning": "dialog-warning",

366

"error": "dialog-error"

367

}

368

return Icon(name=icon_map.get(icon_type, "dialog-information"))

369

370

elif platform.system() in ["Darwin", "Windows"]:

371

# Use custom app icons on macOS/Windows

372

icon_path = Path(f"assets/icons/{icon_type}.png")

373

if icon_path.exists():

374

return Icon(path=icon_path)

375

else:

376

return Icon(name=icon_type) # Fallback to system

377

378

else:

379

# Fallback for other platforms

380

return Icon(name=icon_type)

381

382

def get_platform_appropriate_sound(sound_type: str) -> Sound:

383

"""Select best sound based on platform"""

384

if platform.system() == "Darwin":

385

sound_map = {

386

"success": "Tink",

387

"warning": "Basso",

388

"error": "Sosumi",

389

"message": "Ping"

390

}

391

return Sound(name=sound_map.get(sound_type, "default"))

392

393

elif platform.system() == "Windows":

394

sound_map = {

395

"success": "ms-winsoundevent:Notification.Default",

396

"message": "ms-winsoundevent:Notification.IM"

397

}

398

return Sound(name=sound_map.get(sound_type, "default"))

399

400

else:

401

return Sound(name="default")

402

403

# Usage

404

info_icon = get_platform_appropriate_icon("info")

405

success_sound = get_platform_appropriate_sound("success")

406

407

await notifier.send(

408

title="Platform Optimized",

409

message="This uses the best icon and sound for your OS",

410

icon=info_icon,

411

sound=success_sound

412

)

413

```