or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-interface.mdindex.mdproject-management.mdpython-api.mdutilities.md

project-management.mddocs/

0

# Project Management

1

2

Project, storage, file, and folder management classes for navigating and manipulating OSF project structures. These classes provide the core functionality for working with OSF data and files.

3

4

## Capabilities

5

6

### Project Class

7

8

Represents an OSF project containing multiple storage providers and associated metadata.

9

10

```python { .api }

11

class Project:

12

def storage(self, provider='osfstorage'):

13

"""

14

Return specific storage provider.

15

16

Args:

17

provider (str): Storage provider name (default: 'osfstorage')

18

Options: 'osfstorage', 'github', 'figshare', 'googledrive', 'owncloud'

19

20

Returns:

21

Storage: Storage instance for the specified provider

22

23

Raises:

24

RuntimeError: If project has no storage provider with the given name

25

"""

26

27

@property

28

def storages(self):

29

"""

30

Iterate over all storage providers for this project.

31

32

Yields:

33

Storage: Storage instances for each available provider

34

"""

35

36

@property

37

def id(self):

38

"""Project ID (GUID)."""

39

40

@property

41

def title(self):

42

"""Project title."""

43

44

@property

45

def description(self):

46

"""Project description."""

47

48

@property

49

def date_created(self):

50

"""Project creation date."""

51

52

@property

53

def date_modified(self):

54

"""Project last modified date."""

55

```

56

57

### Storage Class

58

59

Represents a storage provider within a project, such as OSF Storage, GitHub, Figshare, etc.

60

61

```python { .api }

62

class Storage:

63

def create_file(self, path, fp, force=False, update=False):

64

"""

65

Store a new file at path in this storage.

66

67

Args:

68

path (str): Full path where to store the file

69

fp (file): File descriptor opened in 'rb' mode

70

force (bool): Force overwrite of existing file

71

update (bool): Overwrite existing file only if files differ

72

73

Raises:

74

ValueError: If file not opened in binary mode

75

FileExistsError: If file exists and neither force nor update is True

76

RuntimeError: If upload fails or file cannot be created/updated

77

"""

78

79

def create_folder(self, name, exist_ok=False):

80

"""

81

Create a new folder.

82

83

Args:

84

name (str): Folder name

85

exist_ok (bool): Don't raise exception if folder already exists

86

87

Returns:

88

Folder: Created folder instance

89

90

Raises:

91

FolderExistsException: If folder exists and exist_ok is False

92

RuntimeError: If folder creation fails

93

"""

94

95

@property

96

def files(self):

97

"""

98

Iterate over all files in this storage.

99

100

Recursively lists all files in all subfolders.

101

102

Yields:

103

File: File instances for each file in storage

104

"""

105

106

@property

107

def folders(self):

108

"""

109

Iterate over top-level folders in this storage.

110

111

Yields:

112

Folder: Folder instances for each top-level folder

113

"""

114

115

@property

116

def id(self):

117

"""Storage ID."""

118

119

@property

120

def name(self):

121

"""Storage name."""

122

123

@property

124

def provider(self):

125

"""Storage provider name ('osfstorage', 'github', etc.)."""

126

127

@property

128

def path(self):

129

"""Storage path."""

130

131

@property

132

def node(self):

133

"""Associated project node."""

134

```

135

136

### File Class

137

138

Represents an individual file in OSF storage with download, update, and deletion capabilities.

139

140

```python { .api }

141

class File:

142

def write_to(self, fp):

143

"""

144

Write contents of this file to a local file.

145

146

Args:

147

fp (file): File pointer opened for writing in binary mode

148

149

Raises:

150

ValueError: If file not opened in binary mode

151

RuntimeError: If download fails

152

"""

153

154

def remove(self):

155

"""

156

Remove this file from remote storage.

157

158

Raises:

159

RuntimeError: If deletion fails

160

"""

161

162

def update(self, fp):

163

"""

164

Update the remote file from a local file.

165

166

Args:

167

fp (file): File pointer opened for reading in binary mode

168

169

Raises:

170

ValueError: If file not opened in binary mode

171

RuntimeError: If update fails

172

"""

173

174

@property

175

def id(self):

176

"""File ID."""

177

178

@property

179

def name(self):

180

"""File name."""

181

182

@property

183

def path(self):

184

"""Materialized file path."""

185

186

@property

187

def osf_path(self):

188

"""OSF internal path."""

189

190

@property

191

def size(self):

192

"""File size in bytes."""

193

194

@property

195

def date_created(self):

196

"""File creation date."""

197

198

@property

199

def date_modified(self):

200

"""File last modified date."""

201

202

@property

203

def hashes(self):

204

"""

205

Dictionary of file hashes.

206

207

Returns:

208

dict: Hash values keyed by algorithm ('md5', 'sha256', etc.)

209

"""

210

```

211

212

### Folder Class

213

214

Represents a folder in OSF storage with file and subfolder access capabilities.

