Coverage for gws-app/gws/plugin/qfieldcloud/api.py: 100%

204 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-23 20:06 +0200

1"""Data classes for the QFieldCloud API, based on its ``swagger.yaml``.""" 

2 

3from datetime import datetime 

4from typing import Optional 

5 

6import gws 

7 

8class JobStatusEnum(gws.Enum): 

9 """Status of a job.""" 

10 

11 pending = 'pending' 

12 queued = 'queued' 

13 started = 'started' 

14 finished = 'finished' 

15 stopped = 'stopped' 

16 failed = 'failed' 

17 

18 

19class LastStatusEnum(gws.Enum): 

20 """Last status of a delta.""" 

21 

22 pending = 'pending' 

23 started = 'started' 

24 applied = 'applied' 

25 conflict = 'conflict' 

26 not_applied = 'not_applied' 

27 error = 'error' 

28 ignored = 'ignored' 

29 unpermitted = 'unpermitted' 

30 

31 

32class OrganizationMemberRoleEnum(gws.Enum): 

33 """Role of an organization member.""" 

34 

35 admin = 'admin' 

36 member = 'member' 

37 

38 

39class ProjectCollaboratorRoleEnum(gws.Enum): 

40 """Role of a project collaborator.""" 

41 

42 admin = 'admin' 

43 manager = 'manager' 

44 editor = 'editor' 

45 reporter = 'reporter' 

46 reader = 'reader' 

47 

48 

49class ProjectStatusEnum(gws.Enum): 

50 """Status of a project.""" 

51 

52 ok = 'ok' 

53 busy = 'busy' 

54 failed = 'failed' 

55 

56 

57class TypeEnum(gws.Enum): 

58 """Type of a job.""" 

59 

60 package = 'package' 

61 delta_apply = 'delta_apply' 

62 process_projectfile = 'process_projectfile' 

63 

64 

65# Data Classes 

66 

67 

68class Login(gws.Data): 

69 """Login credentials.""" 

70 

71 password: str 

72 """Password.""" 

73 username: Optional[str] 

74 """User name.""" 

75 email: Optional[str] 

76 """Email address.""" 

77 

78 

79class CompleteUser(gws.Data): 

80 """Full information about the authenticated user.""" 

81 

82 username: str 

83 """User name.""" 

84 type: int 

85 """User type, see ``UserType``.""" 

86 full_name: str 

87 """Full name.""" 

88 avatar_url: str 

89 """URL of the avatar image.""" 

90 email: Optional[str] 

91 """Email address.""" 

92 first_name: Optional[str] 

93 """First name.""" 

94 last_name: Optional[str] 

95 """Last name.""" 

96 

97 

98class PublicInfoUser(gws.Data): 

99 """Public information about a user.""" 

100 

101 username: str 

102 """User name.""" 

103 type: int 

104 """User type, see ``UserType``.""" 

105 full_name: str 

106 """Full name.""" 

107 avatar_url: str 

108 """URL of the avatar image.""" 

109 username_display: str 

110 """User name for display.""" 

111 

112 

113class DeltaFeature(gws.Data): 

114 """Feature state in a delta, before or after the change.""" 

115 

116 attributes: dict 

117 """Feature attributes.""" 

118 geometry: Optional[str] 

119 """Geometry as WKT, only present if the geometry has changed.""" 

120 files_sha256: Optional[dict] 

121 """Checksums of attached files by file name.""" 

122 

123 

124class Delta(gws.Data): 

125 """A single change, as sent by QField in a delta payload.""" 

126 

127 uuid: str 

128 """Delta id.""" 

129 clientId: str 

130 """Id of the local export on the device.""" 

131 exportId: str 

132 """Id of the package export.""" 

133 localLayerId: str 

134 """Id of the layer in the packaged QGIS project.""" 

135 localLayerName: str 

136 """Name of the layer in the packaged QGIS project.""" 

137 localLayerCrs: str 

138 """CRS of the layer in the packaged QGIS project.""" 

139 localPk: str 

140 """Primary key of the feature in the packaged layer.""" 

141 sourceLayerId: str 

142 """Id of the layer in the source QGIS project.""" 

143 sourcePk: str 

144 """Primary key of the feature in the source layer.""" 

145 method: str 

146 """Change type, ``create``, ``patch`` or ``delete``.""" 

147 new: Optional[DeltaFeature] 

148 """Feature after the change, ``None`` for deletions.""" 

149 old: Optional[DeltaFeature] 

150 """Feature before the change, ``None`` for creations.""" 

151 

152 

