or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

client-operations.mdconfiguration.mdfile-transfer.mdindex.mdresource-management.mdsynchronization.md

synchronization.mddocs/

0

# Synchronization

1

2

Advanced directory synchronization capabilities for keeping local and remote directories in sync. These operations provide intelligent synchronization with support for push, pull, and bidirectional synchronization, handling file comparisons and conflict resolution.

3

4

## Capabilities

5

6

### Push Synchronization

7

8

Uploads missing or changed files from local directory to remote directory, ensuring remote has all local changes.

9

10

```python { .api }

11

def push(self, remote_directory: str, local_directory: str) -> None:

12

"""

13

Upload missing or changed files from local to remote directory.

14

15

Compares local and remote directories, then uploads files that are:

16

- Present locally but missing remotely

17

- Modified locally (newer modification time)

18

- Different in size between local and remote

19

20

Parameters:

21

- remote_directory: str, path to remote directory

22

- local_directory: str, path to local directory

23

24

Raises:

25

- LocalResourceNotFound: if local directory doesn't exist

26

- RemoteParentNotFound: if remote parent directory doesn't exist

27

- NotConnection: if connection to server fails

28

- NotEnoughSpace: if insufficient space on server

29

"""

30

```

31

32

### Pull Synchronization

33

34

Downloads missing or changed files from remote directory to local directory, ensuring local has all remote changes.

35

36

```python { .api }

37

def pull(self, remote_directory: str, local_directory: str) -> None:

38

"""

39

Download missing or changed files from remote to local directory.

40

41

Compares remote and local directories, then downloads files that are:

42

- Present remotely but missing locally

43

- Modified remotely (newer modification time)

44

- Different in size between remote and local

45

46

Parameters:

47

- remote_directory: str, path to remote directory

48

- local_directory: str, path to local directory

49

50

Raises:

51

- RemoteResourceNotFound: if remote directory doesn't exist

52

- LocalResourceNotFound: if local parent directory doesn't exist

53

- NotConnection: if connection to server fails

54

"""

55

```

56

57

### Bidirectional Synchronization

58

59

Synchronizes both directories bidirectionally, ensuring both local and remote directories have the latest version of all files.

60

61

```python { .api }

62

def sync(self, remote_directory: str, local_directory: str) -> None:

63

"""

64

Bidirectionally synchronize local and remote directories.

65

66

Performs both push and pull operations to ensure both directories

67

contain the most recent version of all files. Handles conflicts by

68

preferring the file with the most recent modification time.

69

70

Parameters:

71

- remote_directory: str, path to remote directory

72

- local_directory: str, path to local directory

73

74

Raises:

75

- LocalResourceNotFound: if local directory doesn't exist

76

- RemoteResourceNotFound: if remote directory doesn't exist

77

- NotConnection: if connection to server fails

78

- NotEnoughSpace: if insufficient space on server

79

"""

80

```

81

82

## Usage Examples

83

84

### Basic Push Operation

85

86

```python

87

import webdav.client as wc

88

89

client = wc.Client({

90

'webdav_hostname': "https://webdav.server.com",

91

'webdav_login': "username",

92

'webdav_password': "password"

93

})

94

95

# Push local changes to remote

96

client.push("projects/website/", "~/Development/website/")

97

print("Local changes pushed to remote directory")

98

```

99

100

### Basic Pull Operation

101

102

```python

103

# Pull remote changes to local

104

client.pull("documents/shared/", "~/Documents/shared/")

105

print("Remote changes pulled to local directory")

106

```

107

108

### Full Bidirectional Sync

109

110

```python

111

# Synchronize both directions

112

client.sync("backup/important/", "~/Documents/important/")

113

print("Directories synchronized bidirectionally")

114

```

115

116

### Sync with Error Handling

117

118

```python

119

from webdav.client import WebDavException, NotConnection, LocalResourceNotFound, RemoteResourceNotFound

120

121

def safe_sync(client, remote_dir, local_dir, operation="sync"):

122

try:

123

if operation == "push":

124

client.push(remote_dir, local_dir)

125

print(f"Successfully pushed {local_dir} to {remote_dir}")

126

elif operation == "pull":

127

client.pull(remote_dir, local_dir)

128

print(f"Successfully pulled {remote_dir} to {local_dir}")

129

elif operation == "sync":

130

client.sync(remote_dir, local_dir)

131

print(f"Successfully synchronized {remote_dir} and {local_dir}")

132

133

except LocalResourceNotFound as e:

134

print(f"Local directory not found: {e}")

135

except RemoteResourceNotFound as e:

136

print(f"Remote directory not found: {e}")

137

except NotConnection as e:

138

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

139

except WebDavException as e:

140

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

141

142

# Use safe sync operations

143

safe_sync(client, "projects/webapp/", "~/Development/webapp/", "push")

144

safe_sync(client, "documents/reports/", "~/Documents/reports/", "pull")

145

safe_sync(client, "shared/collaboration/", "~/Shared/collaboration/", "sync")

146

```

147

148

### Periodic Synchronization

149

150

```python

151

import time

152

import schedule

153

154

def sync_directories():

155

"""Periodic sync function"""

156

try:

157

client.sync("backup/documents/", "~/Documents/")

158

print(f"Sync completed at {time.strftime('%Y-%m-%d %H:%M:%S')}")

159

except Exception as e:

160

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

161

162

# Schedule sync every hour

163

schedule.every().hour.do(sync_directories)

164

165

# Or run once daily at 2 AM

166

schedule.every().day.at("02:00").do(sync_directories)

167

168

# Keep scheduler running

169

while True:

170

schedule.run_pending()

171

time.sleep(60)

172

```

