|
3 | 3 | import logging |
4 | 4 | import os |
5 | 5 | import sys |
| 6 | +import requests |
| 7 | +import urllib3 |
| 8 | +import cgi |
| 9 | + |
6 | 10 | from enum import Enum |
7 | 11 | from pathlib import Path |
8 | 12 | from typing import Any, Callable, Dict, List, Optional, TypedDict, Union, cast |
9 | 13 | from urllib import parse as urlparse |
10 | 14 |
|
11 | | -import requests |
12 | | -import urllib3 |
13 | 15 | from requests.adapters import HTTPAdapter, Retry |
14 | 16 | from requests_toolbelt.multipart.encoder import MultipartEncoderMonitor |
15 | 17 |
|
@@ -76,6 +78,7 @@ class JobTypes(str, Enum): |
76 | 78 | PACKAGE = "package" |
77 | 79 | APPLY_DELTAS = "delta_apply" |
78 | 80 | PROCESS_PROJECTFILE = "process_projectfile" |
| 81 | + CREATE_PROJECT = "create_project" |
79 | 82 |
|
80 | 83 |
|
81 | 84 | class ProjectCollaboratorRole(str, Enum): |
@@ -399,6 +402,75 @@ def get_project( |
399 | 402 |
|
400 | 403 | return cast(Dict, payload) |
401 | 404 |
|
| 405 | + def get_project_seed( |
| 406 | + self, |
| 407 | + project_id: str, |
| 408 | + ) -> Dict[str, Any]: |
| 409 | + """Get project seed data. |
| 410 | +
|
| 411 | + Args: |
| 412 | + project_id: the project data to get seed data for. |
| 413 | +
|
| 414 | + Returns: |
| 415 | + A dictionary containing project seed. |
| 416 | +
|
| 417 | + Example: |
| 418 | + ```python |
| 419 | + client.get_project_seed(project_id) |
| 420 | + ``` |
| 421 | + """ |
| 422 | + payload = self._request_json("GET", f"projects/{project_id}/seed") |
| 423 | + |
| 424 | + return cast(Dict, payload) |
| 425 | + |
| 426 | + def get_project_seed_xlsform( |
| 427 | + self, |
| 428 | + project_id: str, |
| 429 | + destination_dir: str, |
| 430 | + ) -> str | None: |
| 431 | + """Get project seed XLSForm file content. |
| 432 | +
|
| 433 | + Args: |
| 434 | + project_id: the project data to get seed XLSForm for. |
| 435 | +
|
| 436 | + Returns: |
| 437 | + The name of the downloaded XLSForm file. |
| 438 | +
|
| 439 | + Example: |
| 440 | + ```python |
| 441 | + client.get_project_seed_xlsform(project_id) |
| 442 | + ``` |
| 443 | + """ |
| 444 | + |
| 445 | + resp = self._request("GET", f"projects/{project_id}/seed/xlsform") |
| 446 | + |
| 447 | + if resp.status_code != 200: |
| 448 | + return None |
| 449 | + |
| 450 | + content_disposition = resp.headers.get("Content-Disposition", "") |
| 451 | + |
| 452 | + if not content_disposition: |
| 453 | + logger.warning( |
| 454 | + "Response has no `Content-Disposition` header. Skip download of XLSForm file!" |
| 455 | + ) |
| 456 | + |
| 457 | + return None |
| 458 | + |
| 459 | + _value, params = cgi.parse_header(content_disposition) |
| 460 | + filename = params.get("filename") |
| 461 | + |
| 462 | + if not filename: |
| 463 | + logger.warning( |
| 464 | + "Response has no filename in `Content-Disposition` header. Skip download of XLSForm file!" |
| 465 | + ) |
| 466 | + |
| 467 | + return None |
| 468 | + |
| 469 | + path = Path(destination_dir).joinpath(filename) |
| 470 | + path.write_bytes(resp.content) |
| 471 | + |
| 472 | + return str(path) |
| 473 | + |
402 | 474 | def list_remote_files( |
403 | 475 | self, project_id: str, skip_metadata: bool = True |
404 | 476 | ) -> List[Dict[str, Any]]: |
|
0 commit comments