Skip to content

Commit

Permalink
feat, python: support envvar scanning for headers (#3064)
Browse files Browse the repository at this point in the history
armandobelardo authored Feb 26, 2024
1 parent 805f92f commit 185a14a
Showing 50 changed files with 1,373 additions and 67 deletions.
38 changes: 19 additions & 19 deletions generators/python/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion generators/python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ pydantic = "^1.9.2"
typer = {extras = ["all"], version = "^0.6.1"}
fern-fern-generator-exec-sdk = {version = "0.0.570", source = "fern-prod"}
ordered-set = "^4.1.0"
fern_fern_ir_v34 = "^0.0.3363"
fern_fern_ir_v36 = "^0.0.3413"

[tool.poetry.dev-dependencies]
pytest = "^7.4.2"
33 changes: 33 additions & 0 deletions generators/python/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -5,6 +5,39 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.11.6] - 2024-02-26

- Improvement: You can now specify envvars to scan for headers, not just auth scheme headers.
```
# OpenAPI
x-fern-global-headers:
- header: x-api-key
name: api_key
optional: true
env: MY_API_KEY
```
... or ...
```
# Fern Definition
getAllUsers:
method: GET
path: /all
request:
name: GetAllUsersRequest
headers:
X-API-KEY: string
env: MY_API_KEY
```
the generated client will look like

```python
import os

class Client:

def __init__(self, *, apiKey: str = os.getenv("MY_API_KEY"))
```

## [0.11.5] - 2024-02-23

- Fix: Fix the usage of ApiError when leveraging auth envvars, when the schema for ApiError was changed, this usage was missed in the update.
2 changes: 1 addition & 1 deletion generators/python/sdk/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.11.5
0.11.6
Original file line number Diff line number Diff line change
@@ -199,14 +199,28 @@ def _get_endpoint_named_parameters(

for header in service.headers + endpoint.headers:
if not self._is_header_literal(header):
header_type_hint = self._context.pydantic_generator_context.get_type_hint_for_type_reference(
header.value_type,
in_endpoint=True,
)
if header.env is not None:
header_type_hint = AST.TypeHint.optional(header_type_hint)
parameters.append(
AST.NamedFunctionParameter(
name=get_parameter_name(header.name.name),
docs=header.docs,
type_hint=self._context.pydantic_generator_context.get_type_hint_for_type_reference(
header.value_type,
in_endpoint=True,
),
type_hint=header_type_hint,
initializer=AST.Expression(
AST.FunctionInvocation(
function_definition=AST.Reference(
import_=AST.ReferenceImport(module=AST.Module.built_in(("os",))),
qualified_name_excluding_import=("getenv",),
),
args=[AST.Expression(f'"{header.env}"')],
)
)
if header.env is not None
else None,
),
)

Original file line number Diff line number Diff line change
@@ -421,6 +421,7 @@ def _get_constructor_info(self) -> ConstructorInfo:
f'{constructor_parameter_name}="YOUR_{header.name.name.screaming_snake_case.safe_name}"',
),
header_key=header.name.wire_value,
environment_variable=header.env,
)
)

