Skip to content

Conversation

asonnenschein
Copy link
Contributor

This PR provides a complete, production-ready Reports API client that seamlessly integrates with the existing Planet Python SDK architecture and follows all established patterns and conventions. Generated with help from Claude Code:

Ticket

#1190

Key Features

  • API Endpoints: List reports, get report details, create/delete reports, download report content, check status, list types/formats
  • Error Handling: Proper APIError and ClientError propagation
  • Authentication: Uses existing Planet SDK authentication system
  • Consistent Patterns: Follows exact same patterns as other Planet API clients
  • Type Hints: Full type annotations throughout
  • Documentation: Comprehensive docstrings for all methods
  • CLI Features: JSON config files, output redirection, pretty-printing, help text

Details

  1. Async Client SDK (planet/clients/reports.py)
    • ReportsClient class extending _BaseClient
    • Methods: list_reports, get_report, create_report, download_report, get_report_status, delete_report, list_report_types, get_report_export_formats
    • Full async/await support following existing patterns
  2. Sync Client SDK (planet/sync/reports.py)
    • ReportsAPI class wrapping the async client
    • Same method signatures with synchronous execution
    • Integrated into Planet class as planet.reports
  3. CLI Implementation (planet/cli/reports.py)
    • Complete CLI commands: list, get, create, download, status, delete, types, formats
    • Integrated into main CLI as planet reports
    • Support for JSON config files, output redirection, and formatting options
  4. Comprehensive Test Suite
    • Unit tests for async client (13 tests)
    • Unit tests for sync client (8 tests)
    • Unit tests for CLI (14 tests)
    • Integration tests for both sync/async clients and CLI
  5. Package Integration
    • Added to planet.clients.init.py exports and client directory
    • Integrated into planet.sync.client.Planet class
    • Added to main CLI command registration

Code Quality

  • Passes linting (flake8, yapf)
  • Follows PEP8 style guidelines
  • Matches existing codebase patterns
  • Proper error handling and type safety
  • Integration tests verify functionality

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a complete Reports API client to the Planet Python SDK, providing both async and sync interfaces for interacting with Planet's reporting system. The implementation follows the existing SDK patterns and conventions while adding comprehensive CLI support.

  • Async/sync Reports API client for listing, creating, downloading, and managing reports
  • Full CLI integration with commands for all report operations
  • Comprehensive test suite covering unit and integration tests

Reviewed Changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
planet/clients/reports.py Async ReportsClient with full API method coverage
planet/sync/reports.py Sync ReportsAPI wrapper for the async client
planet/sync/client.py Integration of reports API into Planet class
planet/clients/init.py Export registration for ReportsClient
planet/cli/reports.py CLI commands for all report operations
planet/cli/cli.py CLI integration of reports command group
tests/unit/test_reports_client.py Unit tests for async ReportsClient
tests/unit/test_reports_sync.py Unit tests for sync ReportsAPI
tests/unit/test_reports_cli.py Unit tests for CLI commands
tests/integration/test_reports_api.py Integration tests for API clients
tests/integration/test_reports_cli.py Integration tests for CLI commands

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

self.destinations = DestinationsAPI(self._session,
f"{planet_base}/destinations/v1")
self.orders = OrdersAPI(self._session, f"{planet_base}/compute/ops")
self.reports = ReportsAPI(self._session, f"{planet_base}/reports/v1/")
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reports API URL includes a trailing slash but the base URL constant in planet/clients/reports.py also includes a trailing slash, which could result in double slashes in the URL path. Consider removing the trailing slash here to be consistent with other API integrations or ensure the ReportsAPI/ReportsClient handles this correctly.

Suggested change
self.reports = ReportsAPI(self._session, f"{planet_base}/reports/v1/")
self.reports = ReportsAPI(self._session, f"{planet_base}/reports/v1")

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{report_id}'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String formatting with f-strings could result in double slashes if self._base_url already ends with a slash. Consider using urllib.parse.urljoin() or ensure consistent slash handling across all URL constructions in this class.

Suggested change
url = f'{self._base_url}/{report_id}'
url = urljoin(self._base_url, report_id)

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{report_id}/download'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same URL construction issue as above - potential for double slashes if self._base_url ends with a slash. This pattern appears multiple times in this file and should be addressed consistently.

Suggested change
url = f'{self._base_url}/{report_id}/download'
url = urljoin(self._base_url, f'{report_id}/download')

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{report_id}/status'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same URL construction issue - potential for double slashes. Consider implementing a helper method for URL path joining to ensure consistent URL formatting.

Suggested change
url = f'{self._base_url}/{report_id}/status'
url = _join_url(self._base_url, report_id, 'status')

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/{report_id}'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same URL construction issue as the previous occurrences in this file.

Suggested change
url = f'{self._base_url}/{report_id}'
url = urljoin(self._base_url, f'{report_id}')

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/types'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same URL construction issue - potential for double slashes if self._base_url ends with a slash.

Suggested change
url = f'{self._base_url}/types'
url = urljoin(self._base_url, 'types')

Copilot uses AI. Check for mistakes.

APIError: If the API returns an error response.
ClientError: If there is an issue with the client request.
"""
url = f'{self._base_url}/formats'
Copy link
Preview

Copilot AI Aug 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same URL construction issue as the previous occurrences in this file.

Suggested change
url = f'{self._base_url}/formats'
url = urljoin(self._base_url, 'formats')

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant