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
36 changes: 34 additions & 2 deletions lib/generators/python.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,33 @@ describe("Python generator", () => {
);
const media = createWidget && requestMedia(createWidget);
if (media) {
media[1].example = { description: null, name: "Widget", provider: "cloud", region: "us", settings: {} };
media[1].schema = {
anyOf: [
{
additionalProperties: false,
example: { labels: [{ bbox: [0.1, 0.2, 0.3, 0.4], classId: 0 }] },
properties: {
labels: {
items: {
properties: {
bbox: {
prefixItems: Array.from({ length: 4 }, () => ({ type: "number" })),
type: "array",
},
classId: { minimum: 0, type: "integer" },
},
required: ["classId"],
type: "object",
},
type: "array",
},
},
required: ["labels"],
type: "object",
},
{ properties: { metadata: { type: "object" } }, required: ["metadata"], type: "object" },
],
};
}
const echo = getOperations(source).find((operation) => operation.path === "/echo");
const echoMedia = echo && requestMedia(echo);
Expand All @@ -144,7 +170,7 @@ describe("Python generator", () => {
expect(sample?.source).toContain("response = client.widgets.retrieve(");
expect(sample?.source).toContain('widget_id="widget_123"');
const createSample = decorated.paths["/widgets"]?.post?.["x-codeSamples"]?.[0];
expect(createSample?.source).toContain('body={"description": None');
expect(createSample?.source).toContain('body={"labels": [{"bbox": [0.1, 0.2, 0.3, 0.4], "classId": 0}]}');
const echoSample = decorated.paths["/echo"]?.post?.["x-codeSamples"]?.[0];
expect(echoSample?.source).toContain("body=None");

Expand Down Expand Up @@ -614,6 +640,12 @@ describe("Python generator", () => {
).toBe("examplexxx");
expect(schemaExample(document, { type: "null" })).toBeNull();
expect(schemaExample(document, { type: ["null"] })).toBeNull();
expect(
schemaExample(document, {
prefixItems: Array.from({ length: 4 }, () => ({ type: "number" })),
type: "array",
}),
).toEqual([1, 1, 1, 1]);
expect(
schemaExample(document, {
allOf: [
Expand Down
32 changes: 28 additions & 4 deletions lib/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface JsonSchema {
multipleOf?: number;
nullable?: boolean;
oneOf?: JsonSchema[];
prefixItems?: JsonSchema[];
properties?: Record<string, JsonSchema>;
propertyNames?: JsonSchema;
pattern?: string;
Expand Down Expand Up @@ -536,12 +537,15 @@ export function pythonCodeSample(
bodyValue?: unknown,
): string {
const request = requestMedia(operation);
const generatedBody = request ? requestBodyExample(document, operation) : "";
const exampleBody =
bodyValue !== undefined
? bodyValue
: request?.[1].example !== undefined
? request[1].example
: schemaExample(document, request?.[1].schema);
: request?.[0].startsWith("text/")
? generatedBody
: JSON.parse(generatedBody || "null");
const bodyValues =
exampleBody && typeof exampleBody === "object" && !Array.isArray(exampleBody)
? (exampleBody as Record<string, unknown>)
Expand Down Expand Up @@ -1286,7 +1290,18 @@ function schemaMatches(document: OpenApiDocument, value: unknown, input: JsonSch
if (Array.isArray(value)) {
if (schema.minItems !== undefined && value.length < schema.minItems) return false;
if (schema.maxItems !== undefined && value.length > schema.maxItems) return false;
if (schema.items && value.some((item) => !schemaMatches(document, item, schema.items as JsonSchema, depth + 1)))
if (
schema.prefixItems?.some(
(item, index) => index < value.length && !schemaMatches(document, value[index], item, depth + 1),
)
)
return false;
if (
schema.items &&
value
.slice(schema.prefixItems?.length ?? 0)
.some((item) => !schemaMatches(document, item, schema.items as JsonSchema, depth + 1))
)
return false;
}
if (value && typeof value === "object" && !Array.isArray(value)) {
Expand Down Expand Up @@ -1495,8 +1510,17 @@ export function schemaExample(
if (schema.type === "null" || (Array.isArray(schema.type) && schema.type.every((value) => value === "null")))
return null;
if (type === "array") {
const length = schema.maxItems === 0 ? 0 : Math.max(1, schema.minItems ?? 0);
return Array.from({ length }, () => schemaExample(document, schema.items, depth + 1, name));
const prefix = (schema.prefixItems ?? []).map((item) => schemaExample(document, item, depth + 1, name));
const length = Math.min(
schema.maxItems ?? Number.POSITIVE_INFINITY,
Math.max(prefix.length, 1, schema.minItems ?? 0),
);
return [
...prefix.slice(0, length),
...Array.from({ length: Math.max(0, length - prefix.length) }, () =>
schemaExample(document, schema.items, depth + 1, name),
),
];
}
if (type === "boolean") return false;
if (type === "integer" || type === "number") {
Expand Down
Loading