Skip to content

Commit 0c0b8dd

Browse files
authored
Add all APIs without oneOfs (#5)
1 parent a429ffa commit 0c0b8dd

File tree

2,047 files changed

+93510
-1476
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

2,047 files changed

+93510
-1476
lines changed

.generator/schemas/v1/openapi.yaml

+18,630-33
Large diffs are not rendered by default.

.generator/schemas/v2/openapi.yaml

+7,557-504
Large diffs are not rendered by default.

.generator/src/generator/cli.py

+2
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ def cli(specs, output):
5454
env.globals["get_type_for_attribute"] = openapi.get_type_for_attribute
5555
env.globals["get_type_for_response"] = openapi.get_type_for_response
5656
env.globals["get_type_for_parameter"] = openapi.get_type_for_parameter
57+
env.globals["get_apis_and_versions"] = openapi.get_apis_and_versions
5758
env.globals["get_type"] = openapi.type_to_rust
5859
env.globals["get_default"] = openapi.get_default
60+
env.globals["get_deprecated"] = openapi.get_deprecated
5961
env.globals["get_container"] = openapi.get_container
6062
env.globals["get_container_type"] = openapi.get_container_type
6163
env.globals["get_type_at_path"] = openapi.get_type_at_path

.generator/src/generator/openapi.py

+34-20
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,21 @@ def get_name(schema, version=None):
2424
if hasattr(schema, "__reference__"):
2525
name = schema.__reference__["$ref"].split("/")[-1]
2626

27-
return f"crate::datadog{version.upper()}::model::{name}" if version else name
27+
return f"crate::datadog{version.upper()}::model::{name}" if version and name else name
2828

29+
def option_wrapper(name, option, nullable):
30+
if option:
31+
name = f"Option<{name}>"
32+
if nullable:
33+
name = f"Option<{name}>"
34+
return name
2935

3036
def type_to_rust(schema, alternative_name=None, render_nullable=False, render_option=True, render_box=False, version=None):
3137
"""Return Rust type name for the type."""
3238

3339
# special case for additionalProperties: true
34-
if schema is True:
35-
return "Value"
40+
if schema is True or schema == {}:
41+
return "serde_json::Value"
3642

3743
if "enum" not in schema:
3844
name = formatter.simple_type(schema, render_nullable=render_nullable, render_option=render_option)
@@ -42,12 +48,10 @@ def type_to_rust(schema, alternative_name=None, render_nullable=False, render_op
4248
name = get_name(schema, version)
4349
if name:
4450
if "enum" in schema:
45-
if render_box and schema.get("nullable", False):
46-
return f"Box<Option<{name}>>"
47-
return f"Option<{name}>" if render_option else name
51+
return option_wrapper(name, render_option, render_nullable)
4852
if not (schema.get("additionalProperties") and not schema.get("properties")) and schema.get("type", "object") == "object":
49-
inner_type = f"Box<{name}>" if render_box else name
50-
return f"Option<{inner_type}>" if render_option else inner_type
53+
name = f"Box<{name}>" if render_box else name
54+
return option_wrapper(name, render_option, render_nullable)
5155

5256
type_ = schema.get("type")
5357
if type_ is None:
@@ -70,20 +74,12 @@ def type_to_rust(schema, alternative_name=None, render_nullable=False, render_op
7074
name = f"Option<{name}>"
7175
if schema.get("nullable") and formatter.is_primitive(schema["items"]):
7276
name = formatter.simple_type(schema["items"], render_nullable=render_nullable, render_option=False)
73-
if render_nullable:
74-
# return f"datadog.{prefix}List[{name}]"
75-
# TODO: implement
76-
return "None"
77-
if render_option:
78-
return f"Option<Vec<{name}>>"
79-
return f"Vec<{name}>"
77+
return option_wrapper(f"Vec<{name}>", render_option, render_nullable)
8078
elif type_ == "object":
79+
name = "serde_json::Value"
8180
if "additionalProperties" in schema:
82-
# return "map[string]{}".format(type_to_rust(schema["additionalProperties"]))
83-
return "None"
84-
if render_option:
85-
return f"Option<Box<{alternative_name}>>"
86-
return f"Box<{alternative_name}>"
81+
name = type_to_rust(schema["additionalProperties"], render_nullable=render_nullable, render_option=False, version=version)
82+
return option_wrapper(f"std::collections::HashMap<String, {name}>", render_option, render_nullable)
8783

8884
raise ValueError(f"Unknown type {type_}")
8985

@@ -128,6 +124,16 @@ def responses_by_types(operation, version):
128124
return result.items()
129125

130126

127+
def get_apis_and_versions(all_apis):
128+
result = {}
129+
for version, api in all_apis.items():
130+
for name, _ in api.items():
131+
if name not in result:
132+
result[name] = []
133+
result[name].append(version)
134+
return result.items()
135+
136+
131137
def child_models(schema, alternative_name=None, seen=None, parent=None):
132138
seen = seen or set()
133139
current_name = get_name(schema)
@@ -418,6 +424,14 @@ def get_container(operation, attribute_path, container_name="o[0]"):
418424
return f'{container_name}.{formatter.attribute_path(attribute_path)}'
419425

420426

427+
def get_deprecated(schema):
428+
if "properties" in schema:
429+
for property in schema["properties"].values():
430+
if property.get("deprecated", False):
431+
return True
432+
return False
433+
434+
421435
def get_container_type(operation, attribute_path, stop=None):
422436
attrs = attribute_path.split(".")[:stop]
423437
for name, parameter in parameters(operation):

.generator/src/generator/templates/api.j2

+50-168
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{% include "partial_header.j2" %}
22

33
use reqwest;
4+
use serde::{Serialize, Deserialize};
45
use crate::datadog::*;
56

67
{% for path, method, operation in operations|sort(attribute="2.operationId", case_sensitive=True) %}
@@ -72,6 +73,7 @@ impl {{ structName }} {
7273
{% for path, method, operation in operations|sort(attribute="2.operationId", case_sensitive=True) %}
7374
{%- set httpMethod = method.upper() %}
7475
{%- set returnType = operation|return_type(version) %}
76+
{%- set formParameter = operation|form_parameter %}
7577
{% if operation.description is defined %}
7678
{{ operation.description | block_comment }}
7779
{%- endif %}
@@ -88,7 +90,7 @@ impl {{ structName }} {
8890
pub async fn {{operation.operationId | snake_case}}_with_http_info(&self{% for name, parameter in operation|parameters %}{% if loop.first %}, params: {{operation.operationId}}Params{% endif %}{% endfor %}) -> Result<ResponseContent<{% if returnType %}{{returnType}}{% else %}(){% endif %}>, Error<{{operation.operationId}}Error>> {
8991
let local_configuration = &self.config;
9092

91-
// unbox the parameters
93+
// unbox and build parameters
9294
{%- for name, parameter in operation|parameters %}
9395
let {{name|variable_name}} = params.{{name|variable_name}};
9496
{%- endfor %}
@@ -106,80 +108,40 @@ impl {{ structName }} {
106108
{%- endif %}
107109
{% endfor %});
108110
let mut local_req_builder = local_client.request(reqwest::Method::{{ httpMethod }}, local_uri_str.as_str());
109-
{#
110-
{{#queryParams}}
111-
{{#required}}
112-
{{#isArray}}
113-
local_req_builder = match "{{collectionFormat}}" {
114-
"multi" => local_req_builder.query(&{{{paramName}}}.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
115-
_ => local_req_builder.query(&[("{{{baseName}}}", &{{{paramName}}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
111+
112+
{% for name, parameter in operation|parameters if parameter.in == "query" %}
113+
{%- set schema = parameter | parameter_schema %}
114+
{%- if parameter.required and schema.type == "array" %}
115+
local_req_builder = local_req_builder.query(&[("{{name}}", &{{name|variable_name}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]);
116+
{%- elif not parameter.required and schema.type == "array" %}
117+
if let Some(ref local) = {{name|variable_name}} {
118+
local_req_builder = local_req_builder.query(&[("{{name}}", &local.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]);
116119
};
117-
{{/isArray}}
118-
{{^isArray}}
119-
{{^isNullable}}
120-
local_req_builder = local_req_builder.query(&[("{{{baseName}}}", &{{{paramName}}}.to_string())]);
121-
{{/isNullable}}
122-
{{#isNullable}}
123-
{{#isDeepObject}}
124-
if let Some(ref local_str) = {{{paramName}}} {
125-
let params = crate::apis::parse_deep_object("{{{baseName}}}", local_str);
126-
local_req_builder = local_req_builder.query(&params);
120+
{%- elif parameter.required %}
121+
local_req_builder = local_req_builder.query(&[("{{name}}", &{{name|variable_name}}.to_string())]);
122+
{%- else %}
123+
if let Some(ref local_str) = {{name|variable_name}} {
124+
local_req_builder = local_req_builder.query(&[("{{name}}", &local_str.to_string())]);
127125
};
128-
{{/isDeepObject}}
129-
{{^isDeepObject}}
130-
if let Some(ref local_str) = {{{paramName}}} {
131-
local_req_builder = local_req_builder.query(&[("{{{baseName}}}", &local_str.to_string())]);
126+
{%- endif %}
127+
{%- endfor %}
128+
129+
{% for name, parameter in operation|parameters if parameter.in == "header" %}
130+
{%- if not parameter.required %}
131+
if let Some(ref local) = {{name|variable_name}} {
132+
local_req_builder = local_req_builder.header("{{name}}", &local.to_string());
132133
};
133-
{{/isDeepObject}}
134-
{{/isNullable}}
135-
{{/isArray}}
136-
{{/required}}
137-
{{^required}}
138-
if let Some(ref local_str) = {{{paramName}}} {
139-
{{#isArray}}
140-
local_req_builder = match "{{collectionFormat}}" {
141-
"multi" => local_req_builder.query(&local_str.into_iter().map(|p| ("{{{baseName}}}".to_owned(), p.to_string())).collect::<Vec<(std::string::String, std::string::String)>>()),
142-
_ => local_req_builder.query(&[("{{{baseName}}}", &local_str.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(",").to_string())]),
143-
};
144-
{{/isArray}}
145-
{{^isArray}}
146-
{{#isDeepObject}}
147-
let params = crate::apis::parse_deep_object("{{{baseName}}}", local_str);
148-
local_req_builder = local_req_builder.query(&params);
149-
{{/isDeepObject}}
150-
{{^isDeepObject}}
151-
local_req_builder = local_req_builder.query(&[("{{{baseName}}}", &local_str.to_string())]);
152-
{{/isDeepObject}}
153-
{{/isArray}}
154-
}
155-
{{/required}}
156-
{{/queryParams}}
157-
#}
134+
{%- else %}
135+
local_req_builder = local_req_builder.header("{{name}}", &{{name|variable_name}}.to_string());
136+
{%- endif %}
137+
{%- endfor %}
138+
139+
// build user agent
158140
if let Some(ref local_user_agent) = local_configuration.user_agent {
159141
local_req_builder = local_req_builder.header(reqwest::header::USER_AGENT, local_user_agent.clone());
160142
}
161-
{#
162-
{{#hasHeaderParams}}
163-
{{#headerParams}}
164-
{{#required}}
165-
{{^isNullable}}
166-
local_req_builder = local_req_builder.header("{{{baseName}}}", {{{paramName}}}{{#isArray}}.join(","){{/isArray}}.to_string());
167-
{{/isNullable}}
168-
{{#isNullable}}
169-
match {{{paramName}}} {
170-
Some(local_param_value) => { local_req_builder = local_req_builder.header("{{{baseName}}}", local_param_value{{#isArray}}.join(","){{/isArray}}.to_string()); },
171-
None => { local_req_builder = local_req_builder.header("{{{baseName}}}", ""); },
172-
}
173-
{{/isNullable}}
174-
{{/required}}
175-
{{^required}}
176-
if let Some(local_param_value) = {{{paramName}}} {
177-
local_req_builder = local_req_builder.header("{{{baseName}}}", local_param_value{{#isArray}}.join(","){{/isArray}}.to_string());
178-
}
179-
{{/required}}
180-
{{/headerParams}}
181-
{{/hasHeaderParams}}
182-
#}
143+
144+
// build auth
183145
{%- set authMethods = operation.security if "security" in operation else openapi.security %}
184146
{%- if authMethods %}
185147
{%- for authMethod in authMethods %}
@@ -193,109 +155,29 @@ impl {{ structName }} {
193155
{%- endfor %}
194156
{%- endfor %}
195157
{%- endif %}
196-
{#
197-
{{#isMultipart}}
198-
{{#hasFormParams}}
158+
159+
{% if formParameter %}
160+
// build form parameters
161+
{%- if formParameter.required %}
199162
let mut local_form = reqwest::multipart::Form::new();
200-
{{#formParams}}
201-
{{#isFile}}
202-
{{^supportAsync}}
203-
{{#required}}
204-
{{^isNullable}}
205-
local_form = local_form.file("{{{baseName}}}", {{{paramName}}})?;
206-
{{/isNullable}}
207-
{{#isNullable}}
208-
match {{{paramName}}} {
209-
Some(local_param_value) => { local_form = local_form.file("{{{baseName}}}", local_param_value)?; },
210-
None => { unimplemented!("Required nullable form file param not supported"); },
211-
}
212-
{{/isNullable}}
213-
{{/required}}
214-
{{^required}}
215-
if let Some(local_param_value) = {{{paramName}}} {
216-
local_form = local_form.file("{{{baseName}}}", local_param_value)?;
217-
}
218-
{{/required}}
219-
// TODO: support file upload for '{{{baseName}}}' parameter
220-
221-
{{/isFile}}
222-
{{^isFile}}
223-
{{#required}}
224-
{{^isNullable}}
225-
local_form = local_form.text("{{{baseName}}}", {{{paramName}}}{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string());
226-
{{/isNullable}}
227-
{{#isNullable}}
228-
match {{{paramName}}} {
229-
Some(local_param_value) => { local_form = local_form.text("{{{baseName}}}", local_param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string()); },
230-
None => { local_form = local_form.text("{{{baseName}}}", ""); },
231-
}
232-
{{/isNullable}}
233-
{{/required}}
234-
{{^required}}
235-
if let Some(local_param_value) = {{{paramName}}} {
236-
local_form = local_form.text("{{{baseName}}}", local_param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string());
237-
}
238-
{{/required}}
239-
{{/isFile}}
240-
{{/formParams}}
163+
local_form = local_form.part("{{formParameter.name}}", reqwest::multipart::Part::bytes({{formParameter.name}}).file_name("{{formParameter.name}}"));
241164
local_req_builder = local_req_builder.multipart(local_form);
242-
{{/hasFormParams}}
243-
{{/isMultipart}}
244-
{{^isMultipart}}
245-
{{#hasFormParams}}
246-
let mut local_form_params = std::collections::HashMap::new();
247-
{{#formParams}}
248-
{{#isFile}}
249-
{{#required}}
250-
{{^isNullable}}
251-
local_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content"));
252-
{{/isNullable}}
253-
{{#isNullable}}
254-
match {{{paramName}}} {
255-
Some(local_param_value) => { local_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content")); },
256-
None => { unimplemented!("Required nullable file form param not supported with x-www-form-urlencoded content"); },
257-
}
258-
{{/isNullable}}
259-
{{/required}}
260-
{{^required}}
261-
if let Some(local_param_value) = {{{paramName}}} {
262-
local_form_params.insert("{{{baseName}}}", unimplemented!("File form param not supported with x-www-form-urlencoded content"));
263-
}
264-
{{/required}}
265-
{{/isFile}}
266-
{{^isFile}}
267-
{{#required}}
268-
{{^isNullable}}
269-
local_form_params.insert("{{{baseName}}}", {{{paramName}}}{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string());
270-
{{/isNullable}}
271-
{{#isNullable}}
272-
match {{{paramName}}} {
273-
Some(local_param_value) => { local_form_params.insert("{{{baseName}}}", local_param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string()); },
274-
None => { local_form_params.insert("{{{baseName}}}", ""); },
275-
}
276-
{{/isNullable}}
277-
{{/required}}
278-
{{^required}}
279-
if let Some(local_param_value) = {{{paramName}}} {
280-
local_form_params.insert("{{{baseName}}}", local_param_value{{#isArray}}.into_iter().map(|p| p.to_string()).collect::<Vec<String>>().join(","){{/isArray}}.to_string());
281-
}
282-
{{/required}}
283-
{{/isFile}}
284-
{{/formParams}}
285-
local_req_builder = local_req_builder.form(&local_form_params);
286-
{{/hasFormParams}}
287-
{{/isMultipart}}
288-
#}
289-
{%- if operation.requestBody is defined and not formParameter %}
290-
{%- set isBodyOptional = False if "required" in operation.requestBody and operation.requestBody.required else True %}
291-
// body params
292-
{%- if isBodyOptional %}
293-
if {{operation.get("x-codegen-request-body-name", "body")|variable_name}}.is_some() {
294-
local_req_builder = local_req_builder.json(&{{operation.get("x-codegen-request-body-name", "body")|variable_name}}.unwrap());
295-
}
296165
{%- else %}
297-
local_req_builder = local_req_builder.json(&{{operation.get("x-codegen-request-body-name", "body")|variable_name}});
166+
if let Some({{formParameter.name}}) = {{formParameter.name}} {
167+
let mut local_form = reqwest::multipart::Form::new();
168+
local_form = local_form.part("{{formParameter.name}}", reqwest::multipart::Part::bytes({{formParameter.name}}).file_name("{{formParameter.name}}"));
169+
local_req_builder = local_req_builder.multipart(local_form);
170+
};
171+
{%- endif %}
298172
{%- endif %}
173+
174+
{%- if operation.requestBody is defined and not formParameter %}
175+
// build body parameters
176+
let output = Vec::new();
177+
let mut ser = serde_json::Serializer::with_formatter(output, DDFormatter);
178+
if {{operation.get("x-codegen-request-body-name", "body")|variable_name}}.serialize(&mut ser).is_ok() {
179+
local_req_builder = local_req_builder.body(ser.into_inner());
180+
}
299181
{%- endif %}
300182

301183
let local_req = local_req_builder.build()?;

0 commit comments

Comments
 (0)