173

174

### Project Backup Sync

175

176

```python

177

import os

178

from datetime import datetime

179

180

def backup_project(project_name, local_path):

181

"""Backup project to WebDAV with timestamp"""

182

timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

183

remote_backup_path = f"backups/{project_name}_{timestamp}/"

184

185

try:

186

# Create timestamped backup

187

client.push(remote_backup_path, local_path)

188

print(f"Project {project_name} backed up to {remote_backup_path}")

189

190

# Also maintain current backup

191

current_backup_path = f"backups/{project_name}_current/"

192

client.sync(current_backup_path, local_path)

193

print(f"Current backup updated at {current_backup_path}")

194

195

except Exception as e:

196

print(f"Backup failed for {project_name}: {e}")

197

198

# Backup multiple projects

199

projects = {

200

"webapp": "~/Development/webapp/",

201

"mobile_app": "~/Development/mobile/",

202

"documentation": "~/Documents/project_docs/"

203

}

204

205

for project, path in projects.items():

206

if os.path.exists(os.path.expanduser(path)):

207

backup_project(project, path)

208

else:

209

print(f"Local path not found: {path}")

210

```

211

212

### Collaborative Workflow

213

214

```python

215

def collaborate_workflow(shared_remote_dir, local_work_dir):

216

"""Workflow for collaborative projects"""

217

218

print("Starting collaborative workflow...")

219

220

# 1. Pull latest changes from team

221

print("Pulling latest changes...")

222

client.pull(shared_remote_dir, local_work_dir)

223

224

# 2. Do local work here

225

print("Work on your changes locally...")

226

input("Press Enter when you've completed your local changes...")

227

228

# 3. Pull again to get any new changes before pushing

229

print("Pulling latest changes before push...")

230

client.pull(shared_remote_dir, local_work_dir)

231

232

# 4. Push your changes

233

print("Pushing your changes...")

234

client.push(shared_remote_dir, local_work_dir)

235

236

print("Collaborative workflow completed!")

237

238

# Use collaborative workflow

239

collaborate_workflow("team/project_alpha/", "~/Work/project_alpha/")

240

```

241

242

### Selective Synchronization

243

244

```python

245

import os

246

import fnmatch

247

248

def selective_sync(remote_dir, local_dir, include_patterns=None, exclude_patterns=None):

249

"""

250

Sync with file filtering based on patterns

251

Note: This is a conceptual example - actual implementation would need

252

to be built on top of the basic sync operations

253

"""

254

255

include_patterns = include_patterns or ['*']

256

exclude_patterns = exclude_patterns or []

257

258

print(f"Syncing {local_dir} with {remote_dir}")

259

print(f"Including: {include_patterns}")

260

print(f"Excluding: {exclude_patterns}")

261

262

# Basic sync (in real implementation, you'd filter before sync)

263

client.sync(remote_dir, local_dir)

264

265

# Post-sync cleanup of excluded files (conceptual)

266

if exclude_patterns:

267

print("Note: Full filtering would require custom implementation")

268

269

# Example: Sync only Python files, exclude cache

270

selective_sync(

271

"projects/python_app/",

272

"~/Development/python_app/",

273

include_patterns=['*.py', '*.txt', '*.md'],

274

exclude_patterns=['__pycache__/*', '*.pyc', '.git/*']

275

)

276

```

277

278

### Sync Status Monitoring

279

280

```python

281

import os

282

from datetime import datetime

283

284

class SyncMonitor:

285

def __init__(self, client):

286

self.client = client

287

self.sync_log = []

288

289

def log_sync(self, operation, remote_dir, local_dir, success, error=None):

290

"""Log sync operation result"""

291

log_entry = {

292

'timestamp': datetime.now().isoformat(),

293

'operation': operation,

294

'remote_dir': remote_dir,

295

'local_dir': local_dir,

296

'success': success,

297

'error': str(error) if error else None

298

}

299

self.sync_log.append(log_entry)

300

301

def monitored_sync(self, remote_dir, local_dir, operation="sync"):

302

"""Perform sync with monitoring"""

303

try:

304

print(f"Starting {operation} operation...")

305

306

if operation == "push":

307

self.client.push(remote_dir, local_dir)

308

elif operation == "pull":

309

self.client.pull(remote_dir, local_dir)

310

else:

311

self.client.sync(remote_dir, local_dir)

312

313

self.log_sync(operation, remote_dir, local_dir, True)

314

print(f"{operation.capitalize()} completed successfully")

315

316

except Exception as e:

317

self.log_sync(operation, remote_dir, local_dir, False, e)

318

print(f"{operation.capitalize()} failed: {e}")

319

320

def get_sync_report(self):

321

"""Generate sync status report"""

322

total_ops = len(self.sync_log)

323

successful_ops = sum(1 for log in self.sync_log if log['success'])

324

325

print(f"\nSync Report:")

326

print(f"Total operations: {total_ops}")

327

print(f"Successful: {successful_ops}")

328

print(f"Failed: {total_ops - successful_ops}")

329

330

# Show recent failures

331

recent_failures = [log for log in self.sync_log[-10:] if not log['success']]

332

if recent_failures:

333

print("\nRecent failures:")

334

for failure in recent_failures:

335

print(f" {failure['timestamp']}: {failure['operation']} - {failure['error']}")

336

337

# Use sync monitor

338

monitor = SyncMonitor(client)

339

monitor.monitored_sync("projects/website/", "~/Development/website/", "sync")

340

monitor.monitored_sync("documents/", "~/Documents/", "pull")

341

monitor.get_sync_report()

342

```