|
7 | 7 |
|
8 | 8 | from gooddata_api_client.exceptions import NotFoundException |
9 | 9 |
|
| 10 | +# CSV upload related imports from generated API client |
| 11 | +from gooddata_api_client.model.analyze_csv_request import AnalyzeCsvRequest |
| 12 | +from gooddata_api_client.model.analyze_csv_request_item import AnalyzeCsvRequestItem |
| 13 | +from gooddata_api_client.model.analyze_csv_response import AnalyzeCsvResponse |
| 14 | +from gooddata_api_client.model.delete_files_request import DeleteFilesRequest |
| 15 | +from gooddata_api_client.model.import_csv_request import ImportCsvRequest |
| 16 | +from gooddata_api_client.model.import_csv_request_table import ImportCsvRequestTable |
| 17 | +from gooddata_api_client.model.import_csv_request_table_source import ImportCsvRequestTableSource |
| 18 | +from gooddata_api_client.model.import_csv_request_table_source_config import ImportCsvRequestTableSourceConfig |
| 19 | + |
10 | 20 | from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase |
11 | 21 | from gooddata_sdk.catalog.data_source.action_model.requests.ldm_request import ( |
12 | 22 | CatalogGenerateLdmRequest, |
@@ -504,6 +514,110 @@ def test_data_sources_connection( |
504 | 514 | message.append(f"Test connection for data source id {k} ended with the following error {v}.") |
505 | 515 | raise ValueError("\n".join(message)) |
506 | 516 |
|
| 517 | + # CSV upload methods are listed below |
| 518 | + |
| 519 | + def staging_upload(self, csv_file: Path) -> str: |
| 520 | + """Upload a CSV file to the staging area. |
| 521 | +
|
| 522 | + Args: |
| 523 | + csv_file (Path): |
| 524 | + Path to the CSV file to upload. |
| 525 | +
|
| 526 | + Returns: |
| 527 | + str: |
| 528 | + Location string referencing the uploaded file in staging. |
| 529 | + """ |
| 530 | + with open(csv_file, "rb") as f: |
| 531 | + response = self._actions_api.staging_upload(file=f) |
| 532 | + return response["location"] |
| 533 | + |
| 534 | + def analyze_csv(self, location: str) -> AnalyzeCsvResponse: |
| 535 | + """Analyze an uploaded CSV file in the staging area. |
| 536 | +
|
| 537 | + Returns column metadata, detected types, and a config object |
| 538 | + that can be passed directly to import_csv. |
| 539 | +
|
| 540 | + Args: |
| 541 | + location (str): |
| 542 | + Location string returned by staging_upload. |
| 543 | +
|
| 544 | + Returns: |
| 545 | + AnalyzeCsvResponse: |
| 546 | + Analysis result with columns, preview data, and config. |
| 547 | + """ |
| 548 | + request = AnalyzeCsvRequest(analyze_requests=[AnalyzeCsvRequestItem(location=location)]) |
| 549 | + responses = self._actions_api.analyze_csv(request, _check_return_type=False) |
| 550 | + return responses[0] |
| 551 | + |
| 552 | + def import_csv( |
| 553 | + self, |
| 554 | + data_source_id: str, |
| 555 | + table_name: str, |
| 556 | + location: str, |
| 557 | + config: dict[str, Any] | None = None, |
| 558 | + ) -> None: |
| 559 | + """Import a CSV file from staging into a GDSTORAGE data source. |
| 560 | +
|
| 561 | + Args: |
| 562 | + data_source_id (str): |
| 563 | + Data source identification string. |
| 564 | + table_name (str): |
| 565 | + Name for the table to create or replace. |
| 566 | + location (str): |
| 567 | + Location string returned by staging_upload. |
| 568 | + config (Optional[dict[str, Any]]): |
| 569 | + Source config dict, typically from analyze_csv response. |
| 570 | + Passed as ImportCsvRequestTableSourceConfig kwargs. |
| 571 | +
|
| 572 | + Returns: |
| 573 | + None |
| 574 | + """ |
| 575 | + source_kwargs: dict[str, Any] = {"location": location} |
| 576 | + if config: |
| 577 | + source_kwargs["config"] = ImportCsvRequestTableSourceConfig(**config) |
| 578 | + source = ImportCsvRequestTableSource(**source_kwargs) |
| 579 | + table = ImportCsvRequestTable(name=table_name, source=source) |
| 580 | + request = ImportCsvRequest(tables=[table]) |
| 581 | + self._actions_api.import_csv(data_source_id, request) |
| 582 | + |
| 583 | + def delete_csv_files(self, data_source_id: str, file_names: list[str]) -> None: |
| 584 | + """Delete files from a GDSTORAGE data source. |
| 585 | +
|
| 586 | + Args: |
| 587 | + data_source_id (str): |
| 588 | + Data source identification string. |
| 589 | + file_names (list[str]): |
| 590 | + List of file names to delete. |
| 591 | +
|
| 592 | + Returns: |
| 593 | + None |
| 594 | + """ |
| 595 | + request = DeleteFilesRequest(file_names=file_names) |
| 596 | + self._actions_api.delete_files(data_source_id, request) |
| 597 | + |
| 598 | + def upload_csv(self, data_source_id: str, csv_file: Path, table_name: str) -> None: |
| 599 | + """Upload a CSV file and import it into a GDSTORAGE data source. |
| 600 | +
|
| 601 | + Convenience method that orchestrates the full flow: |
| 602 | + staging_upload → analyze_csv → import_csv → register_upload_notification. |
| 603 | +
|
| 604 | + Args: |
| 605 | + data_source_id (str): |
| 606 | + Data source identification string for a GDSTORAGE data source. |
| 607 | + csv_file (Path): |
| 608 | + Path to the CSV file to upload. |
| 609 | + table_name (str): |
| 610 | + Name for the table to create or replace in the data source. |
| 611 | +
|
| 612 | + Returns: |
| 613 | + None |
| 614 | + """ |
| 615 | + location = self.staging_upload(csv_file) |
| 616 | + analysis = self.analyze_csv(location) |
| 617 | + config = analysis.to_dict().get("config") |
| 618 | + self.import_csv(data_source_id, table_name, location, config=config) |
| 619 | + self.register_upload_notification(data_source_id) |
| 620 | + |
507 | 621 | # Help methods are listed below |
508 | 622 |
|
509 | 623 | @staticmethod |
|
0 commit comments