feat: expose public hash-unit function for diagnostic use - #12
Conversation
Extract the MD5 + base64url-no-padding unit hashing logic out of Context.get_unit_hash() into a standalone sdk.internal.hashing.hash_unit() function, so callers that only need the hash (e.g. diagnostic tooling) don't have to construct a full Context. Context.get_unit_hash() now delegates to it instead of duplicating the logic.
WalkthroughAdds Estimated code review effort: 1 (Trivial) | ~5 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
sdk/internal/hashing.py (1)
5-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd direct tests for
hash_unit.The canonical
"test"vector is useful, but also cover Unicode input, padding removal, and parity withContext.get_unit_hash()so future changes cannot silently alter the assignment contract.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@sdk/internal/hashing.py` around lines 5 - 7, Add direct tests for hash_unit covering the canonical "test" vector, Unicode input, removal of trailing Base64 padding, and equality with Context.get_unit_hash() for the same unit. Keep assertions focused on preserving the existing assignment contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@sdk/internal/hashing.py`:
- Line 6: Update the hashlib.md5 call assigned to dig to pass
usedforsecurity=False, preserving the existing UTF-8 encoding and digest
behavior while explicitly marking the hash as compatibility-only.
---
Nitpick comments:
In `@sdk/internal/hashing.py`:
- Around line 5-7: Add direct tests for hash_unit covering the canonical "test"
vector, Unicode input, removal of trailing Base64 padding, and equality with
Context.get_unit_hash() for the same unit. Keep assertions focused on preserving
the existing assignment contract.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: d2116e6b-0f3a-4ede-9b48-fa862ab95bf4
📒 Files selected for processing (2)
sdk/context.pysdk/internal/hashing.py
|
|
||
|
|
||
| def hash_unit(unit: str) -> str: | ||
| dig = hashlib.md5(unit.encode('utf-8')).digest() |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify the repository's declared Python support before using usedforsecurity.
rg -n \
'requires-python|python_requires|target-version|python-version|\\.python-version|\\.tool-versions' \
.Repository: absmartly/python3-sdk
Length of output: 205
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '--- sdk/internal/hashing.py ---\n'
cat -n sdk/internal/hashing.py
printf '\n--- pyproject.toml ---\n'
cat -n pyproject.tomlRepository: absmartly/python3-sdk
Length of output: 250
🌐 Web query:
Python hashlib md5 usedforsecurity introduced version 3.9 docs
💡 Result:
The keyword-only argument usedforsecurity was introduced to the hashlib module in Python 3.9 [1][2]. All hashlib constructors (including md5) were updated in version 3.9 to include this parameter, which defaults to True [1][3]. The purpose of this parameter is to allow the use of hashing algorithms that might otherwise be blocked or considered insecure in restricted environments (such as those enforcing FIPS compliance) [1][2]. By setting usedforsecurity to False, a developer indicates that the hashing algorithm is not being used in a security-sensitive context—for example, when using a hash function strictly as a non-cryptographic, one-way compression function [1][4].
Citations:
- 1: https://docs.python.org/3.9/library/hashlib.html?highlight=hashlib
- 2: https://github.com/python/cpython/blob/3.9/Doc/library/hashlib.rst
- 3: https://docs.python.org/release/3.9.25/library/hashlib.html
- 4: https://docs.python.org/3.10/library/hashlib.html
Mark this compatibility hash as non-security use. Add usedforsecurity=False so the intent is explicit and FIPS-mode environments do not reject it. The project already requires Python >=3.9, so the keyword is available.
🧰 Tools
🪛 Ruff (0.15.21)
[error] 6-6: Probable use of insecure hash functions in hashlib: md5
(S324)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@sdk/internal/hashing.py` at line 6, Update the hashlib.md5 call assigned to
dig to pass usedforsecurity=False, preserving the existing UTF-8 encoding and
digest behavior while explicitly marking the hash as compatibility-only.
Source: Linters/SAST tools
Replace the wrapper's own inline MD5 + base64url computation with a call to python3-sdk's new sdk.internal.hashing.hash_unit(), matching the go-sdk/dotnet-sdk/kotlin-wrapper pattern of routing this diagnostic through the real SDK's hash function instead of a side-channel copy. Verified locally (Dockerfile builds python3-sdk from the local /Users/joalves/git_tree/sdks/python3-sdk checkout): 202/202 scenarios pass and hashUnit(value="test") returns the canonical "CY9rzUYh03PK3k6DJie09g". Depends on absmartly/python3-sdk#12 (adds hash_unit) being merged upstream before this works against a non-local/CI build of python3-sdk.
Summary
Context.get_unit_hash()into a standalone, module-levelsdk.internal.hashing.hash_unit(unit: str) -> strfunction.Context.get_unit_hash()now delegates tohash_unit()instead of duplicating the logic — single implementation, no behavior change.Context(Clock, ContextConfig, Future, ContextDataProvider, ContextPublisher, ContextEventLogger, VariableParser, AudienceMatcher). This mirrors equivalent changes already made in go-sdk (sdk.HashUnit) and dotnet-sdk (ABSmartly.Internal.Hashing.Md5.Hash).hash_unit("test") == "CY9rzUYh03PK3k6DJie09g", matching the canonical cross-SDK test vector (also covered bytest/test_md5.pyfixtures on another branch).Test plan
pytest test/) — 92 passed, no regressions.hash_unit("test")produces the canonical hashCY9rzUYh03PK3k6DJie09g.Summary by CodeRabbit