Original file line number Diff line number Diff line change
@@ -91,7 +91,39 @@ exports[`generate IR 1`] = `
"type": "statusCode",
},
"errors": {},
"headers": [],
"headers": [
{
"availability": null,
"docs": null,
"env": "ANOTHER_ENV_VAR",
"name": {
"name": {
"camelCase": {
"safeName": "xAnotherHeader",
"unsafeName": "xAnotherHeader",
},
"originalName": "X-Another-Header",
"pascalCase": {
"safeName": "XAnotherHeader",
"unsafeName": "XAnotherHeader",
},
"screamingSnakeCase": {
"safeName": "X_ANOTHER_HEADER",
"unsafeName": "X_ANOTHER_HEADER",
},
"snakeCase": {
"safeName": "x_another_header",
"unsafeName": "x_another_header",
},
},
"wireValue": "X-Another-Header",
},
"valueType": {
"_type": "primitive",
"primitive": "STRING",
},
},
],
"idempotencyHeaders": [],
"pathParameters": [],
"rootPackage": {
@@ -115,7 +147,7 @@ exports[`generate IR 1`] = `
"sdkConfig": {
"hasFileDownloadEndpoints": false,
"hasStreamingEndpoints": false,
"isAuthMandatory": true,
"isAuthMandatory": false,
"platformHeaders": {
"language": "X-Fern-Language",
"sdkName": "X-Fern-SDK-Name",
@@ -192,6 +224,156 @@ exports[`generate IR 1`] = `
},
"sdkRequest": null,
},
{
"allPathParameters": [],
"auth": false,
"availability": null,
"baseUrl": null,
"displayName": null,
"docs": "GET request with custom api key",
"errors": [],
"examples": [],
"fullPath": {
"head": "apiKeyInHeader",
"parts": [],
},
"headers": [
{
"availability": null,
"docs": "Specifies the endpoint key.",
"env": "MY_HEADER_ENV",
"name": {
"name": {
"camelCase": {
"safeName": "xEndpointHeader",
"unsafeName": "xEndpointHeader",
},
"originalName": "X-Endpoint-Header",
"pascalCase": {
"safeName": "XEndpointHeader",
"unsafeName": "XEndpointHeader",
},
"screamingSnakeCase": {
"safeName": "X_ENDPOINT_HEADER",
"unsafeName": "X_ENDPOINT_HEADER",
},
"snakeCase": {
"safeName": "x_endpoint_header",
"unsafeName": "x_endpoint_header",
},
},
"wireValue": "X-Endpoint-Header",
},
"valueType": {
"_type": "primitive",
"primitive": "STRING",
},
},
],
"id": "endpoint_service.getWithHeader",
"idempotent": false,
"method": "GET",
"name": {
"camelCase": {
"safeName": "getWithHeader",
"unsafeName": "getWithHeader",
},
"originalName": "getWithHeader",
"pascalCase": {
"safeName": "GetWithHeader",
"unsafeName": "GetWithHeader",
},
"screamingSnakeCase": {
"safeName": "GET_WITH_HEADER",
"unsafeName": "GET_WITH_HEADER",
},
"snakeCase": {
"safeName": "get_with_header",
"unsafeName": "get_with_header",
},
},
"pagination": null,
"path": {
"head": "/apiKeyInHeader",
"parts": [],
},
"pathParameters": [],
"queryParameters": [],
"requestBody": null,
"response": {
"type": "json",
"value": {
"docs": null,
"responseBodyType": {
"_type": "primitive",
"primitive": "STRING",
},
"type": "response",
},
},
"sdkRequest": {
"requestParameterName": {
"camelCase": {
"safeName": "request",
"unsafeName": "request",
},
"originalName": "request",
"pascalCase": {
"safeName": "Request",
"unsafeName": "Request",
},
"screamingSnakeCase": {
"safeName": "REQUEST",
"unsafeName": "REQUEST",
},
"snakeCase": {
"safeName": "request",
"unsafeName": "request",
},
},
"shape": {
"bodyKey": {
"camelCase": {
"safeName": "body",
"unsafeName": "body",
},
"originalName": "body",
"pascalCase": {
"safeName": "Body",
"unsafeName": "Body",
},
"screamingSnakeCase": {
"safeName": "BODY",
"unsafeName": "BODY",
},
"snakeCase": {
"safeName": "body",
"unsafeName": "body",
},
},
"type": "wrapper",
"wrapperName": {
"camelCase": {
"safeName": "headerAuthRequest",
"unsafeName": "headerAuthRequest",
},
"originalName": "HeaderAuthRequest",
"pascalCase": {
"safeName": "HeaderAuthRequest",
"unsafeName": "HeaderAuthRequest",
},
"screamingSnakeCase": {
"safeName": "HEADER_AUTH_REQUEST",
"unsafeName": "HEADER_AUTH_REQUEST",
},
"snakeCase": {
"safeName": "header_auth_request",
"unsafeName": "header_auth_request",
},
},
},
},
},
],
"headers": [],
"name": {
Loading

0 comments on commit 185a14a

Please sign in to comment.