-
-
Notifications
You must be signed in to change notification settings - Fork 1
v0.3.0 refactors #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
v0.3.0 refactors #18
Conversation
BREAKING CHANGE: Development workflow now uses uv instead of Hatch - Replace Hatch CI workflow with new uv-based CI pipeline - Update documentation workflow to use uv instead of Hatch - Remove old Hatch workflow configuration - Add uv configuration files (.prototools, .python-version) - Update pyproject.toml to include dev dependencies and remove Hatch environments - Add comprehensive development guidelines in AGENTS.md - Fix type annotation issues in API insights method - Update smoke test documentation to reference new uv commands This change requires developers to install and use uv instead of Hatch for development tasks. All previous Hatch commands need to be replaced with their uv equivalents as documented in AGENTS.md.
Add /llmc.toml to the .gitignore file to prevent tracking of the LLMC configuration file in version control.
- Add ThreadsHTTPError exception for better HTTP error handling - Add Python <3.11 compatibility fallback for StrEnum - Add logging support with debug messages for failed requests - Make SSL credentials optional for development environments - Add 30-second timeout to HTTP client sessions - Improve JSON parsing with UTC timezone support for ISO-8601 dates - Consolidate HTTP methods into unified _request method - Remove unused fields from default field sets - Fix parameter name bug in user_insights method (PARAMS__METRIC -> PARAMS__FIELDS) - Improve URL parameter encoding to handle non-string values BREAKING CHANGE: SSL certificates are now optional, which may affect existing deployments that rely on the previous behavior of throwing an error when certificates are missing. The ThreadsHTTPError exception replaces generic exceptions for HTTP errors, which may affect error handling in client code.
Split the monolithic api.py file into multiple modules: - client.py: Contains the main API class with all methods - types.py: Contains all type definitions, enums, and constants - errors.py: Contains all custom exception classes - __init__.py: Provides backwards-compatible imports This change improves code maintainability and readability by separating concerns. The API interface remains the same with all classes and functions re-exported from the api module. BREAKING CHANGE: Internal import paths have changed. Code importing specific classes directly from pythreads.api.Field, pythreads.api.MediaType, etc. may break. Use imports from pythreads.api instead.
- Update GitHub Actions workflow to test against Python versions 3.8, 3.9, 3.10, 3.11, and 3.12 - Add matrix strategy for comprehensive version coverage - Pin Python version using uv for consistent environment setup - Add test coverage for ThreadsHTTPError exception handling in API methods - Add test for credentials deserialization with Z-suffix timezone format - Add test for SSL credentials when environment variables are missing These changes improve CI robustness by ensuring compatibility across supported Python versions and enhance test coverage for error handling scenarios.
Add timeout and base_url parameters to the API client constructor to allow customization of request timeout and API endpoint. This enhances flexibility for different deployment environments and network conditions. - Add optional timeout parameter (default 30s) supporting float or ClientTimeout objects - Add optional base_url parameter for custom API endpoints - Refactor URL building into _build_url method for consistent base_url handling - Add pre-commit configuration with ruff and pyright hooks - Update README with development section including setup and testing instructions - Add test coverage for HTTP error handling with text bodies The API constructor now accepts keyword-only timeout and base_url parameters while maintaining backward compatibility with existing code.
- Add retry configuration parameters: retries, backoff_base, backoff_max - Implement automatic retry for transient HTTP errors (429, 5xx status codes) - Add exponential backoff with jitter to prevent thundering herd - Update API class docstring and documentation with new options - Add comprehensive logging for retry attempts The retry mechanism helps improve reliability when dealing with rate limiting and temporary server errors, while the exponential backoff prevents overwhelming the server with rapid retry attempts.
Extract HTTP transport logic and accounts endpoints into dedicated service classes: - Add Transport class to centralize HTTP request handling, retries, and URL building - Add AccountsService to encapsulate account-related API operations - Wire Transport and AccountsService instances in API client initialization - Migrate account() and publishing_limit() methods to use new service layer - Add types-requests dependency for improved type checking - Exclude tests directory from pyright type checking to focus on source code The existing public API remains unchanged - this is an internal refactoring to improve code organization and maintainability.
Move threads, replies, and conversation methods from the main API client to a new ThreadsService class to improve code organization and separation of concerns. Changes: - Create new ThreadsService class in endpoints/threads.py - Add threads_service property to API client - Refactor threads(), replies(), and conversation() methods to delegate to ThreadsService - Maintain existing public API interface for backwards compatibility
Extract media container creation, publishing, and status checking operations from the main API client into a new MediaService class. This improves code organization and separation of concerns by moving media-related functionality into its own service module. - Add new MediaService class in endpoints/media.py - Refactor create_container, create_carousel_container, container_status, publish_container, container, and thread methods to delegate to MediaService - Update API class to initialize and use MediaService instance - Maintain backward compatibility with existing API interface
…ervices - Create InsightsService to handle user insights and thread insights functionality - Create ModerationService to handle reply management operations - Move user_insights, insights, and manage_reply methods from API class to respective services - Update API class to initialize and use the new services - Maintain backward compatibility by keeping the same public API methods This refactoring improves code organization by separating concerns into dedicated service classes while preserving the existing API interface.
Add comprehensive type annotations using TypedDict for API responses: - AccountResponse for account endpoint return values - PublishingLimitResponse for publishing limit data - InsightsResponse for insights API responses Update method signatures in client.py and endpoint modules to use proper return type annotations instead of 'Any'. Add documentation section for endpoint modules in pythreads.rst with automodule directives for better API reference coverage. These changes improve type safety and developer experience without breaking existing functionality.
Add convenience async iterators to simplify pagination: - threads_iter: iterate through user's threads with automatic cursor handling - replies_iter: iterate through thread replies - conversation_iter: iterate through flattened conversations Additional improvements: - Add architecture documentation explaining package layout and design principles - Extract utility functions for timestamp and date parameter handling - Update README with iterator usage examples - Document iterator methods in API reference All iterators support per_page limits and optional page_limit for bounded iteration.
Add support for per-request customization through a new `request_options` parameter across all API client methods. This allows users to override default retry behavior, timeouts, backoff settings, and base URL on a per-request basis. Changes include: - Add `request_options` parameter to all client methods (account, user_insights, publishing_limit, etc.) - Add `RequestOptions` TypedDict type for type safety - Update transport layer to handle request-specific options - Maintain backward compatibility by making the parameter optional with default None - Support customizable retries, backoff_base, backoff_max, base_url, and timeout settings This enhancement provides greater flexibility for handling different API call requirements without changing global client configuration.
Add optional Pydantic v2 models for API response validation with a new `models` extra. Users can now install with `pip install pythreads[models]` to get validation models for insights and other API responses. Changes: - Add `pythreads.api.models` module with Pydantic models for account, publishing limits, and insights responses - Add `models` optional dependency group in pyproject.toml requiring pydantic>=2,<3 - Update documentation with usage examples for the new models - Make python-dotenv import optional with fallback to avoid hard dependency - Add per-call request options example in README
…test - Add comprehensive docstrings to all public API methods in client.py - Document parameters, return types, and usage for each method - Include details about optional request_options parameter - Create new test file for validating InsightsResponseModel Pydantic validation This improves API documentation and ensures model validation works correctly.
- Enable sphinx.ext.doctest extension in documentation configuration - Create new doctests.rst file with examples for utils and pydantic models - Add doctests section to main documentation index - Enhance pythreads.rst with per-call overrides and common methods examples This addition provides executable documentation examples that validate core functionality while serving as practical usage guides for users.
- Add CLAUDE.md documentation for AI assistant guidance - Introduce centralized Config class for environment variable management - Add comprehensive response type definitions for better type safety - Refactor pagination with reusable PaginatedIterator base class - Replace manual iterator implementations with specialized iterator classes - Add proper return type annotations across API methods - Maintain backward compatibility with legacy get_ssl_credentials function The Config class centralizes all environment variable handling and validation, improving maintainability and testing. New TypedDict definitions provide better IDE support and runtime type checking for API responses. The paginated iterator refactoring reduces code duplication while maintaining the same async iterator interface.
There was a problem hiding this 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 pull request modernizes the project's development, CI, and documentation workflows by migrating from Hatch to the uv toolchain, introducing automated lint/type checks with pre-commit, and improving developer and contributor documentation. It also updates the documentation to reflect new async iterator features and exposes key API types and errors for easier imports.
- Replaced Hatch-based build system with uv for faster dependency management and simplified scripts
- Added comprehensive API refactoring with service-oriented architecture and async iterators
- Enhanced documentation with new architectural guides and per-call API options
Reviewed Changes
Copilot reviewed 36 out of 38 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_threads.py | Added new test for SSL credentials handling and updated imports |
| tests/test_smoke.py | Updated test command from Hatch to uv |
| tests/test_models.py | New test file for Pydantic model validation |
| tests/test_credentials.py | Added test for UTC timezone handling in credentials deserialization |
| tests/test_api.py | Added comprehensive HTTP error handling tests |
| src/pythreads/threads.py | Refactored configuration loading and SSL handling to use centralized config |
| src/pythreads/credentials.py | Enhanced ISO timestamp parsing to support 'Z' UTC suffix |
| src/pythreads/config.py | New centralized configuration management system |
| src/pythreads/api/ | Complete API restructure with service-oriented architecture and async iterators |
| pyproject.toml | Migration from Hatch to uv with new dev dependencies and Pyright configuration |
| docs/ | Enhanced documentation with new architecture guides and API usage examples |
| CI/Workflows | Updated from Hatch to uv-based workflows |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| try: # pragma: no cover - import path when available | ||
| from enum import StrEnum # type: ignore[attr-defined] | ||
| except Exception: # pragma: no cover - fallback for older Python | ||
| class StrEnum(str, Enum): | ||
| pass |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a more specific exception type instead of the broad Exception. Consider using ImportError since this is specifically handling a missing import scenario.
| try: | ||
| from dotenv import load_dotenv | ||
| except Exception: # fallback if python-dotenv isn't available | ||
| def load_dotenv(*args, **kwargs): # type: ignore[no-redef] | ||
| return False |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ImportError instead of the broad Exception for handling missing import of python-dotenv.
| try: | ||
| body = await response.json() | ||
| except Exception: | ||
| try: | ||
| body = await response.text() | ||
| except Exception: | ||
| body = None |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use more specific exception types instead of broad Exception. For JSON parsing, consider ValueError or aiohttp.ContentTypeError. For text retrieval, consider aiohttp.ClientError.
| try: | ||
| body = await response.json() | ||
| except Exception: | ||
| try: | ||
| body = await response.text() | ||
| except Exception: | ||
| body = None |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use more specific exception types instead of broad Exception. For JSON parsing, consider ValueError or aiohttp.ContentTypeError. For text retrieval, consider aiohttp.ClientError.
| limit: Optional[int] = None, | ||
| before: Optional[str] = None, | ||
| after: Optional[str] = None, | ||
| *, request_options: dict | None = None) -> ThreadsListResponse: |
Copilot
AI
Sep 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] Consider using a typed dictionary or dataclass for request_options instead of dict | None to provide better type safety and documentation of valid options.
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: | ||
| python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python-version }} | ||
| - name: Setup uv | ||
| uses: astral-sh/setup-uv@v4 | ||
| - name: Pin Python | ||
| run: uv python pin ${{ matrix.python-version }} | ||
| - name: Sync dependencies (dev) | ||
| run: uv sync --dev | ||
| - name: Lint (ruff) | ||
| run: uv run ruff check --fix . | ||
| - name: Type check (pyright) | ||
| run: uv run pyright . | ||
| - name: Run tests (exclude smoke) | ||
| env: | ||
| CI: "1" | ||
| run: uv run pytest -m "not smoke" | ||
| # - name: Coverage HTML (optional) | ||
| # run: uv run coverage html |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI 3 months ago
The best way to fix this problem is to explicitly add a permissions block to the job (or at the workflow root if preferred) specifying the minimal required access: contents: read. This restricts the GITHUB_TOKEN to only permit reading repository contents, adhering to the principle of least privilege. Specifically, you should add the permissions: key under the appropriate job (here, under the build job at line 11), with the value contents: read. No extra imports, method, or definition is needed for this YAML configuration fix: it is purely a matter of amending the workflow.
-
Copy modified lines R11-R12
| @@ -8,6 +8,8 @@ | ||
|
|
||
| jobs: | ||
| build: | ||
| permissions: | ||
| contents: read | ||
| runs-on: ubuntu-latest | ||
| strategy: | ||
| matrix: |
- Replace `--dev` flag with `--extra dev` in CI workflows - Standardize string quotes to double quotes in YAML files - Update step names to reflect new dependency sync approach
Replace all instances of `dict | None` with `RequestOptions | None` for request_options parameters across the codebase. This change introduces type safety and better documentation for request options. Changes include: - Import RequestOptions type in all relevant modules - Update all method signatures to use RequestOptions instead of dict - Remove unused imports and constants that are no longer needed - Fix iterator methods to return proper typed iterators instead of generic AsyncIterator - Update async iterator implementation to use proper async iteration protocol BREAKING CHANGE: request_options parameter type changed from dict to RequestOptions. Users must now pass RequestOptions objects instead of plain dictionaries.
This pull request modernizes the project's development, CI, and documentation workflows by migrating from Hatch to the uv toolchain, introducing automated lint/type checks with pre-commit, and improving developer and contributor documentation. It also updates the documentation to reflect new async iterator features and exposes key API types and errors for easier imports.
Tooling & CI Modernization:
.github/workflows/ci.yml,.github/workflows/documentation.yml,.prototools,pyproject.toml,README.md,AGENTS.md,CLAUDE.md) [1] [2] [3] [4] [5] [6] [7].github/workflows/hatch.yml,pyproject.toml) [1] [2]Developer Experience Improvements:
.pre-commit-config.yaml).python-versionfile to standardize on Python 3.12 for development.AGENTS.mdand added a detailed architecture and workflow guide for Claude inCLAUDE.md. [1] [2]Documentation Enhancements:
threads_iter,replies_iter), per-call API options, and usage of Pydantic models for response validation. (README.md,docs/source/pythreads.rst) [1] [2] [3]docs/source/architecture.rst,docs/source/doctests.rst,docs/source/conf.py,docs/source/index.rst) [1] [2] [3] [4]API Improvements:
pythreads.apipackage now re-exports key types and errors, making it easier to import these directly frompythreads.api. (src/pythreads/api/__init__.py)Configuration Updates:
[tool.pyright]section topyproject.tomlfor consistent type checking configuration.References: [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19]