Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codegen/layouts/partials/method-docstring.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

:param wait_for_action_attempt: Whether, and for how long, to wait for the action attempt to finish.{{/if}}{{#unless (eq returnType "None")}}

:returns: {{{indent (pythonDoc responseDescription) 8}}}{{/unless}}{{#if hasRequiredParameters}}
:returns: {{{indent (pythonDoc responseDescription) 8}}}{{/unless}}{{#if requiresAtLeastOneParameter}}

:raises ValueError: At least one parameter must be provided.{{/if}}{{#if isDeprecated}}

Expand Down
9 changes: 6 additions & 3 deletions codegen/layouts/partials/route-method.hbs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@route_metadata(path="{{path}}", has_required_parameters={{#if hasRequiredParameters}}True{{else}}False{{/if}}, has_pagination={{#if hasPagination}}True{{else}}False{{/if}})
@route_metadata(path="{{path}}", at_least_one_parameter_names=({{#each atLeastOneParameterNames}}"{{this}}",{{#unless @last}} {{/unless}}{{/each}}), has_pagination={{#if hasPagination}}True{{else}}False{{/if}})
{{#if isAsync}}async {{/if}}def {{> method-signature}}:
"""{{> method-docstring}}"""
{{payloadVar}}: Dict[str, Any] = {}
Expand All @@ -7,9 +7,12 @@
if {{name}} is not None:
{{../payloadVar}}["{{name}}"] = {{name}}
{{/each}}
{{#if hasRequiredParameters}}
{{#if requiresAtLeastOneParameter}}

if not {{payloadVar}}:
if all(
param is None
for param in ({{#each atLeastOneParameterNames}}{{this}},{{#unless @last}} {{/unless}}{{/each}})
):
raise ValueError("At least one parameter is required for {{path}}")
{{/if}}

Expand Down
16 changes: 14 additions & 2 deletions codegen/lib/layouts/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ export interface MethodLayoutContext {
httpVerb: string
payloadVar: string
payloadArg: string
hasRequiredParameters: boolean
requiresAtLeastOneParameter: boolean
atLeastOneParameterNames: string[]
hasPagination: boolean
description: string
responseDescription: string
Expand Down Expand Up @@ -66,6 +67,16 @@ export interface RouteLayoutContext {
methods: MethodLayoutContext[]
}

const paginationParameterNames = new Set(['limit', 'page_cursor'])

const getAtLeastOneParameterNames = (method: ClassMethod): string[] =>
method.hasRequiredParameters &&
method.parameters.every(({ required }) => !(required ?? false))
? method.parameters
.map(({ name }) => name)
.filter((name) => !paginationParameterNames.has(name))
: []

const getRequestLayoutContext = (
preferredMethod: string,
): Pick<MethodLayoutContext, 'httpVerb' | 'payloadVar' | 'payloadArg'> => {
Expand All @@ -84,7 +95,8 @@ export const getMethodLayoutContext = (
name: method.methodName,
path: method.path,
...getRequestLayoutContext(method.preferredMethod),
hasRequiredParameters: method.hasRequiredParameters,
requiresAtLeastOneParameter: getAtLeastOneParameterNames(method).length > 0,
atLeastOneParameterNames: getAtLeastOneParameterNames(method),
hasPagination: method.hasPagination,
description: method.description,
responseDescription: method.responseDescription,
Expand Down
11 changes: 8 additions & 3 deletions seam/route.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
from typing import Any, Callable, TypeVar, cast
from typing import Any, Callable, Tuple, TypeVar, cast

F = TypeVar("F", bound=Callable)


def route_metadata(*, path: str, has_required_parameters: bool, has_pagination: bool):
def route_metadata(
*,
path: str,
has_pagination: bool,
at_least_one_parameter_names: Tuple[str, ...] = (),
):
"""Attach generated route metadata to a request callable."""

def decorate(request: F) -> F:
# Functions do not declare these attributes, so set them through Any.
route = cast(Any, request)
route.__seam_path__ = path
route.__seam_has_required_parameters__ = has_required_parameters
route.__seam_has_pagination__ = has_pagination
route.__seam_at_least_one_parameter_names__ = at_least_one_parameter_names
return request

return decorate
Loading
Loading