153class DeltaStatusType(gws.Enum): 

154 """Status of a delta.""" 

155 

156 pending = 'STATUS_PENDING' 

157 busy = 'STATUS_BUSY' 

158 applied = 'STATUS_APPLIED' 

159 conflict = 'STATUS_CONFLICT' 

160 not_applied = 'STATUS_NOT_APPLIED' 

161 error = 'STATUS_ERROR' 

162 ignored = 'STATUS_IGNORED' 

163 unpermitted = 'STATUS_UNPERMITTED' 

164 

165 

166class Job(gws.Data): 

167 """A server job, e.g. packaging.""" 

168 

169 type: TypeEnum 

170 """Job type.""" 

171 id: str 

172 """Job id.""" 

173 created_at: datetime 

174 """Creation time.""" 

175 created_by: int 

176 """Id of the user who created the job.""" 

177 project_id: str 

178 """Project id.""" 

179 status: JobStatusEnum 

180 """Job status.""" 

181 updated_at: datetime 

182 """Last update time.""" 

183 started_at: Optional[datetime] 

184 """Start time.""" 

185 finished_at: Optional[datetime] 

186 """Finish time.""" 

187 

188 

189class Organization(gws.Data): 

190 """An organization.""" 

191 

192 username: str 

193 """Organization name.""" 

194 type: int 

195 """User type, see ``UserType``.""" 

196 avatar_url: str 

197 """URL of the avatar image.""" 

198 members: str 

199 """Organization members.""" 

200 organization_owner: str 

201 """Owner of the organization.""" 

202 membership_role: str 

203 """Role of the current user in the organization.""" 

204 membership_role_origin: str 

205 """Origin of the membership role.""" 

206 membership_is_public: bool 

207 """Whether the membership is public.""" 

208 teams: list[str] 

209 """Organization teams.""" 

210 email: Optional[str] 

211 """Email address.""" 

212 

213 

214class OrganizationMember(gws.Data): 

215 """A member of an organization.""" 

216 

217 organization: str 

218 """Organization name.""" 

219 member: str 

220 """Member user name.""" 

221 role: OrganizationMemberRoleEnum 

222 """Member role.""" 

223 is_public: Optional[bool] 

224 """Whether the membership is public.""" 

225 

226 

227class Project(gws.Data): 

228 """A QField Cloud project.""" 

229 

230 id: str 

231 """Project id.""" 

232 name: str 

233 """Project name.""" 

234 owner: str 

235 """Project owner.""" 

236 created_at: datetime 

237 """Creation time.""" 

238 updated_at: datetime 

239 """Last update time.""" 

240 can_repackage: bool 

241 """Whether the project can be packaged again.""" 

242 needs_repackaging: bool 

243 """Whether the project must be packaged again.""" 

244 status: ProjectStatusEnum 

245 """Project status.""" 

246 user_role: str 

247 """Role of the current user in the project.""" 

248 user_role_origin: str 

249 """Origin of the user role.""" 

250 is_shared_datasets_project: bool 

251 """Whether this is a shared datasets project.""" 

252 is_attachment_download_on_demand: bool 

253 """Whether attachments are downloaded on demand.""" 

254 description: Optional[str] 

255 """Project description.""" 

256 private: Optional[bool] 

257 """Whether the project is private.""" 

258 is_public: Optional[bool] 

259 """Whether the project is public.""" 

260 data_last_packaged_at: Optional[datetime] 

261 """Time of the last packaging.""" 

262 data_last_updated_at: Optional[datetime] 

263 """Time of the last data update.""" 

264 shared_datasets_project_id: Optional[str] 

265 """Id of the shared datasets project.""" 

266 is_featured: Optional[bool] 

267 """Whether the project is featured.""" 

268 

269 

270class ProjectCollaborator(gws.Data): 

271 """A collaborator of a project.""" 

272 

273 collaborator: str 

274 """Collaborator user name.""" 

275 project_id: str 

276 """Project id.""" 

277 created_by: str 

278 """User who added the collaborator.""" 

279 updated_by: str 

280 """User who last updated the collaborator.""" 

281 created_at: datetime 

282 """Creation time.""" 

283 updated_at: datetime 

284 """Last update time.""" 

285 role: Optional[ProjectCollaboratorRoleEnum] 

286 """Collaborator role.""" 

287 

288 

289class Team(gws.Data): 

290 """A team in an organization.""" 

291 

292 team: str 

293 """Team name.""" 

294 organization: str 

295 """Organization name.""" 

296 members: list[str] 

297 """Team members.""" 

