Repository navigation
fix(python): stop defaulting env-var credentials to an empty string in usage snippets - #129
Open
LukasParke wants to merge 1 commit into
Open
LukasParke wants to merge 1 commit into
LukasParke wants to merge 1 commit into
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
…n usage snippets
With envVarPrefix configured, Python usage snippets read security values
from the environment as os.getenv("PREFIX_API_KEY", ""). When the
variable is unset, the snippet passes an explicit empty string, which the
SDK treats as a provided credential and sends as an empty value (for
example "Authorization: Bearer ").
Render os.getenv("PREFIX_API_KEY") without a default when the target
security field is optional or nullable. The generated constructor and
model already accept None there, so the snippet still type-checks under
pyright and mypy, and an unset variable now leaves the credential absent.
Required str fields keep the "" default so the snippet remains
type-correct.
LukasParke
force-pushed
the
fix/python-getenv-usage-snippet
branch
from
October 21, 2026 19:13
f36edc1 to
28628f7
Compare
LukasParke
marked this pull request as ready for review
October 21, 2026 19:19
Author
|
recheck |
2ynn
approved these changes
Oct 21, 2026
2ynn
left a comment
Contributor
There was a problem hiding this comment.
Thank you @LukasParke! As stated in PR#130 we want to preserve the existing distinction between explicit "" and None (i.e. an empty credential should not silently trigger environment fallback). Accordingly this PR makes sense:
an unset environment variable should remain absent rather than become an explicit empty credential.
I will approve it now, although I think we should apply that principle across other languages so they remain consistent, at least Go and Typescript that also support the automatic envVarPrefix security feature.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
When
envVarPrefixis configured, Python usage snippets (README, USAGE.md,docs/sdks/*/README.md) read security values from the environment like this:If the variable is unset, the snippet passes an explicit
"". The SDK treats that as a provided credential, so it never takes its "no credential" path and instead sends an empty value. For a bearer scheme that is a literalAuthorization: Bearerheader. PassingNoneleaves the credential absent, which is what the snippet means.Checked against an SDK generated from a single bearer-scheme spec (
envVarPrefix: ACME,flattenGlobalSecurity: true), withACME_API_KEYunset unless noted:Authorizationsentapi_key=os.getenv("ACME_API_KEY", "")Bearerapi_key=os.getenv("ACME_API_KEY")api_key=os.getenv("ACME_API_KEY"), variable set tosecretBearer secretWhat changed
languageSpecificEnvVarWrappingintemplates/templates/pythonv2/includes/sanitization.tsnow takes thefieldDefthat the shared security-usage code already passes. It rendersos.getenv("NAME")with no default when thex-envdirective has no default and the target field is optional or nullable.Optional[Union[Optional[str], Callable[[], Optional[str]]]] = None, soOptional[str]fromos.getenvis accepted. A usage snippet extracted from the generated USAGE.md passespyrightandmypy --strict.strfields keep the""default. This covers fields inside security option models and required per-operation security models. PassingOptional[str]there would fail type checking and pydantic validation. In those positions an explicit security object is already being built, so the SDK's environment fallback does not apply either way.x-envusages are unchanged, because nofieldDefreaches the wrapper on those paths.zSDKs/sdk-pythonv2regenerates byte-identical. Its env-var snippets all target requiredstrfields inside security option models or per-operation security models, so none of them change.envVarSecurityUsage/pythonv2.Testing
npm run format,make check-template-pythonv2,git diff --check: clean.mise run test:generator: passed.TARGET=review make build-pythonv2: no diff inzSDKs/; generation-timepyright,mypyandpylintpassed.TARGET=quaternary make test-pythonv2(flattened security withenvVarPrefix): 247 passed, 1 skipped. Generated tests already use a non-empty"value"default and are unaffected.os.getenv("ACME_API_KEY", "")toos.getenv("ACME_API_KEY"), SDK-levelpyright/mypy/pylintpassed, and the header behavior in the table above was observed with anhttpx.MockTransport.make testmatrix.Public-safety check
.claude/skills/public-repo-communication/SKILL.md).git diff --check.Summary by cubic
Fixes Python usage snippets so unset environment credentials are left absent instead of being sent as empty strings.
envVarPrefixset, snippets emittedos.getenv("ACME_API_KEY", ""), which the SDK treats as a provided credential and sends as an empty value, such as anAuthorization: Bearerheader.os.getenv("ACME_API_KEY")without a default; the generated constructor already acceptsNone.strfields keep the""default so the snippets remain type-correct underpyrightandmypy --strict.x-envusages such as server URLs are unchanged.Written for commit 28628f7. Summary will update on new commits.