215

216

```python { .api }

217

class Folder:

218

def create_folder(self, name, exist_ok=False):

219

"""

220

Create a subfolder within this folder.

221

222

Args:

223

name (str): Subfolder name

224

exist_ok (bool): Don't raise exception if folder already exists

225

226

Returns:

227

Folder: Created subfolder instance

228

229

Raises:

230

FolderExistsException: If folder exists and exist_ok is False

231

RuntimeError: If folder creation fails

232

"""

233

234

@property

235

def files(self):

236

"""

237

Iterate over files in this folder.

238

239

Unlike Storage.files, this does not recursively find all files.

240

Only lists files directly in this folder.

241

242

Yields:

243

File: File instances for each file in folder

244

"""

245

246

@property

247

def folders(self):

248

"""

249

Iterate over subfolders in this folder.

250

251

Yields:

252

Folder: Folder instances for each subfolder

253

"""

254

255

@property

256

def id(self):

257

"""Folder ID."""

258

259

@property

260

def name(self):

261

"""Folder name."""

262

263

@property

264

def path(self):

265

"""Materialized folder path."""

266

267

@property

268

def osf_path(self):

269

"""OSF internal path."""

270

271

@property

272

def date_created(self):

273

"""Folder creation date."""

274

275

@property

276

def date_modified(self):

277

"""Folder last modified date."""

278

```

279

280

## Usage Examples

281

282

### Working with Projects

283

284

```python

285

from osfclient import OSF

286

287

osf = OSF(token='your_token')

288

project = osf.project('project_id')

289

290

print(f"Project: {project.title}")

291

print(f"Created: {project.date_created}")

292

print(f"Description: {project.description}")

293

294

# List all storage providers

295

for storage in project.storages:

296

print(f"Storage: {storage.name} ({storage.provider})")

297

298

# Get default OSF Storage

299

osf_storage = project.storage() # defaults to 'osfstorage'

300

301

# Get specific storage provider

302

try:

303

github_storage = project.storage('github')

304

print(f"GitHub storage available: {github_storage.name}")

305

except RuntimeError:

306

print("No GitHub storage configured for this project")

307

```

308

309

### File Operations

310

311

```python

312

# List all files recursively

313

storage = project.storage()

314

for file in storage.files:

315

print(f"File: {file.path}")

316

print(f" Size: {file.size} bytes")

317

print(f" Modified: {file.date_modified}")

318

print(f" MD5: {file.hashes.get('md5', 'N/A')}")

319

320

# Download a specific file

321

target_file = next((f for f in storage.files if f.name == 'data.csv'), None)

322

if target_file:

323

with open('local_data.csv', 'wb') as local_file:

324

target_file.write_to(local_file)

325

print("File downloaded successfully")

326

327

# Upload a new file

328

with open('local_upload.txt', 'rb') as upload_file:

329

storage.create_file('remote_folder/uploaded_file.txt', upload_file)

330

print("File uploaded successfully")

331

332

# Update existing file

333

existing_file = next((f for f in storage.files if f.name == 'update_me.txt'), None)

334

if existing_file:

335

with open('new_content.txt', 'rb') as content:

336

existing_file.update(content)

337

print("File updated successfully")

338

339

# Delete a file

340

file_to_delete = next((f for f in storage.files if f.name == 'delete_me.txt'), None)

341

if file_to_delete:

342

file_to_delete.remove()

343

print("File deleted successfully")

344

```

345

346

### Folder Operations

347

348

```python

349

# Create folder structure

350

storage = project.storage()

351

main_folder = storage.create_folder('data_analysis', exist_ok=True)

352

sub_folder = main_folder.create_folder('raw_data', exist_ok=True)

353

354

# Navigate folder structure

355

for folder in storage.folders:

356

print(f"Top-level folder: {folder.name}")

357

for subfolder in folder.folders:

358

print(f" Subfolder: {subfolder.name}")

359

for file in folder.files:

360

print(f" File: {file.name}")

361

362

# Upload file to specific folder structure

363

with open('experiment_data.csv', 'rb') as data_file:

364

storage.create_file('data_analysis/raw_data/experiment_data.csv', data_file)

365

```

366

367

### Handling Upload Conflicts

368

369

```python

370

with open('existing_file.txt', 'rb') as upload_file:

371

try:

372

# This will fail if file already exists

373

storage.create_file('path/existing_file.txt', upload_file)

374

except FileExistsError:

375

print("File already exists")

376

377

# Force overwrite

378

upload_file.seek(0) # Reset file pointer

379

storage.create_file('path/existing_file.txt', upload_file, force=True)

380

print("File overwritten")

381

382

# Or use update mode (only overwrites if files differ)

383

with open('maybe_changed.txt', 'rb') as upload_file:

384

storage.create_file('path/maybe_changed.txt', upload_file, update=True)

385

print("File uploaded or updated if changed")

386

```