298 

299 

300class TeamMember(gws.Data): 

301 """A member of a team.""" 

302 

303 member: str 

304 """Member user name.""" 

305 

306 

307## not in swagger.yaml but used in code 

308 

309 

310class Package(gws.Data): 

311 """A project package, as listed for download.""" 

312 

313 files: list[dict] 

314 """Package files.""" 

315 layers: list[dict] 

316 """Package layers.""" 

317 status: JobStatusEnum 

318 """Packaging status.""" 

319 package_id: str 

320 """Package id.""" 

321 packaged_at: datetime 

322 """Packaging time.""" 

323 data_last_updated_at: datetime 

324 """Time of the last data update.""" 

325 

326 

327class AuthProvider(gws.Data): 

328 """An authentication provider offered to the client.""" 

329 

330 type: str 

331 """Provider type.""" 

332 id: str 

333 """Provider id.""" 

334 name: str 

335 """Provider name for display.""" 

336 

337 

338class UserType(gws.Enum): 

339 """Type of a user account.""" 

340 

341 person = 1 

342 organization = 2 

343 team = 3 

344 

345 

346class AuthToken(gws.Data): 

347 """Authentication token and user information returned on login.""" 

348 

349 token: str 

350 """Session token.""" 

351 expires_at: datetime 

352 """Expiration time.""" 

353 username: str 

354 """User name.""" 

355 type: UserType 

356 """User type.""" 

357 full_name: str 

358 """Full name.""" 

359 avatar_url: str 

360 """URL of the avatar image.""" 

361 email: Optional[str] 

362 """Email address.""" 

363 first_name: Optional[str] 

364 """First name.""" 

365 last_name: Optional[str] 

366 """Last name.""" 

367 

368 

369class ServerInfo(gws.Data): 

370 """Server information.""" 

371 

372 version: str 

373 """Server version.""" 

374 auth_providers: list[AuthProvider] 

375 """Available authentication providers.""" 

376 signup_url: str 

377 """URL of the signup page.""" 

378 whitelabel: dict 

379 """Branding options.""" 

380 

381 

382class Status(gws.Data): 

383 """Server status.""" 

384 

385 version: str 

386 """Server version.""" 

387 database: str 

388 """Database status.""" 

389 storage: str 

390 """Storage status.""" 

391 status_page_url: Optional[str] 

392 """URL of the status page.""" 

393 incident_message: Optional[str] 

394 """Incident message.""" 

395 incident_timestamp_utc: Optional[str] 

396 """Incident time.""" 

397 maintenance_message: Optional[str] 

398 """Maintenance message.""" 

399 maintenance_start_timestamp_utc: Optional[str] 

400 """Maintenance start time.""" 

401 maintenance_end_timestamp_utc: Optional[str] 

402 """Maintenance end time.""" 

403 

404 

405class Subscription(gws.Data): 

406 """Subscription of a user.""" 

407 

408 plan_display_name: str 

409 """Plan name for display.""" 

410 active_storage_total_bytes: int 

411 """Total storage available, in bytes.""" 

412 storage_used_bytes: int 

413 """Storage used, in bytes.""" 

414 plan_storage_threshold_warning_bytes: int 

415 """Storage warning threshold, in bytes.""" 

416 plan_storage_threshold_critical_bytes: int 

417 """Storage critical threshold, in bytes.""" 

418 status: str 

419 """Subscription status.""" 

420 

421 

422class PostJobPayload(gws.Data): 

423 """Payload of a job creation request.""" 

424 

425 type: TypeEnum 

426 """Job type.""" 

427 project_id: str 

428 """Project id.""" 

429 

430 

431class DeltasPayload(gws.Data): 

432 """A delta payload (delta file) sent by QField.""" 

433 

434 deltas: list[Delta] 

435 """List of deltas.""" 

436 files: list[dict] 

437 """List of files.""" 

438 id: str 

439 """Payload id.""" 

440 project: str 

441 """Project id.""" 

442 version: str 

443 """Delta file format version.""" 

444 

445 

446class PackageFile(gws.Data): 

447 """A file in a package.""" 

448 

449 name: str 

450 """File name, relative to the package.""" 

451 size: int 

452 """File size in bytes.""" 

453 uploaded_at: str 

454 """Upload time.""" 

455 is_attachment: bool 

456 """Whether the file is an attachment.""" 

457 md5sum: str 

458 """MD5 checksum, in the format QField expects.""" 

459 last_modified: str 

460 """Modification time.""" 

461 sha256: str 

462 """SHA-256 checksum."""