Refactor: Extract duplicated patterns into shared utilities#54
Conversation
There was a problem hiding this comment.
Hi @Copilot! 👋
Your private repo does not have access to Sourcery.
Please upgrade to continue using Sourcery ✨
…orts Co-authored-by: Bryan-Roe <74067792+Bryan-Roe@users.noreply.github.com>
Co-authored-by: Bryan-Roe <74067792+Bryan-Roe@users.noreply.github.com>
Co-authored-by: Bryan-Roe <74067792+Bryan-Roe@users.noreply.github.com>
| resp = self.client.chat.completions.create( | ||
| model=self.model, | ||
| messages=messages, | ||
| temperature=self.temperature, | ||
| max_tokens=self.max_output_tokens, | ||
| stream=stream, | ||
| ) |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Possibly found usage of AI: OpenAI
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by detect-openai.
You can view more details about this finding in the Semgrep AppSec Platform.
| resp = self.client.chat.completions.create( | ||
| model=self.model, | ||
| messages=messages, | ||
| temperature=self.temperature, | ||
| max_tokens=self.max_output_tokens, | ||
| stream=stream, | ||
| ) |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Possibly found usage of AI: OpenAI
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by detect-openai.
You can view more details about this finding in the Semgrep AppSec Platform.
|
Semgrep found 6
Possibly found usage of AI: OpenAI Semgrep found 6
|
| return True, None, None | ||
|
|
||
| provider_lower = provider_choice.lower() | ||
| valid_providers = {'auto', 'openai', 'azure', 'local', 'lora', 'lmstudio'} |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Possibly found usage of AI: OpenAI
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by detect-generic-ai-oai.
You can view more details about this finding in the Semgrep AppSec Platform.
| """Validate provider choice and model override. | ||
|
|
||
| Args: | ||
| provider_choice: The requested provider ('auto', 'openai', 'azure', 'local', 'lora') |
There was a problem hiding this comment.
Semgrep identified an issue in your code:
Possibly found usage of AI: OpenAI
To resolve this comment:
🔧 No guidance has been designated for this issue. Fix according to your organization's approved methods.
💬 Ignore this finding
Reply with Semgrep commands to ignore this finding.
/fp <comment>for false positive/ar <comment>for acceptable risk/other <comment>for all other reasons
Alternatively, triage in Semgrep AppSec Platform to ignore the finding created by detect-generic-ai-oai.
You can view more details about this finding in the Semgrep AppSec Platform.
There was a problem hiding this comment.
Hi @Bryan-Roe! 👋
Your private repo does not have access to Sourcery.
Please upgrade to continue using Sourcery ✨
There was a problem hiding this comment.
Pull request overview
Refactors duplicated provider/HTTP/import patterns into shared utilities, and adds unit tests to lock in behavior.
Changes:
- Extracted shared OpenAI-compatible streaming/non-streaming response parsing into
BaseChatProvider. - Added
shared/import_helpers.pyand refactored optional imports infunction_app.pyto usesafe_import(). - Added
shared/http_utils.pyand refactored HTTP endpoints to use shared validation/CORS/static-file serving helpers.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_provider_response_handling.py | Adds tests for the new BaseChatProvider response helper methods. |
| tests/test_import_helpers.py | Adds tests for safe_import() and create_stub_function(). |
| tests/test_http_utils.py | Adds tests for shared HTTP validation/header/static-file helpers. |
| talk-to-ai/src/chat_providers.py | Introduces shared response handlers and refactors providers to use them. |
| shared/import_helpers.py | New module to consolidate defensive import + fallback patterns. |
| shared/http_utils.py | New module for message/provider validation and static file serving helpers. |
| http_chat_web/function_app.py | Refactors static file serving to use serve_static_file(). |
| http_chat/function_app.py | Refactors message validation + CORS header creation via shared helpers. |
| function_app.py | Refactors optional imports to use safe_import() utilities. |
| docs/REFACTORING_SUMMARY.md | Adds documentation summarizing refactor scope and impact. |
| def serve_static_file( | ||
| file_path: Path, | ||
| mimetype: str, | ||
| use_cache_headers: bool = False | ||
| ) -> Tuple[Optional[str], int, Dict[str, str]]: |
There was a problem hiding this comment.
use_cache_headers is misleading: when it's True, the function adds no-cache headers via create_no_cache_headers(). This is likely to confuse callers/maintainers and contradicts the intent implied by the name. Rename the parameter to something like disable_cache / no_cache (and update docstring accordingly), or invert the behavior so use_cache_headers=True actually enables cache-friendly headers.
| Args: | ||
| file_path: Path to the file to serve | ||
| mimetype: MIME type for the response (e.g., 'text/html', 'application/javascript') | ||
| use_cache_headers: Whether to add no-cache headers (default: False for better caching) |
There was a problem hiding this comment.
use_cache_headers is misleading: when it's True, the function adds no-cache headers via create_no_cache_headers(). This is likely to confuse callers/maintainers and contradicts the intent implied by the name. Rename the parameter to something like disable_cache / no_cache (and update docstring accordingly), or invert the behavior so use_cache_headers=True actually enables cache-friendly headers.
| headers = {} | ||
| if use_cache_headers: | ||
| headers.update(create_no_cache_headers()) |
There was a problem hiding this comment.
use_cache_headers is misleading: when it's True, the function adds no-cache headers via create_no_cache_headers(). This is likely to confuse callers/maintainers and contradicts the intent implied by the name. Rename the parameter to something like disable_cache / no_cache (and update docstring accordingly), or invert the behavior so use_cache_headers=True actually enables cache-friendly headers.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 016f6c9f68
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| from datetime import datetime | ||
|
|
||
| # Import defensive import helper | ||
| from shared.import_helpers import safe_import, create_stub_function |
There was a problem hiding this comment.
Guard import_helpers import to preserve startup fallbacks
This unconditional top-level import introduces a hard dependency on the shared package at module import time. In environments where shared is not on sys.path (the same scenario the surrounding code previously handled with defensive try/except imports), function_app.py now fails to load before any fallback stubs are installed, which can prevent the Functions worker from starting at all.
Useful? React with 👍 / 👎.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Eliminated ~150 lines of duplicated code across providers, HTTP endpoints, and import patterns by extracting common logic into reusable utilities.
Changes
Provider Response Handling
Extracted OpenAI-compatible streaming/non-streaming response parsing from 3 provider classes into
BaseChatProviderhelper methods:Impact:
OpenAIProviderandLMStudioProvidernow use shared logic;AzureOpenAIProvideruses it for non-quota cases.Defensive Import Pattern
Created
shared/import_helpers.pyto consolidate try/except import blocks with fallbacks:HTTP Utilities
Created
shared/http_utils.pyconsolidating validation and file serving:validate_messages()- Message format validation (used in 2+ endpoints)create_cors_headers()- CORS header generationserve_static_file()- File serving with error handlingRefactored
http_chat/function_app.pyandhttp_chat_web/function_app.pyto use shared utilities.Test Coverage
30 unit tests added covering all utility functions (100% passing).
Additional Refactoring Opportunities
Identified but not implemented:
sys.pathmanipulation (60+ instances, inconsistent patterns)os.getenv()calls without validation)See
docs/REFACTORING_SUMMARY.mdfor details.✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.