mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
## Description Extracts project-name normalization for proxy attribution from `savings_tracker.py` into `headroom.proxy.project_name_policy`. `savings_tracker.sanitize_project_name` and `PROJECT_NAME_MAX_LENGTH` remain compatibility aliases for existing callers. Closes # ## Type of Change - [ ] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [x] Code refactoring (no functional changes) ## Changes Made - Added `project_name_policy.py` for project-name decoding, printable-character filtering, trimming, and length capping. - Kept `savings_tracker` compatibility aliases for existing imports and project-context callers. - Added focused policy tests plus re-export coverage. - Carried forward the LiteLLM callback compatibility shim needed for current mypy on `main`. ## Testing - [x] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [x] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text python -m pytest tests\test_project_name_policy.py tests\test_proxy_project_savings.py 20 passed in 17.05s python -m ruff check . All checks passed! python -m ruff format --check . 1095 files already formatted python -m mypy headroom --ignore-missing-imports Success: no issues found in 409 source files gitleaks protect --staged --no-banner --redact no leaks found ``` ## Real Behavior Proof - Environment: Windows, Python 3.13.13, branch `jd/architecture-slice-26`. - Exact command / steps: ran new project-name policy tests, existing project savings tests, ruff, ruff format check, mypy, and staged gitleaks scan. - Observed result: project attribution/savings behavior remains covered and local lint/type/security checks pass. - Not tested: full proxy runtime; this slice preserves existing `savings_tracker` imports. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Screenshots (if applicable) N/A ## Additional Notes Documentation and changelog updates are N/A for this internal architecture-only refactor. The push reported existing default-branch Dependabot alerts; no staged secret leaks were found for this PR.
26 lines
1.1 KiB
Python
26 lines
1.1 KiB
Python
from __future__ import annotations
|
|
|
|
from headroom.proxy.project_name_policy import PROJECT_NAME_MAX_LENGTH, sanitize_project_name
|
|
from headroom.proxy.savings_tracker import sanitize_project_name as savings_sanitize_project_name
|
|
|
|
|
|
def test_project_name_policy_normalizes_and_caps() -> None:
|
|
assert sanitize_project_name(" api-server ") == "api-server"
|
|
assert sanitize_project_name("a" * 300) == "a" * PROJECT_NAME_MAX_LENGTH
|
|
assert sanitize_project_name("x\x00\x1by") == "xy"
|
|
|
|
|
|
def test_project_name_policy_decodes_percent_encoded_unicode() -> None:
|
|
assert sanitize_project_name("%E9%A1%B9%E7%9B%AE") == "\u9879\u76ee"
|
|
assert sanitize_project_name("my%20repo") == "my repo"
|
|
|
|
|
|
def test_project_name_policy_rejects_unusable_values() -> None:
|
|
assert sanitize_project_name("") is None
|
|
assert sanitize_project_name(" ") is None
|
|
assert sanitize_project_name(None) is None
|
|
assert sanitize_project_name(42) is None
|
|
|
|
|
|
def test_savings_tracker_reexports_project_name_policy() -> None:
|
|
assert savings_sanitize_project_name is sanitize_project_name
|