From 7a23bdceb4696339b2ab00bf76d2dcf680803e7c Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 7 Mar 2018 00:20:46 +0800 Subject: [PATCH 001/180] renaming for openapi-generator --- README.mustache | 125 ++++++++ __init__api.mustache | 7 + __init__model.mustache | 10 + __init__package.mustache | 17 + __init__test.mustache | 0 api.mustache | 214 +++++++++++++ api_client.mustache | 627 +++++++++++++++++++++++++++++++++++++ api_doc.mustache | 85 +++++ api_test.mustache | 37 +++ asyncio/rest.mustache | 260 +++++++++++++++ configuration.mustache | 260 +++++++++++++++ git_push.sh.mustache | 52 +++ gitignore.mustache | 64 ++++ model.mustache | 219 +++++++++++++ model_doc.mustache | 11 + model_test.mustache | 35 +++ partial_header.mustache | 13 + requirements.mustache | 5 + rest.mustache | 314 +++++++++++++++++++ setup.mustache | 43 +++ test-requirements.mustache | 11 + tornado/rest.mustache | 255 +++++++++++++++ tox.mustache | 20 ++ travis.mustache | 14 + 24 files changed, 2698 insertions(+) create mode 100644 README.mustache create mode 100644 __init__api.mustache create mode 100644 __init__model.mustache create mode 100644 __init__package.mustache create mode 100644 __init__test.mustache create mode 100644 api.mustache create mode 100644 api_client.mustache create mode 100644 api_doc.mustache create mode 100644 api_test.mustache create mode 100644 asyncio/rest.mustache create mode 100644 configuration.mustache create mode 100755 git_push.sh.mustache create mode 100644 gitignore.mustache create mode 100644 model.mustache create mode 100644 model_doc.mustache create mode 100644 model_test.mustache create mode 100644 partial_header.mustache create mode 100644 requirements.mustache create mode 100644 rest.mustache create mode 100644 setup.mustache create mode 100644 test-requirements.mustache create mode 100644 tornado/rest.mustache create mode 100644 tox.mustache create mode 100644 travis.mustache diff --git a/README.mustache b/README.mustache new file mode 100644 index 0000000000..c1355be778 --- /dev/null +++ b/README.mustache @@ -0,0 +1,125 @@ +# {{{projectName}}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +This Python package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage +### pip install + +If the python package is hosted on Github, you can install directly from Github + +```sh +pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git +``` +(you may need to run `pip` with root permission: `sudo pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git`) + +Then import the package: +```python +import {{{packageName}}} +``` + +### Setuptools + +Install via [Setuptools](http://pypi.python.org/pypi/setuptools). + +```sh +python setup.py install --user +``` +(or `sudo python setup.py install` to install the package for all users) + +Then import the package: +```python +import {{{packageName}}} +``` + +## Getting Started + +Please follow the [installation procedure](#installation--usage) and then run the following: + +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +{{{packageName}}}.configuration.username = 'YOUR_USERNAME' +{{{packageName}}}.configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +{{{packageName}}}.configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# {{{packageName}}}.configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +{{{packageName}}}.configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} +{{/hasAuthMethods}} +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} All endpoints do not require authorization. +{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} +{{#authMethods}}## {{{name}}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/__init__api.mustache b/__init__api.mustache new file mode 100644 index 0000000000..db658a10fa --- /dev/null +++ b/__init__api.mustache @@ -0,0 +1,7 @@ +from __future__ import absolute_import + +# flake8: noqa + +# import apis into api package +{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/__init__model.mustache b/__init__model.mustache new file mode 100644 index 0000000000..2266b3d17f --- /dev/null +++ b/__init__model.mustache @@ -0,0 +1,10 @@ +# coding: utf-8 + +# flake8: noqa +{{>partial_header}} + +from __future__ import absolute_import + +# import models into model package +{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}} +{{/models}} diff --git a/__init__package.mustache b/__init__package.mustache new file mode 100644 index 0000000000..cd42506f54 --- /dev/null +++ b/__init__package.mustache @@ -0,0 +1,17 @@ +# coding: utf-8 + +# flake8: noqa + +{{>partial_header}} + +from __future__ import absolute_import + +# import apis into sdk package +{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}}{{/apiInfo}} +# import ApiClient +from {{packageName}}.api_client import ApiClient +from {{packageName}}.configuration import Configuration +# import models into sdk package +{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} +{{/model}}{{/models}} \ No newline at end of file diff --git a/__init__test.mustache b/__init__test.mustache new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api.mustache b/api.mustache new file mode 100644 index 0000000000..a65946f578 --- /dev/null +++ b/api.mustache @@ -0,0 +1,214 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from {{packageName}}.api_client import ApiClient + + +{{#operations}} +class {{classname}}(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client +{{#operation}} + + def {{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async=True +{{#sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} +{{^sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} + >>> result = thread.get() + + :param async bool +{{#allParams}} + :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} +{{/allParams}} + :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async'): + return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 + else: + (data) = self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 + return data + + def {{operationId}}_with_http_info(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async=True +{{#sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} +{{^sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} + >>> result = thread.get() + + :param async bool +{{#allParams}} + :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/optional}} +{{/allParams}} + :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, + returns the request thread. + """ + + all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 + all_params.append('async') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method {{operationId}}" % key + ) + params[key] = val + del params['kwargs'] +{{#allParams}} +{{#required}} + # verify the required parameter '{{paramName}}' is set + if ('{{paramName}}' not in params or + params['{{paramName}}'] is None): + raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 +{{/required}} +{{/allParams}} + +{{#allParams}} +{{#hasValidation}} + {{#maxLength}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) > {{maxLength}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 + {{/maxLength}} + {{#minLength}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) < {{minLength}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 + {{/minLength}} + {{#maximum}} + if '{{paramName}}' in params and params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 + {{/maximum}} + {{#minimum}} + if '{{paramName}}' in params and params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 + {{/minimum}} + {{#pattern}} + if '{{paramName}}' in params and not re.search('{{{vendorExtensions.x-regex}}}', params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 + {{/pattern}} + {{#maxItems}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) > {{maxItems}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 + {{/maxItems}} + {{#minItems}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) < {{minItems}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 + {{/minItems}} +{{/hasValidation}} +{{#-last}} +{{/-last}} +{{/allParams}} + collection_formats = {} + + path_params = {} +{{#pathParams}} + if '{{paramName}}' in params: + path_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/pathParams}} + + query_params = [] +{{#queryParams}} + if '{{paramName}}' in params: + query_params.append(('{{baseName}}', params['{{paramName}}'])){{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/queryParams}} + + header_params = {} +{{#headerParams}} + if '{{paramName}}' in params: + header_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/headerParams}} + + form_params = [] + local_var_files = {} +{{#formParams}} + if '{{paramName}}' in params: + {{#notFile}}form_params.append(('{{baseName}}', params['{{paramName}}'])){{/notFile}}{{#isFile}}local_var_files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/formParams}} + + body_params = None +{{#bodyParam}} + if '{{paramName}}' in params: + body_params = params['{{paramName}}'] +{{/bodyParam}} + {{#hasProduces}} + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + [{{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) # noqa: E501 + + {{/hasProduces}} + {{#hasConsumes}} + # HTTP header `Content-Type` + header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 + [{{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) # noqa: E501 + + {{/hasConsumes}} + # Authentication setting + auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + + return self.api_client.call_api( + '{{{path}}}', '{{httpMethod}}', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 + auth_settings=auth_settings, + async=params.get('async'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) +{{/operation}} +{{/operations}} diff --git a/api_client.mustache b/api_client.mustache new file mode 100644 index 0000000000..a6df41b072 --- /dev/null +++ b/api_client.mustache @@ -0,0 +1,627 @@ +# coding: utf-8 +{{>partial_header}} +from __future__ import absolute_import + +import datetime +import json +import mimetypes +from multiprocessing.pool import ThreadPool +import os +import re +import tempfile + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import quote +{{#tornado}} +import tornado.gen +{{/tornado}} + +from {{packageName}}.configuration import Configuration +import {{modelPackage}} +from {{packageName}} import rest + + +class ApiClient(object): + """Generic API client for Swagger client library builds. + + Swagger generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the Swagger + templates. + + NOTE: This class is auto generated by the swagger code generator program. + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + """ + + PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types + NATIVE_TYPES_MAPPING = { + 'int': int, + 'long': int if six.PY3 else long, # noqa: F821 + 'float': float, + 'str': str, + 'bool': bool, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'object': object, + } + + def __init__(self, configuration=None, header_name=None, header_value=None, + cookie=None): + if configuration is None: + configuration = Configuration() + self.configuration = configuration + + self.pool = ThreadPool() + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{packageVersion}}}/python{{/httpUserAgent}}' + + def __del__(self): + self.pool.close() + self.pool.join() + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + {{#tornado}} + @tornado.gen.coroutine + {{/tornado}} + {{#asyncio}}async {{/asyncio}}def __call_api( + self, resource_path, method, path_params=None, + query_params=None, header_params=None, body=None, post_params=None, + files=None, response_type=None, auth_settings=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) + header_params = dict(self.parameters_to_tuples(header_params, + collection_formats)) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples(path_params, + collection_formats) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # query parameters + if query_params: + query_params = self.sanitize_for_serialization(query_params) + query_params = self.parameters_to_tuples(query_params, + collection_formats) + + # post parameters + if post_params or files: + post_params = self.prepare_post_parameters(post_params, files) + post_params = self.sanitize_for_serialization(post_params) + post_params = self.parameters_to_tuples(post_params, + collection_formats) + + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + url = self.configuration.host + resource_path + + # perform request and return response + response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + + self.last_response = response_data + + return_data = response_data + if _preload_content: + # deserialize response data + if response_type: + return_data = self.deserialize(response_data, response_type) + else: + return_data = None + +{{^tornado}} + if _return_http_data_only: + return (return_data) + else: + return (return_data, response_data.status, + response_data.getheaders()) +{{/tornado}} +{{#tornado}} + if _return_http_data_only: + raise tornado.gen.Return(return_data) + else: + raise tornado.gen.Return((return_data, response_data.status, + response_data.getheaders())) +{{/tornado}} + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is swagger model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, list): + return [self.sanitize_for_serialization(sub_obj) + for sub_obj in obj] + elif isinstance(obj, tuple): + return tuple(self.sanitize_for_serialization(sub_obj) + for sub_obj in obj) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + + if isinstance(obj, dict): + obj_dict = obj + else: + # Convert model obj to dict except + # attributes `swagger_types`, `attribute_map` + # and attributes which value is not None. + # Convert attribute name to json key in + # model definition for request. + obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) + for attr, _ in six.iteritems(obj.swagger_types) + if getattr(obj, attr) is not None} + + return {key: self.sanitize_for_serialization(val) + for key, val in six.iteritems(obj_dict)} + + def deserialize(self, response, response_type): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + + :return: deserialized object. + """ + # handle file downloading + # save response body into a tmp file and return the instance + if response_type == "file": + return self.__deserialize_file(response) + + # fetch data from response object + try: + data = json.loads(response.data) + except ValueError: + data = response.data + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if type(klass) == str: + if klass.startswith('list['): + sub_kls = re.match('list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) + for sub_data in data] + + if klass.startswith('dict('): + sub_kls = re.match('dict\(([^,]*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) + for k, v in six.iteritems(data)} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr({{modelPackage}}, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object(data) + elif klass == datetime.date: + return self.__deserialize_date(data) + elif klass == datetime.datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def call_api(self, resource_path, method, + path_params=None, query_params=None, header_params=None, + body=None, post_params=None, files=None, + response_type=None, auth_settings=None, async=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + """Makes the HTTP request (synchronous) and returns deserialized data. + + To make an async request, set the async parameter. + + :param resource_path: Path to method endpoint. + :param method: Method to call. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param response: Response data type. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param async bool: execute request asynchronously + :param _return_http_data_only: response data without head status code + and headers + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: + If async parameter is True, + the request will be called asynchronously. + The method will return the request thread. + If parameter async is False or missing, + then the method will return the response directly. + """ + if not async: + return self.__call_api(resource_path, method, + path_params, query_params, header_params, + body, post_params, files, + response_type, auth_settings, + _return_http_data_only, collection_formats, + _preload_content, _request_timeout) + else: + thread = self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, query_params, + header_params, body, + post_params, files, + response_type, auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, _request_timeout)) + return thread + + def request(self, method, url, query_params=None, headers=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + """Makes the HTTP request using RESTClient.""" + if method == "GET": + return self.rest_client.GET(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "HEAD": + return self.rest_client.HEAD(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "OPTIONS": + return self.rest_client.OPTIONS(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "POST": + return self.rest_client.POST(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PUT": + return self.rest_client.PUT(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PATCH": + return self.rest_client.PATCH(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "DELETE": + return self.rest_client.DELETE(url, + query_params=query_params, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + else: + raise ValueError( + "http method must be `GET`, `HEAD`, `OPTIONS`," + " `POST`, `PATCH`, `PUT` or `DELETE`." + ) + + def parameters_to_tuples(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: Parameters as list of tuples, collections formatted + """ + new_params = [] + if collection_formats is None: + collection_formats = {} + for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(str(value) for value in v))) + else: + new_params.append((k, v)) + return new_params + + def prepare_post_parameters(self, post_params=None, files=None): + """Builds form parameters. + + :param post_params: Normal form parameters. + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + + if post_params: + params = post_params + + if files: + for k, v in six.iteritems(files): + if not v: + continue + file_names = v if type(v) is list else [v] + for n in file_names: + with open(n, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([k, tuple([filename, filedata, mimetype])])) + + return params + + def select_header_accept(self, accepts): + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return + + accepts = [x.lower() for x in accepts] + + if 'application/json' in accepts: + return 'application/json' + else: + return ', '.join(accepts) + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return 'application/json' + + content_types = [x.lower() for x in content_types] + + if 'application/json' in content_types or '*/*' in content_types: + return 'application/json' + else: + return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param querys: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = self.configuration.auth_settings().get(auth) + if auth_setting: + if not auth_setting['value']: + continue + elif auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "wb") as f: + f.write(response.data) + + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return six.text_type(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return a original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + try: + from dateutil.parser import parse + return parse(string).date() + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason="Failed to parse `{0}` as date object".format(string) + ) + + def __deserialize_datatime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as datetime object" + .format(string) + ) + ) + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + if not klass.swagger_types and not hasattr(klass, + 'get_real_child_model'): + return data + + kwargs = {} + if klass.swagger_types is not None: + for attr, attr_type in six.iteritems(klass.swagger_types): + if (data is not None and + klass.attribute_map[attr] in data and + isinstance(data, (list, dict))): + value = data[klass.attribute_map[attr]] + kwargs[attr] = self.__deserialize(value, attr_type) + + instance = klass(**kwargs) + + if hasattr(instance, 'get_real_child_model'): + klass_name = instance.get_real_child_model(data) + if klass_name: + instance = self.__deserialize(data, klass_name) + return instance diff --git a/api_doc.mustache b/api_doc.mustache new file mode 100644 index 0000000000..32c26d929d --- /dev/null +++ b/api_doc.mustache @@ -0,0 +1,85 @@ +# {{packageName}}.{{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} +# **{{{operationId}}}** +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{paramName}}}{{/required}}{{^required}}{{{paramName}}}={{{paramName}}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{{summary}}}{{#notes}} + +{{{notes}}}{{/notes}} + +### Example +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} +{{^hasAuthMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | {{^required}}[optional] {{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +{{/operation}} +{{/operations}} diff --git a/api_test.mustache b/api_test.mustache new file mode 100644 index 0000000000..90fafc15f3 --- /dev/null +++ b/api_test.mustache @@ -0,0 +1,37 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +import {{packageName}} +from {{apiPackage}}.{{classVarName}} import {{classname}} # noqa: E501 +from {{packageName}}.rest import ApiException + + +class {{#operations}}Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" + + def setUp(self): + self.api = {{apiPackage}}.{{classVarName}}.{{classname}}() # noqa: E501 + + def tearDown(self): + pass + + {{#operation}} + def test_{{operationId}}(self): + """Test case for {{{operationId}}} + +{{#summary}} + {{{summary}}} # noqa: E501 +{{/summary}} + """ + pass + + {{/operation}} +{{/operations}} + +if __name__ == '__main__': + unittest.main() diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache new file mode 100644 index 0000000000..39003abfbf --- /dev/null +++ b/asyncio/rest.mustache @@ -0,0 +1,260 @@ +# coding: utf-8 + +{{>partial_header}} + +import io +import json +import logging +import re +import ssl + +import aiohttp +import certifi +# python 2 and python 3 compatibility library +from six.moves.urllib.parse import urlencode + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp, data): + self.aiohttp_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = data + + def getheaders(self): + """Returns a CIMultiDictProxy of the response headers.""" + return self.aiohttp_response.headers + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.aiohttp_response.headers.get(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=4): + # maxsize is number of requests to host that are allowed in parallel + # ca_certs vs cert_file vs key_file + # http://stackoverflow.com/a/23957365/2985775 + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + ssl_context = ssl.create_default_context(cafile=ca_certs) + if configuration.cert_file: + ssl_context.load_cert_chain( + configuration.cert_file, keyfile=configuration.key_file + ) + + connector = aiohttp.TCPConnector( + limit=maxsize, + ssl_context=ssl_context, + verify_ssl=configuration.verify_ssl + ) + + # https pool manager + if configuration.proxy: + self.pool_manager = aiohttp.ClientSession( + connector=connector, + proxy=configuration.proxy + ) + else: + self.pool_manager = aiohttp.ClientSession( + connector=connector + ) + + async def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Execute request + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: this is a non-applicable field for + the AiohttpClient. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + timeout = _request_timeout or 5 * 60 + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + args = { + "method": method, + "url": url, + "timeout": timeout, + "headers": headers + } + + if query_params: + args["url"] += '?' + urlencode(query_params) + + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if re.search('json', headers['Content-Type'], re.IGNORECASE): + if body is not None: + body = json.dumps(body) + args["data"] = body + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + args["data"] = aiohttp.FormData(post_params) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by aiohttp + del headers['Content-Type'] + data = aiohttp.FormData() + for param in post_params: + k, v = param + if isinstance(v, tuple) and len(v) == 3: + data.add_field(k, + value=v[1], + filename=v[0], + content_type=v[2]) + else: + data.add_field(k, v) + args["data"] = data + + # Pass a `bytes` parameter directly in the body to support + # other content types than Json when `body` argument is provided + # in serialized form + elif isinstance(body, bytes): + args["data"] = body + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + + async with self.pool_manager.request(**args) as r: + data = await r.text() + r = RESTResponse(r, data) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + async def GET(self, url, headers=None, query_params=None, + _preload_content=True, _request_timeout=None): + return (await self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params)) + + async def HEAD(self, url, headers=None, query_params=None, + _preload_content=True, _request_timeout=None): + return (await self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params)) + + async def OPTIONS(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return (await self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def POST(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return (await self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def PATCH(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\nReason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/configuration.mustache b/configuration.mustache new file mode 100644 index 0000000000..84e6ad4d20 --- /dev/null +++ b/configuration.mustache @@ -0,0 +1,260 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import copy +import logging +import multiprocessing +import sys +import urllib3 + +import six +from six.moves import http_client as httplib + + +class TypeWithDefault(type): + def __init__(cls, name, bases, dct): + super(TypeWithDefault, cls).__init__(name, bases, dct) + cls._default = None + + def __call__(cls): + if cls._default is None: + cls._default = type.__call__(cls) + return copy.copy(cls._default) + + def set_default(cls, default): + cls._default = copy.copy(default) + + +class Configuration(six.with_metaclass(TypeWithDefault, object)): + """NOTE: This class is auto generated by the swagger code generator program. + + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + """ + + def __init__(self): + """Constructor""" + # Default Base url + self.host = "{{{basePath}}}" + # Temp file folder for downloading files + self.temp_folder_path = None + + # Authentication Settings + # dict to store API key(s) + self.api_key = {} + # dict to store API prefix (e.g. Bearer) + self.api_key_prefix = {} + # Username for HTTP basic authentication + self.username = "" + # Password for HTTP basic authentication + self.password = "" +{{#authMethods}}{{#isOAuth}} + # access token for OAuth + self.access_token = "" +{{/isOAuth}}{{/authMethods}} + # Logging Settings + self.logger = {} + self.logger["package_logger"] = logging.getLogger("{{packageName}}") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + # Log format + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + # Log stream handler + self.logger_stream_handler = None + # Log file handler + self.logger_file_handler = None + # Debug file location + self.logger_file = None + # Debug switch + self.debug = False + + # SSL/TLS verification + # Set this to false to skip verifying SSL certificate when calling API + # from https server. + self.verify_ssl = True + # Set this to customize the certificate file to verify the peer. + self.ssl_ca_cert = None + # client certificate file + self.cert_file = None + # client key file + self.key_file = None + # Set this to True/False to enable/disable SSL hostname verification. + self.assert_hostname = None + + # urllib3 connection pool's maximum number of connections saved + # per pool. urllib3 uses 1 connection as default value, but this is + # not the best value when you are making a lot of possibly parallel + # requests to the same host, which is often the case here. + # cpu_count * 5 is used as default value to increase performance. + self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + + # Proxy URL + self.proxy = None + # Safe chars for path_param + self.safe_chars_for_path_param = '' + + @property + def logger_file(self): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_file_handler) + if self.logger_stream_handler: + logger.removeHandler(self.logger_stream_handler) + else: + # If not set logging file, + # then add stream handler and remove file handler. + self.logger_stream_handler = logging.StreamHandler() + self.logger_stream_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_stream_handler) + if self.logger_file_handler: + logger.removeHandler(self.logger_file_handler) + + @property + def debug(self): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.DEBUG) + # turn on httplib debug + httplib.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.WARNING) + # turn off httplib debug + httplib.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier): + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :return: The token for api key authentication. + """ + if (self.api_key.get(identifier) and + self.api_key_prefix.get(identifier)): + return self.api_key_prefix[identifier] + ' ' + self.api_key[identifier] # noqa: E501 + elif self.api_key.get(identifier): + return self.api_key[identifier] + + def get_basic_auth_token(self): + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + return urllib3.util.make_headers( + basic_auth=self.username + ':' + self.password + ).get('authorization') + + def auth_settings(self): + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + return { +{{#authMethods}} +{{#isApiKey}} + '{{name}}': + { + 'type': 'api_key', + 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': self.get_api_key_with_prefix('{{keyParamName}}') + }, +{{/isApiKey}} +{{#isBasic}} + '{{name}}': + { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': self.get_basic_auth_token() + }, +{{/isBasic}}{{#isOAuth}} + '{{name}}': + { + 'type': 'oauth2', + 'in': 'header', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + }, +{{/isOAuth}}{{/authMethods}} + } + + def to_debug_report(self): + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: {{version}}\n"\ + "SDK Package Version: {{packageVersion}}".\ + format(env=sys.platform, pyversion=sys.version) diff --git a/git_push.sh.mustache b/git_push.sh.mustache new file mode 100755 index 0000000000..a2d7523483 --- /dev/null +++ b/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/gitignore.mustache b/gitignore.mustache new file mode 100644 index 0000000000..a655050c26 --- /dev/null +++ b/gitignore.mustache @@ -0,0 +1,64 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/model.mustache b/model.mustache new file mode 100644 index 0000000000..5668793b3f --- /dev/null +++ b/model.mustache @@ -0,0 +1,219 @@ +# coding: utf-8 + +{{>partial_header}} + +import pprint +import re # noqa: F401 + +import six +{{#imports}}{{#-first}} +{{/-first}} +{{import}} # noqa: F401,E501 +{{/imports}} + + +{{#models}} +{{#model}} +class {{classname}}(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """{{#allowableValues}} + + """ + allowed enum values + """ +{{#enumVars}} + {{name}} = {{{value}}}{{^-last}} +{{/-last}} +{{/enumVars}}{{/allowableValues}} + + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { +{{#vars}} + '{{name}}': '{{{datatype}}}'{{#hasMore}},{{/hasMore}} +{{/vars}} + } + + attribute_map = { +{{#vars}} + '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} +{{/vars}} + } +{{#discriminator}} + + discriminator_value_class_map = { + {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, + {{/-last}}{{/children}} + } +{{/discriminator}} + + def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 + """{{classname}} - a model defined in Swagger""" # noqa: E501 +{{#vars}}{{#-first}} +{{/-first}} + self._{{name}} = None +{{/vars}} + self.discriminator = {{#discriminator}}'{{discriminator}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} +{{#vars}}{{#-first}} +{{/-first}} +{{#required}} + self.{{name}} = {{name}} +{{/required}} +{{^required}} + if {{name}} is not None: + self.{{name}} = {{name}} +{{/required}} +{{/vars}} + +{{#vars}} + @property + def {{name}}(self): + """Gets the {{name}} of this {{classname}}. # noqa: E501 + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :return: The {{name}} of this {{classname}}. # noqa: E501 + :rtype: {{datatype}} + """ + return self._{{name}} + + @{{name}}.setter + def {{name}}(self, {{name}}): + """Sets the {{name}} of this {{classname}}. + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 + :type: {{datatype}} + """ +{{#required}} + if {{name}} is None: + raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 +{{/required}} +{{#isEnum}} +{{#isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 +{{#isListContainer}} + if not set({{{name}}}).issubset(set(allowed_values)): + raise ValueError( + "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isListContainer}} +{{#isMapContainer}} + if not set({{{name}}}.keys()).issubset(set(allowed_values)): + raise ValueError( + "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isMapContainer}} +{{/isContainer}} +{{^isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + if {{{name}}} not in allowed_values: + raise ValueError( + "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 + .format({{{name}}}, allowed_values) + ) +{{/isContainer}} +{{/isEnum}} +{{^isEnum}} +{{#hasValidation}} +{{#maxLength}} + if {{name}} is not None and len({{name}}) > {{maxLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 +{{/maxLength}} +{{#minLength}} + if {{name}} is not None and len({{name}}) < {{minLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 +{{/minLength}} +{{#maximum}} + if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 +{{/maximum}} +{{#minimum}} + if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 +{{/minimum}} +{{#pattern}} + if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 +{{/pattern}} +{{#maxItems}} + if {{name}} is not None and len({{name}}) > {{maxItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 +{{/maxItems}} +{{#minItems}} + if {{name}} is not None and len({{name}}) < {{minItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 +{{/minItems}} +{{/hasValidation}} +{{/isEnum}} + + self._{{name}} = {{name}} + +{{/vars}} +{{#discriminator}} + def get_real_child_model(self, data): + """Returns the real base class specified by the discriminator""" + discriminator_value = data[self.discriminator].lower() + return self.discriminator_value_class_map.get(discriminator_value) + +{{/discriminator}} + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other +{{/model}} +{{/models}} diff --git a/model_doc.mustache b/model_doc.mustache new file mode 100644 index 0000000000..569550df37 --- /dev/null +++ b/model_doc.mustache @@ -0,0 +1,11 @@ +{{#models}}{{#model}}# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/vars}} + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + +{{/model}}{{/models}} diff --git a/model_test.mustache b/model_test.mustache new file mode 100644 index 0000000000..765e4f9c2c --- /dev/null +++ b/model_test.mustache @@ -0,0 +1,35 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +{{#models}} +{{#model}} +import {{packageName}} +from {{modelPackage}}.{{classFilename}} import {{classname}} # noqa: E501 +from {{packageName}}.rest import ApiException + + +class Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test{{classname}}(self): + """Test {{classname}}""" + # FIXME: construct object with mandatory attributes with example values + # model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501 + pass + +{{/model}} +{{/models}} + +if __name__ == '__main__': + unittest.main() diff --git a/partial_header.mustache b/partial_header.mustache new file mode 100644 index 0000000000..513ad04cdb --- /dev/null +++ b/partial_header.mustache @@ -0,0 +1,13 @@ +""" +{{#appName}} + {{{appName}}} +{{/appName}} + +{{#appDescription}} + {{{appDescription}}} # noqa: E501 +{{/appDescription}} + + {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" diff --git a/requirements.mustache b/requirements.mustache new file mode 100644 index 0000000000..bafdc07532 --- /dev/null +++ b/requirements.mustache @@ -0,0 +1,5 @@ +certifi >= 14.05.14 +six >= 1.10 +python_dateutil >= 2.5.3 +setuptools >= 21.0.0 +urllib3 >= 1.15.1 diff --git a/rest.mustache b/rest.mustache new file mode 100644 index 0000000000..ff9b019dc5 --- /dev/null +++ b/rest.mustache @@ -0,0 +1,314 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import io +import json +import logging +import re +import ssl + +import certifi +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import urlencode + +try: + import urllib3 +except ImportError: + raise ImportError('Swagger python client requires urllib3.') + + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.urllib3_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = resp.data + + def getheaders(self): + """Returns a dictionary of the response headers.""" + return self.urllib3_response.getheaders() + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.urllib3_response.getheader(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=None): + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + addition_pool_args = {} + if configuration.assert_hostname is not None: + addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + + if maxsize is None: + if configuration.connection_pool_maxsize is not None: + maxsize = configuration.connection_pool_maxsize + else: + maxsize = 4 + + # https pool manager + if configuration.proxy: + self.pool_manager = urllib3.ProxyManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + proxy_url=configuration.proxy, + **addition_pool_args + ) + else: + self.pool_manager = urllib3.PoolManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + **addition_pool_args + ) + + def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Perform requests. + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)): # noqa: E501,F821 + timeout = urllib3.Timeout(total=_request_timeout) + elif (isinstance(_request_timeout, tuple) and + len(_request_timeout) == 2): + timeout = urllib3.Timeout( + connect=_request_timeout[0], read=_request_timeout[1]) + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if query_params: + url += '?' + urlencode(query_params) + if re.search('json', headers['Content-Type'], re.IGNORECASE): + request_body = None + if body is not None: + request_body = json.dumps(body) + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=False, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=True, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + # Pass a `string` parameter directly in the body to support + # other content types than Json when `body` argument is + # provided in serialized form + elif isinstance(body, str): + request_body = body + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request(method, url, + fields=query_params, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + except urllib3.exceptions.SSLError as e: + msg = "{0}\n{1}".format(type(e).__name__, str(e)) + raise ApiException(status=0, reason=msg) + + if _preload_content: + r = RESTResponse(r) + + # In the python 3, the response.data is bytes. + # we need to decode it to string. + if six.PY3: + r.data = r.data.decode('utf8') + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/setup.mustache b/setup.mustache new file mode 100644 index 0000000000..e7107e9be9 --- /dev/null +++ b/setup.mustache @@ -0,0 +1,43 @@ +# coding: utf-8 + +{{>partial_header}} + +from setuptools import setup, find_packages # noqa: H301 + +NAME = "{{{projectName}}}" +VERSION = "{{packageVersion}}" +{{#apiInfo}} +{{#apis}} +{{^hasMore}} +# To install the library, run the following +# +# python setup.py install +# +# prerequisite: setuptools +# http://pypi.python.org/pypi/setuptools + +REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] +{{#asyncio}} +REQUIRES.append("aiohttp") +{{/asyncio}} +{{#tornado}} +REQUIRES.append("tornado") +{{/tornado}} + +setup( + name=NAME, + version=VERSION, + description="{{appName}}", + author_email="{{infoEmail}}", + url="{{packageUrl}}", + keywords=["Swagger", "{{appName}}"], + install_requires=REQUIRES, + packages=find_packages(), + include_package_data=True, + long_description="""\ + {{appDescription}} # noqa: E501 + """ +) +{{/hasMore}} +{{/apis}} +{{/apiInfo}} diff --git a/test-requirements.mustache b/test-requirements.mustache new file mode 100644 index 0000000000..31f8d94d99 --- /dev/null +++ b/test-requirements.mustache @@ -0,0 +1,11 @@ +{{^asyncio}} +coverage>=4.0.3 +nose>=1.3.7 +{{/asyncio}} +{{#asyncio}} +pytest>=3.3.1 +pytest-cov>=2.5.1 +{{/asyncio}} +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 diff --git a/tornado/rest.mustache b/tornado/rest.mustache new file mode 100644 index 0000000000..bc74fbc295 --- /dev/null +++ b/tornado/rest.mustache @@ -0,0 +1,255 @@ +# coding: utf-8 + +{{>partial_header}} + +import io +import json +import logging +import re + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import urlencode +import tornado +import tornado.gen +from tornado import httpclient +from urllib3.filepost import encode_multipart_formdata + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.tornado_response = resp + self.status = resp.code + self.reason = resp.reason + + if resp.body: + # In Python 3, the response body is utf-8 encoded bytes. + if six.PY3: + self.data = resp.body.decode('utf-8') + else: + self.data = resp.body + else: + self.data = None + + def getheaders(self): + """Returns a CIMultiDictProxy of the response headers.""" + return self.tornado_response.headers + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.tornado_response.headers.get(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=4): + # maxsize is number of requests to host that are allowed in parallel + + self.ca_certs = configuration.ssl_ca_cert + self.client_key = configuration.key_file + self.client_cert = configuration.cert_file + + self.proxy_port = self.proxy_host = None + + # https pool manager + if configuration.proxy: + self.proxy_port = 80 + self.proxy_host = configuration.proxy + + self.pool_manager = httpclient.AsyncHTTPClient() + + @tornado.gen.coroutine + def request(self, method, url, query_params=None, headers=None, body=None, + post_params=None, _preload_content=True, + _request_timeout=None): + """Execute Request + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: this is a non-applicable field for + the AiohttpClient. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + request = httpclient.HTTPRequest(url) + request.allow_nonstandard_methods = True + request.ca_certs = self.ca_certs + request.client_key = self.client_key + request.client_cert = self.client_cert + request.proxy_host = self.proxy_host + request.proxy_port = self.proxy_port + request.method = method + if headers: + request.headers = headers + if 'Content-Type' not in headers: + request.headers['Content-Type'] = 'application/json' + request.request_timeout = _request_timeout or 5 * 60 + + post_params = post_params or {} + + if query_params: + request.url += '?' + urlencode(query_params) + + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if re.search('json', headers['Content-Type'], re.IGNORECASE): + if body: + body = json.dumps(body) + request.body = body + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + request.body = urlencode(post_params) + elif headers['Content-Type'] == 'multipart/form-data': + multipart = encode_multipart_formdata(post_params) + request.body, headers['Content-Type'] = multipart + # Pass a `bytes` parameter directly in the body to support + # other content types than Json when `body` argument is provided + # in serialized form + elif isinstance(body, bytes): + request.body = body + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + + r = yield self.pool_manager.fetch(request, raise_error=False) + + if _preload_content: + + r = RESTResponse(r) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + raise tornado.gen.Return(r) + + @tornado.gen.coroutine + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + result = yield self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + result = yield self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + result = yield self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\nReason: {1}\n".format( + self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/tox.mustache b/tox.mustache new file mode 100644 index 0000000000..63d12fdeae --- /dev/null +++ b/tox.mustache @@ -0,0 +1,20 @@ +[tox] +{{^asyncio}} +envlist = py27, py3 +{{/asyncio}} +{{#asyncio}} +envlist = py3 +{{/asyncio}} + +[testenv] +deps=-r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +commands= +{{^asyncio}} + nosetests \ + [] +{{/asyncio}} +{{#asyncio}} + pytest -v --cov petstore_api +{{/asyncio}} diff --git a/travis.mustache b/travis.mustache new file mode 100644 index 0000000000..86211e2d4a --- /dev/null +++ b/travis.mustache @@ -0,0 +1,14 @@ +# ref: https://docs.travis-ci.com/user/languages/python +language: python +python: + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" + #- "3.5-dev" # 3.5 development branch + #- "nightly" # points to the latest development branch e.g. 3.6-dev +# command to install dependencies +install: "pip install -r requirements.txt" +# command to run tests +script: nosetests From 309f429de5831d7f8acc7bad6f468913266d4e18 Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Sat, 14 Apr 2018 16:36:30 +0200 Subject: [PATCH 002/180] Rename projects from swagger-codegen master branch --- README.mustache | 125 ++++++++ __init__api.mustache | 7 + __init__model.mustache | 10 + __init__package.mustache | 17 + __init__test.mustache | 0 api.mustache | 214 +++++++++++++ api_client.mustache | 627 +++++++++++++++++++++++++++++++++++++ api_doc.mustache | 85 +++++ api_test.mustache | 37 +++ asyncio/rest.mustache | 260 +++++++++++++++ configuration.mustache | 260 +++++++++++++++ git_push.sh.mustache | 52 +++ gitignore.mustache | 64 ++++ model.mustache | 219 +++++++++++++ model_doc.mustache | 11 + model_test.mustache | 35 +++ partial_header.mustache | 13 + requirements.mustache | 5 + rest.mustache | 314 +++++++++++++++++++ setup.mustache | 43 +++ test-requirements.mustache | 11 + tornado/rest.mustache | 255 +++++++++++++++ tox.mustache | 20 ++ travis.mustache | 14 + 24 files changed, 2698 insertions(+) create mode 100644 README.mustache create mode 100644 __init__api.mustache create mode 100644 __init__model.mustache create mode 100644 __init__package.mustache create mode 100644 __init__test.mustache create mode 100644 api.mustache create mode 100644 api_client.mustache create mode 100644 api_doc.mustache create mode 100644 api_test.mustache create mode 100644 asyncio/rest.mustache create mode 100644 configuration.mustache create mode 100755 git_push.sh.mustache create mode 100644 gitignore.mustache create mode 100644 model.mustache create mode 100644 model_doc.mustache create mode 100644 model_test.mustache create mode 100644 partial_header.mustache create mode 100644 requirements.mustache create mode 100644 rest.mustache create mode 100644 setup.mustache create mode 100644 test-requirements.mustache create mode 100644 tornado/rest.mustache create mode 100644 tox.mustache create mode 100644 travis.mustache diff --git a/README.mustache b/README.mustache new file mode 100644 index 0000000000..c1355be778 --- /dev/null +++ b/README.mustache @@ -0,0 +1,125 @@ +# {{{projectName}}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +This Python package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage +### pip install + +If the python package is hosted on Github, you can install directly from Github + +```sh +pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git +``` +(you may need to run `pip` with root permission: `sudo pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git`) + +Then import the package: +```python +import {{{packageName}}} +``` + +### Setuptools + +Install via [Setuptools](http://pypi.python.org/pypi/setuptools). + +```sh +python setup.py install --user +``` +(or `sudo python setup.py install` to install the package for all users) + +Then import the package: +```python +import {{{packageName}}} +``` + +## Getting Started + +Please follow the [installation procedure](#installation--usage) and then run the following: + +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +{{{packageName}}}.configuration.username = 'YOUR_USERNAME' +{{{packageName}}}.configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +{{{packageName}}}.configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# {{{packageName}}}.configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +{{{packageName}}}.configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} +{{/hasAuthMethods}} +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} All endpoints do not require authorization. +{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} +{{#authMethods}}## {{{name}}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/__init__api.mustache b/__init__api.mustache new file mode 100644 index 0000000000..db658a10fa --- /dev/null +++ b/__init__api.mustache @@ -0,0 +1,7 @@ +from __future__ import absolute_import + +# flake8: noqa + +# import apis into api package +{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}}{{/apiInfo}} \ No newline at end of file diff --git a/__init__model.mustache b/__init__model.mustache new file mode 100644 index 0000000000..2266b3d17f --- /dev/null +++ b/__init__model.mustache @@ -0,0 +1,10 @@ +# coding: utf-8 + +# flake8: noqa +{{>partial_header}} + +from __future__ import absolute_import + +# import models into model package +{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}} +{{/models}} diff --git a/__init__package.mustache b/__init__package.mustache new file mode 100644 index 0000000000..cd42506f54 --- /dev/null +++ b/__init__package.mustache @@ -0,0 +1,17 @@ +# coding: utf-8 + +# flake8: noqa + +{{>partial_header}} + +from __future__ import absolute_import + +# import apis into sdk package +{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}}{{/apiInfo}} +# import ApiClient +from {{packageName}}.api_client import ApiClient +from {{packageName}}.configuration import Configuration +# import models into sdk package +{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} +{{/model}}{{/models}} \ No newline at end of file diff --git a/__init__test.mustache b/__init__test.mustache new file mode 100644 index 0000000000..e69de29bb2 diff --git a/api.mustache b/api.mustache new file mode 100644 index 0000000000..a65946f578 --- /dev/null +++ b/api.mustache @@ -0,0 +1,214 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from {{packageName}}.api_client import ApiClient + + +{{#operations}} +class {{classname}}(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + Ref: https://github.com/swagger-api/swagger-codegen + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client +{{#operation}} + + def {{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async=True +{{#sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} +{{^sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} + >>> result = thread.get() + + :param async bool +{{#allParams}} + :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} +{{/allParams}} + :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, + returns the request thread. + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async'): + return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 + else: + (data) = self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 + return data + + def {{operationId}}_with_http_info(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async=True +{{#sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} +{{^sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) +{{/sortParamsByRequiredFlag}} + >>> result = thread.get() + + :param async bool +{{#allParams}} + :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/optional}} +{{/allParams}} + :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, + returns the request thread. + """ + + all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 + all_params.append('async') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + params = locals() + for key, val in six.iteritems(params['kwargs']): + if key not in all_params: + raise TypeError( + "Got an unexpected keyword argument '%s'" + " to method {{operationId}}" % key + ) + params[key] = val + del params['kwargs'] +{{#allParams}} +{{#required}} + # verify the required parameter '{{paramName}}' is set + if ('{{paramName}}' not in params or + params['{{paramName}}'] is None): + raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 +{{/required}} +{{/allParams}} + +{{#allParams}} +{{#hasValidation}} + {{#maxLength}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) > {{maxLength}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 + {{/maxLength}} + {{#minLength}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) < {{minLength}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 + {{/minLength}} + {{#maximum}} + if '{{paramName}}' in params and params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 + {{/maximum}} + {{#minimum}} + if '{{paramName}}' in params and params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 + {{/minimum}} + {{#pattern}} + if '{{paramName}}' in params and not re.search('{{{vendorExtensions.x-regex}}}', params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 + {{/pattern}} + {{#maxItems}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) > {{maxItems}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 + {{/maxItems}} + {{#minItems}} + if ('{{paramName}}' in params and + len(params['{{paramName}}']) < {{minItems}}): + raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 + {{/minItems}} +{{/hasValidation}} +{{#-last}} +{{/-last}} +{{/allParams}} + collection_formats = {} + + path_params = {} +{{#pathParams}} + if '{{paramName}}' in params: + path_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/pathParams}} + + query_params = [] +{{#queryParams}} + if '{{paramName}}' in params: + query_params.append(('{{baseName}}', params['{{paramName}}'])){{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/queryParams}} + + header_params = {} +{{#headerParams}} + if '{{paramName}}' in params: + header_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/headerParams}} + + form_params = [] + local_var_files = {} +{{#formParams}} + if '{{paramName}}' in params: + {{#notFile}}form_params.append(('{{baseName}}', params['{{paramName}}'])){{/notFile}}{{#isFile}}local_var_files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/formParams}} + + body_params = None +{{#bodyParam}} + if '{{paramName}}' in params: + body_params = params['{{paramName}}'] +{{/bodyParam}} + {{#hasProduces}} + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + [{{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) # noqa: E501 + + {{/hasProduces}} + {{#hasConsumes}} + # HTTP header `Content-Type` + header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 + [{{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) # noqa: E501 + + {{/hasConsumes}} + # Authentication setting + auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + + return self.api_client.call_api( + '{{{path}}}', '{{httpMethod}}', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 + auth_settings=auth_settings, + async=params.get('async'), + _return_http_data_only=params.get('_return_http_data_only'), + _preload_content=params.get('_preload_content', True), + _request_timeout=params.get('_request_timeout'), + collection_formats=collection_formats) +{{/operation}} +{{/operations}} diff --git a/api_client.mustache b/api_client.mustache new file mode 100644 index 0000000000..a6df41b072 --- /dev/null +++ b/api_client.mustache @@ -0,0 +1,627 @@ +# coding: utf-8 +{{>partial_header}} +from __future__ import absolute_import + +import datetime +import json +import mimetypes +from multiprocessing.pool import ThreadPool +import os +import re +import tempfile + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import quote +{{#tornado}} +import tornado.gen +{{/tornado}} + +from {{packageName}}.configuration import Configuration +import {{modelPackage}} +from {{packageName}} import rest + + +class ApiClient(object): + """Generic API client for Swagger client library builds. + + Swagger generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the Swagger + templates. + + NOTE: This class is auto generated by the swagger code generator program. + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + """ + + PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types + NATIVE_TYPES_MAPPING = { + 'int': int, + 'long': int if six.PY3 else long, # noqa: F821 + 'float': float, + 'str': str, + 'bool': bool, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'object': object, + } + + def __init__(self, configuration=None, header_name=None, header_value=None, + cookie=None): + if configuration is None: + configuration = Configuration() + self.configuration = configuration + + self.pool = ThreadPool() + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{packageVersion}}}/python{{/httpUserAgent}}' + + def __del__(self): + self.pool.close() + self.pool.join() + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + {{#tornado}} + @tornado.gen.coroutine + {{/tornado}} + {{#asyncio}}async {{/asyncio}}def __call_api( + self, resource_path, method, path_params=None, + query_params=None, header_params=None, body=None, post_params=None, + files=None, response_type=None, auth_settings=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) + header_params = dict(self.parameters_to_tuples(header_params, + collection_formats)) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples(path_params, + collection_formats) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # query parameters + if query_params: + query_params = self.sanitize_for_serialization(query_params) + query_params = self.parameters_to_tuples(query_params, + collection_formats) + + # post parameters + if post_params or files: + post_params = self.prepare_post_parameters(post_params, files) + post_params = self.sanitize_for_serialization(post_params) + post_params = self.parameters_to_tuples(post_params, + collection_formats) + + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + url = self.configuration.host + resource_path + + # perform request and return response + response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + + self.last_response = response_data + + return_data = response_data + if _preload_content: + # deserialize response data + if response_type: + return_data = self.deserialize(response_data, response_type) + else: + return_data = None + +{{^tornado}} + if _return_http_data_only: + return (return_data) + else: + return (return_data, response_data.status, + response_data.getheaders()) +{{/tornado}} +{{#tornado}} + if _return_http_data_only: + raise tornado.gen.Return(return_data) + else: + raise tornado.gen.Return((return_data, response_data.status, + response_data.getheaders())) +{{/tornado}} + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is swagger model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, list): + return [self.sanitize_for_serialization(sub_obj) + for sub_obj in obj] + elif isinstance(obj, tuple): + return tuple(self.sanitize_for_serialization(sub_obj) + for sub_obj in obj) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + + if isinstance(obj, dict): + obj_dict = obj + else: + # Convert model obj to dict except + # attributes `swagger_types`, `attribute_map` + # and attributes which value is not None. + # Convert attribute name to json key in + # model definition for request. + obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) + for attr, _ in six.iteritems(obj.swagger_types) + if getattr(obj, attr) is not None} + + return {key: self.sanitize_for_serialization(val) + for key, val in six.iteritems(obj_dict)} + + def deserialize(self, response, response_type): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + + :return: deserialized object. + """ + # handle file downloading + # save response body into a tmp file and return the instance + if response_type == "file": + return self.__deserialize_file(response) + + # fetch data from response object + try: + data = json.loads(response.data) + except ValueError: + data = response.data + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if type(klass) == str: + if klass.startswith('list['): + sub_kls = re.match('list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) + for sub_data in data] + + if klass.startswith('dict('): + sub_kls = re.match('dict\(([^,]*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) + for k, v in six.iteritems(data)} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr({{modelPackage}}, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object(data) + elif klass == datetime.date: + return self.__deserialize_date(data) + elif klass == datetime.datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def call_api(self, resource_path, method, + path_params=None, query_params=None, header_params=None, + body=None, post_params=None, files=None, + response_type=None, auth_settings=None, async=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None): + """Makes the HTTP request (synchronous) and returns deserialized data. + + To make an async request, set the async parameter. + + :param resource_path: Path to method endpoint. + :param method: Method to call. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param response: Response data type. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param async bool: execute request asynchronously + :param _return_http_data_only: response data without head status code + and headers + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: + If async parameter is True, + the request will be called asynchronously. + The method will return the request thread. + If parameter async is False or missing, + then the method will return the response directly. + """ + if not async: + return self.__call_api(resource_path, method, + path_params, query_params, header_params, + body, post_params, files, + response_type, auth_settings, + _return_http_data_only, collection_formats, + _preload_content, _request_timeout) + else: + thread = self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, query_params, + header_params, body, + post_params, files, + response_type, auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, _request_timeout)) + return thread + + def request(self, method, url, query_params=None, headers=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + """Makes the HTTP request using RESTClient.""" + if method == "GET": + return self.rest_client.GET(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "HEAD": + return self.rest_client.HEAD(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "OPTIONS": + return self.rest_client.OPTIONS(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "POST": + return self.rest_client.POST(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PUT": + return self.rest_client.PUT(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PATCH": + return self.rest_client.PATCH(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "DELETE": + return self.rest_client.DELETE(url, + query_params=query_params, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + else: + raise ValueError( + "http method must be `GET`, `HEAD`, `OPTIONS`," + " `POST`, `PATCH`, `PUT` or `DELETE`." + ) + + def parameters_to_tuples(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: Parameters as list of tuples, collections formatted + """ + new_params = [] + if collection_formats is None: + collection_formats = {} + for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(str(value) for value in v))) + else: + new_params.append((k, v)) + return new_params + + def prepare_post_parameters(self, post_params=None, files=None): + """Builds form parameters. + + :param post_params: Normal form parameters. + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + + if post_params: + params = post_params + + if files: + for k, v in six.iteritems(files): + if not v: + continue + file_names = v if type(v) is list else [v] + for n in file_names: + with open(n, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([k, tuple([filename, filedata, mimetype])])) + + return params + + def select_header_accept(self, accepts): + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return + + accepts = [x.lower() for x in accepts] + + if 'application/json' in accepts: + return 'application/json' + else: + return ', '.join(accepts) + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return 'application/json' + + content_types = [x.lower() for x in content_types] + + if 'application/json' in content_types or '*/*' in content_types: + return 'application/json' + else: + return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param querys: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = self.configuration.auth_settings().get(auth) + if auth_setting: + if not auth_setting['value']: + continue + elif auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "wb") as f: + f.write(response.data) + + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return six.text_type(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return a original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + try: + from dateutil.parser import parse + return parse(string).date() + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason="Failed to parse `{0}` as date object".format(string) + ) + + def __deserialize_datatime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as datetime object" + .format(string) + ) + ) + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + if not klass.swagger_types and not hasattr(klass, + 'get_real_child_model'): + return data + + kwargs = {} + if klass.swagger_types is not None: + for attr, attr_type in six.iteritems(klass.swagger_types): + if (data is not None and + klass.attribute_map[attr] in data and + isinstance(data, (list, dict))): + value = data[klass.attribute_map[attr]] + kwargs[attr] = self.__deserialize(value, attr_type) + + instance = klass(**kwargs) + + if hasattr(instance, 'get_real_child_model'): + klass_name = instance.get_real_child_model(data) + if klass_name: + instance = self.__deserialize(data, klass_name) + return instance diff --git a/api_doc.mustache b/api_doc.mustache new file mode 100644 index 0000000000..32c26d929d --- /dev/null +++ b/api_doc.mustache @@ -0,0 +1,85 @@ +# {{packageName}}.{{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} +# **{{{operationId}}}** +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{paramName}}}{{/required}}{{^required}}{{{paramName}}}={{{paramName}}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) + +{{{summary}}}{{#notes}} + +{{{notes}}}{{/notes}} + +### Example +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} +{{^hasAuthMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +``` + +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#allParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | {{^required}}[optional] {{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} +{{/allParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +{{/operation}} +{{/operations}} diff --git a/api_test.mustache b/api_test.mustache new file mode 100644 index 0000000000..90fafc15f3 --- /dev/null +++ b/api_test.mustache @@ -0,0 +1,37 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +import {{packageName}} +from {{apiPackage}}.{{classVarName}} import {{classname}} # noqa: E501 +from {{packageName}}.rest import ApiException + + +class {{#operations}}Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" + + def setUp(self): + self.api = {{apiPackage}}.{{classVarName}}.{{classname}}() # noqa: E501 + + def tearDown(self): + pass + + {{#operation}} + def test_{{operationId}}(self): + """Test case for {{{operationId}}} + +{{#summary}} + {{{summary}}} # noqa: E501 +{{/summary}} + """ + pass + + {{/operation}} +{{/operations}} + +if __name__ == '__main__': + unittest.main() diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache new file mode 100644 index 0000000000..39003abfbf --- /dev/null +++ b/asyncio/rest.mustache @@ -0,0 +1,260 @@ +# coding: utf-8 + +{{>partial_header}} + +import io +import json +import logging +import re +import ssl + +import aiohttp +import certifi +# python 2 and python 3 compatibility library +from six.moves.urllib.parse import urlencode + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp, data): + self.aiohttp_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = data + + def getheaders(self): + """Returns a CIMultiDictProxy of the response headers.""" + return self.aiohttp_response.headers + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.aiohttp_response.headers.get(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=4): + # maxsize is number of requests to host that are allowed in parallel + # ca_certs vs cert_file vs key_file + # http://stackoverflow.com/a/23957365/2985775 + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + ssl_context = ssl.create_default_context(cafile=ca_certs) + if configuration.cert_file: + ssl_context.load_cert_chain( + configuration.cert_file, keyfile=configuration.key_file + ) + + connector = aiohttp.TCPConnector( + limit=maxsize, + ssl_context=ssl_context, + verify_ssl=configuration.verify_ssl + ) + + # https pool manager + if configuration.proxy: + self.pool_manager = aiohttp.ClientSession( + connector=connector, + proxy=configuration.proxy + ) + else: + self.pool_manager = aiohttp.ClientSession( + connector=connector + ) + + async def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Execute request + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: this is a non-applicable field for + the AiohttpClient. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + timeout = _request_timeout or 5 * 60 + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + args = { + "method": method, + "url": url, + "timeout": timeout, + "headers": headers + } + + if query_params: + args["url"] += '?' + urlencode(query_params) + + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if re.search('json', headers['Content-Type'], re.IGNORECASE): + if body is not None: + body = json.dumps(body) + args["data"] = body + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + args["data"] = aiohttp.FormData(post_params) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by aiohttp + del headers['Content-Type'] + data = aiohttp.FormData() + for param in post_params: + k, v = param + if isinstance(v, tuple) and len(v) == 3: + data.add_field(k, + value=v[1], + filename=v[0], + content_type=v[2]) + else: + data.add_field(k, v) + args["data"] = data + + # Pass a `bytes` parameter directly in the body to support + # other content types than Json when `body` argument is provided + # in serialized form + elif isinstance(body, bytes): + args["data"] = body + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + + async with self.pool_manager.request(**args) as r: + data = await r.text() + r = RESTResponse(r, data) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + async def GET(self, url, headers=None, query_params=None, + _preload_content=True, _request_timeout=None): + return (await self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params)) + + async def HEAD(self, url, headers=None, query_params=None, + _preload_content=True, _request_timeout=None): + return (await self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params)) + + async def OPTIONS(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return (await self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def POST(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return (await self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + async def PATCH(self, url, headers=None, query_params=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + return (await self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body)) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\nReason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/configuration.mustache b/configuration.mustache new file mode 100644 index 0000000000..84e6ad4d20 --- /dev/null +++ b/configuration.mustache @@ -0,0 +1,260 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import copy +import logging +import multiprocessing +import sys +import urllib3 + +import six +from six.moves import http_client as httplib + + +class TypeWithDefault(type): + def __init__(cls, name, bases, dct): + super(TypeWithDefault, cls).__init__(name, bases, dct) + cls._default = None + + def __call__(cls): + if cls._default is None: + cls._default = type.__call__(cls) + return copy.copy(cls._default) + + def set_default(cls, default): + cls._default = copy.copy(default) + + +class Configuration(six.with_metaclass(TypeWithDefault, object)): + """NOTE: This class is auto generated by the swagger code generator program. + + Ref: https://github.com/swagger-api/swagger-codegen + Do not edit the class manually. + """ + + def __init__(self): + """Constructor""" + # Default Base url + self.host = "{{{basePath}}}" + # Temp file folder for downloading files + self.temp_folder_path = None + + # Authentication Settings + # dict to store API key(s) + self.api_key = {} + # dict to store API prefix (e.g. Bearer) + self.api_key_prefix = {} + # Username for HTTP basic authentication + self.username = "" + # Password for HTTP basic authentication + self.password = "" +{{#authMethods}}{{#isOAuth}} + # access token for OAuth + self.access_token = "" +{{/isOAuth}}{{/authMethods}} + # Logging Settings + self.logger = {} + self.logger["package_logger"] = logging.getLogger("{{packageName}}") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + # Log format + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + # Log stream handler + self.logger_stream_handler = None + # Log file handler + self.logger_file_handler = None + # Debug file location + self.logger_file = None + # Debug switch + self.debug = False + + # SSL/TLS verification + # Set this to false to skip verifying SSL certificate when calling API + # from https server. + self.verify_ssl = True + # Set this to customize the certificate file to verify the peer. + self.ssl_ca_cert = None + # client certificate file + self.cert_file = None + # client key file + self.key_file = None + # Set this to True/False to enable/disable SSL hostname verification. + self.assert_hostname = None + + # urllib3 connection pool's maximum number of connections saved + # per pool. urllib3 uses 1 connection as default value, but this is + # not the best value when you are making a lot of possibly parallel + # requests to the same host, which is often the case here. + # cpu_count * 5 is used as default value to increase performance. + self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + + # Proxy URL + self.proxy = None + # Safe chars for path_param + self.safe_chars_for_path_param = '' + + @property + def logger_file(self): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_file_handler) + if self.logger_stream_handler: + logger.removeHandler(self.logger_stream_handler) + else: + # If not set logging file, + # then add stream handler and remove file handler. + self.logger_stream_handler = logging.StreamHandler() + self.logger_stream_handler.setFormatter(self.logger_formatter) + for _, logger in six.iteritems(self.logger): + logger.addHandler(self.logger_stream_handler) + if self.logger_file_handler: + logger.removeHandler(self.logger_file_handler) + + @property + def debug(self): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.DEBUG) + # turn on httplib debug + httplib.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in six.iteritems(self.logger): + logger.setLevel(logging.WARNING) + # turn off httplib debug + httplib.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier): + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :return: The token for api key authentication. + """ + if (self.api_key.get(identifier) and + self.api_key_prefix.get(identifier)): + return self.api_key_prefix[identifier] + ' ' + self.api_key[identifier] # noqa: E501 + elif self.api_key.get(identifier): + return self.api_key[identifier] + + def get_basic_auth_token(self): + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + return urllib3.util.make_headers( + basic_auth=self.username + ':' + self.password + ).get('authorization') + + def auth_settings(self): + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + return { +{{#authMethods}} +{{#isApiKey}} + '{{name}}': + { + 'type': 'api_key', + 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': self.get_api_key_with_prefix('{{keyParamName}}') + }, +{{/isApiKey}} +{{#isBasic}} + '{{name}}': + { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': self.get_basic_auth_token() + }, +{{/isBasic}}{{#isOAuth}} + '{{name}}': + { + 'type': 'oauth2', + 'in': 'header', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + }, +{{/isOAuth}}{{/authMethods}} + } + + def to_debug_report(self): + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: {{version}}\n"\ + "SDK Package Version: {{packageVersion}}".\ + format(env=sys.platform, pyversion=sys.version) diff --git a/git_push.sh.mustache b/git_push.sh.mustache new file mode 100755 index 0000000000..a2d7523483 --- /dev/null +++ b/git_push.sh.mustache @@ -0,0 +1,52 @@ +#!/bin/sh +# ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ +# +# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" + +git_user_id=$1 +git_repo_id=$2 +release_note=$3 + +if [ "$git_user_id" = "" ]; then + git_user_id="{{{gitUserId}}}" + echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id" +fi + +if [ "$git_repo_id" = "" ]; then + git_repo_id="{{{gitRepoId}}}" + echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id" +fi + +if [ "$release_note" = "" ]; then + release_note="{{{releaseNote}}}" + echo "[INFO] No command line input provided. Set \$release_note to $release_note" +fi + +# Initialize the local directory as a Git repository +git init + +# Adds the files in the local repository and stages them for commit. +git add . + +# Commits the tracked changes and prepares them to be pushed to a remote repository. +git commit -m "$release_note" + +# Sets the new remote +git_remote=`git remote` +if [ "$git_remote" = "" ]; then # git remote not defined + + if [ "$GIT_TOKEN" = "" ]; then + echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." + git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + else + git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + fi + +fi + +git pull origin master + +# Pushes (Forces) the changes in the local repository up to the remote repository +echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +git push origin master 2>&1 | grep -v 'To https' + diff --git a/gitignore.mustache b/gitignore.mustache new file mode 100644 index 0000000000..a655050c26 --- /dev/null +++ b/gitignore.mustache @@ -0,0 +1,64 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +env/ +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +*.egg-info/ +.installed.cfg +*.egg + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*,cover +.hypothesis/ +venv/ +.python-version + +# Translations +*.mo +*.pot + +# Django stuff: +*.log + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +#Ipython Notebook +.ipynb_checkpoints diff --git a/model.mustache b/model.mustache new file mode 100644 index 0000000000..5668793b3f --- /dev/null +++ b/model.mustache @@ -0,0 +1,219 @@ +# coding: utf-8 + +{{>partial_header}} + +import pprint +import re # noqa: F401 + +import six +{{#imports}}{{#-first}} +{{/-first}} +{{import}} # noqa: F401,E501 +{{/imports}} + + +{{#models}} +{{#model}} +class {{classname}}(object): + """NOTE: This class is auto generated by the swagger code generator program. + + Do not edit the class manually. + """{{#allowableValues}} + + """ + allowed enum values + """ +{{#enumVars}} + {{name}} = {{{value}}}{{^-last}} +{{/-last}} +{{/enumVars}}{{/allowableValues}} + + """ + Attributes: + swagger_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + swagger_types = { +{{#vars}} + '{{name}}': '{{{datatype}}}'{{#hasMore}},{{/hasMore}} +{{/vars}} + } + + attribute_map = { +{{#vars}} + '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} +{{/vars}} + } +{{#discriminator}} + + discriminator_value_class_map = { + {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, + {{/-last}}{{/children}} + } +{{/discriminator}} + + def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 + """{{classname}} - a model defined in Swagger""" # noqa: E501 +{{#vars}}{{#-first}} +{{/-first}} + self._{{name}} = None +{{/vars}} + self.discriminator = {{#discriminator}}'{{discriminator}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} +{{#vars}}{{#-first}} +{{/-first}} +{{#required}} + self.{{name}} = {{name}} +{{/required}} +{{^required}} + if {{name}} is not None: + self.{{name}} = {{name}} +{{/required}} +{{/vars}} + +{{#vars}} + @property + def {{name}}(self): + """Gets the {{name}} of this {{classname}}. # noqa: E501 + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :return: The {{name}} of this {{classname}}. # noqa: E501 + :rtype: {{datatype}} + """ + return self._{{name}} + + @{{name}}.setter + def {{name}}(self, {{name}}): + """Sets the {{name}} of this {{classname}}. + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 + :type: {{datatype}} + """ +{{#required}} + if {{name}} is None: + raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 +{{/required}} +{{#isEnum}} +{{#isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 +{{#isListContainer}} + if not set({{{name}}}).issubset(set(allowed_values)): + raise ValueError( + "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isListContainer}} +{{#isMapContainer}} + if not set({{{name}}}.keys()).issubset(set(allowed_values)): + raise ValueError( + "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isMapContainer}} +{{/isContainer}} +{{^isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + if {{{name}}} not in allowed_values: + raise ValueError( + "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 + .format({{{name}}}, allowed_values) + ) +{{/isContainer}} +{{/isEnum}} +{{^isEnum}} +{{#hasValidation}} +{{#maxLength}} + if {{name}} is not None and len({{name}}) > {{maxLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 +{{/maxLength}} +{{#minLength}} + if {{name}} is not None and len({{name}}) < {{minLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 +{{/minLength}} +{{#maximum}} + if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 +{{/maximum}} +{{#minimum}} + if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 +{{/minimum}} +{{#pattern}} + if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 +{{/pattern}} +{{#maxItems}} + if {{name}} is not None and len({{name}}) > {{maxItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 +{{/maxItems}} +{{#minItems}} + if {{name}} is not None and len({{name}}) < {{minItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 +{{/minItems}} +{{/hasValidation}} +{{/isEnum}} + + self._{{name}} = {{name}} + +{{/vars}} +{{#discriminator}} + def get_real_child_model(self, data): + """Returns the real base class specified by the discriminator""" + discriminator_value = data[self.discriminator].lower() + return self.discriminator_value_class_map.get(discriminator_value) + +{{/discriminator}} + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.swagger_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other +{{/model}} +{{/models}} diff --git a/model_doc.mustache b/model_doc.mustache new file mode 100644 index 0000000000..569550df37 --- /dev/null +++ b/model_doc.mustache @@ -0,0 +1,11 @@ +{{#models}}{{#model}}# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{/vars}} + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + +{{/model}}{{/models}} diff --git a/model_test.mustache b/model_test.mustache new file mode 100644 index 0000000000..765e4f9c2c --- /dev/null +++ b/model_test.mustache @@ -0,0 +1,35 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +{{#models}} +{{#model}} +import {{packageName}} +from {{modelPackage}}.{{classFilename}} import {{classname}} # noqa: E501 +from {{packageName}}.rest import ApiException + + +class Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test{{classname}}(self): + """Test {{classname}}""" + # FIXME: construct object with mandatory attributes with example values + # model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501 + pass + +{{/model}} +{{/models}} + +if __name__ == '__main__': + unittest.main() diff --git a/partial_header.mustache b/partial_header.mustache new file mode 100644 index 0000000000..513ad04cdb --- /dev/null +++ b/partial_header.mustache @@ -0,0 +1,13 @@ +""" +{{#appName}} + {{{appName}}} +{{/appName}} + +{{#appDescription}} + {{{appDescription}}} # noqa: E501 +{{/appDescription}} + + {{#version}}OpenAPI spec version: {{{version}}}{{/version}} + {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" diff --git a/requirements.mustache b/requirements.mustache new file mode 100644 index 0000000000..bafdc07532 --- /dev/null +++ b/requirements.mustache @@ -0,0 +1,5 @@ +certifi >= 14.05.14 +six >= 1.10 +python_dateutil >= 2.5.3 +setuptools >= 21.0.0 +urllib3 >= 1.15.1 diff --git a/rest.mustache b/rest.mustache new file mode 100644 index 0000000000..ff9b019dc5 --- /dev/null +++ b/rest.mustache @@ -0,0 +1,314 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import io +import json +import logging +import re +import ssl + +import certifi +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import urlencode + +try: + import urllib3 +except ImportError: + raise ImportError('Swagger python client requires urllib3.') + + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.urllib3_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = resp.data + + def getheaders(self): + """Returns a dictionary of the response headers.""" + return self.urllib3_response.getheaders() + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.urllib3_response.getheader(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=None): + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + addition_pool_args = {} + if configuration.assert_hostname is not None: + addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + + if maxsize is None: + if configuration.connection_pool_maxsize is not None: + maxsize = configuration.connection_pool_maxsize + else: + maxsize = 4 + + # https pool manager + if configuration.proxy: + self.pool_manager = urllib3.ProxyManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + proxy_url=configuration.proxy, + **addition_pool_args + ) + else: + self.pool_manager = urllib3.PoolManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + **addition_pool_args + ) + + def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Perform requests. + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)): # noqa: E501,F821 + timeout = urllib3.Timeout(total=_request_timeout) + elif (isinstance(_request_timeout, tuple) and + len(_request_timeout) == 2): + timeout = urllib3.Timeout( + connect=_request_timeout[0], read=_request_timeout[1]) + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if query_params: + url += '?' + urlencode(query_params) + if re.search('json', headers['Content-Type'], re.IGNORECASE): + request_body = None + if body is not None: + request_body = json.dumps(body) + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=False, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=True, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + # Pass a `string` parameter directly in the body to support + # other content types than Json when `body` argument is + # provided in serialized form + elif isinstance(body, str): + request_body = body + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request(method, url, + fields=query_params, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + except urllib3.exceptions.SSLError as e: + msg = "{0}\n{1}".format(type(e).__name__, str(e)) + raise ApiException(status=0, reason=msg) + + if _preload_content: + r = RESTResponse(r) + + # In the python 3, the response.data is bytes. + # we need to decode it to string. + if six.PY3: + r.data = r.data.decode('utf8') + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/setup.mustache b/setup.mustache new file mode 100644 index 0000000000..e7107e9be9 --- /dev/null +++ b/setup.mustache @@ -0,0 +1,43 @@ +# coding: utf-8 + +{{>partial_header}} + +from setuptools import setup, find_packages # noqa: H301 + +NAME = "{{{projectName}}}" +VERSION = "{{packageVersion}}" +{{#apiInfo}} +{{#apis}} +{{^hasMore}} +# To install the library, run the following +# +# python setup.py install +# +# prerequisite: setuptools +# http://pypi.python.org/pypi/setuptools + +REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] +{{#asyncio}} +REQUIRES.append("aiohttp") +{{/asyncio}} +{{#tornado}} +REQUIRES.append("tornado") +{{/tornado}} + +setup( + name=NAME, + version=VERSION, + description="{{appName}}", + author_email="{{infoEmail}}", + url="{{packageUrl}}", + keywords=["Swagger", "{{appName}}"], + install_requires=REQUIRES, + packages=find_packages(), + include_package_data=True, + long_description="""\ + {{appDescription}} # noqa: E501 + """ +) +{{/hasMore}} +{{/apis}} +{{/apiInfo}} diff --git a/test-requirements.mustache b/test-requirements.mustache new file mode 100644 index 0000000000..31f8d94d99 --- /dev/null +++ b/test-requirements.mustache @@ -0,0 +1,11 @@ +{{^asyncio}} +coverage>=4.0.3 +nose>=1.3.7 +{{/asyncio}} +{{#asyncio}} +pytest>=3.3.1 +pytest-cov>=2.5.1 +{{/asyncio}} +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 diff --git a/tornado/rest.mustache b/tornado/rest.mustache new file mode 100644 index 0000000000..bc74fbc295 --- /dev/null +++ b/tornado/rest.mustache @@ -0,0 +1,255 @@ +# coding: utf-8 + +{{>partial_header}} + +import io +import json +import logging +import re + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import urlencode +import tornado +import tornado.gen +from tornado import httpclient +from urllib3.filepost import encode_multipart_formdata + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.tornado_response = resp + self.status = resp.code + self.reason = resp.reason + + if resp.body: + # In Python 3, the response body is utf-8 encoded bytes. + if six.PY3: + self.data = resp.body.decode('utf-8') + else: + self.data = resp.body + else: + self.data = None + + def getheaders(self): + """Returns a CIMultiDictProxy of the response headers.""" + return self.tornado_response.headers + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.tornado_response.headers.get(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=4): + # maxsize is number of requests to host that are allowed in parallel + + self.ca_certs = configuration.ssl_ca_cert + self.client_key = configuration.key_file + self.client_cert = configuration.cert_file + + self.proxy_port = self.proxy_host = None + + # https pool manager + if configuration.proxy: + self.proxy_port = 80 + self.proxy_host = configuration.proxy + + self.pool_manager = httpclient.AsyncHTTPClient() + + @tornado.gen.coroutine + def request(self, method, url, query_params=None, headers=None, body=None, + post_params=None, _preload_content=True, + _request_timeout=None): + """Execute Request + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: this is a non-applicable field for + the AiohttpClient. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ValueError( + "body parameter cannot be used with post_params parameter." + ) + + request = httpclient.HTTPRequest(url) + request.allow_nonstandard_methods = True + request.ca_certs = self.ca_certs + request.client_key = self.client_key + request.client_cert = self.client_cert + request.proxy_host = self.proxy_host + request.proxy_port = self.proxy_port + request.method = method + if headers: + request.headers = headers + if 'Content-Type' not in headers: + request.headers['Content-Type'] = 'application/json' + request.request_timeout = _request_timeout or 5 * 60 + + post_params = post_params or {} + + if query_params: + request.url += '?' + urlencode(query_params) + + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if re.search('json', headers['Content-Type'], re.IGNORECASE): + if body: + body = json.dumps(body) + request.body = body + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + request.body = urlencode(post_params) + elif headers['Content-Type'] == 'multipart/form-data': + multipart = encode_multipart_formdata(post_params) + request.body, headers['Content-Type'] = multipart + # Pass a `bytes` parameter directly in the body to support + # other content types than Json when `body` argument is provided + # in serialized form + elif isinstance(body, bytes): + request.body = body + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + + r = yield self.pool_manager.fetch(request, raise_error=False) + + if _preload_content: + + r = RESTResponse(r) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + raise tornado.gen.Return(r) + + @tornado.gen.coroutine + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + result = yield self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + result = yield self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + result = yield self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + @tornado.gen.coroutine + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + result = yield self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + raise tornado.gen.Return(result) + + +class ApiException(Exception): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\nReason: {1}\n".format( + self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message diff --git a/tox.mustache b/tox.mustache new file mode 100644 index 0000000000..63d12fdeae --- /dev/null +++ b/tox.mustache @@ -0,0 +1,20 @@ +[tox] +{{^asyncio}} +envlist = py27, py3 +{{/asyncio}} +{{#asyncio}} +envlist = py3 +{{/asyncio}} + +[testenv] +deps=-r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +commands= +{{^asyncio}} + nosetests \ + [] +{{/asyncio}} +{{#asyncio}} + pytest -v --cov petstore_api +{{/asyncio}} diff --git a/travis.mustache b/travis.mustache new file mode 100644 index 0000000000..86211e2d4a --- /dev/null +++ b/travis.mustache @@ -0,0 +1,14 @@ +# ref: https://docs.travis-ci.com/user/languages/python +language: python +python: + - "2.7" + - "3.2" + - "3.3" + - "3.4" + - "3.5" + #- "3.5-dev" # 3.5 development branch + #- "nightly" # points to the latest development branch e.g. 3.6-dev +# command to install dependencies +install: "pip install -r requirements.txt" +# command to run tests +script: nosetests From 092c6f0b7acda2a64f53c2257796096b4e8c92aa Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Tue, 17 Apr 2018 09:19:10 +0200 Subject: [PATCH 003/180] Add OpenAPI spec 3.0 support (beta) Co-authored-by: Akihito Nakano Co-authored-by: Jeremie Bresson Co-authored-by: Jim Schubert Co-authored-by: Martin Delille Co-authored-by: Tomasz Prus Co-authored-by: William Cheng --- api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.mustache b/api.mustache index a65946f578..512d2570b1 100644 --- a/api.mustache +++ b/api.mustache @@ -171,7 +171,7 @@ class {{classname}}(object): local_var_files = {} {{#formParams}} if '{{paramName}}' in params: - {{#notFile}}form_params.append(('{{baseName}}', params['{{paramName}}'])){{/notFile}}{{#isFile}}local_var_files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 + {{^isFile}}form_params.append(('{{baseName}}', params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/formParams}} From 1d0decf44f33b9514284566238a951b5db4f550a Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 19 Apr 2018 15:02:22 +0800 Subject: [PATCH 004/180] update discriminator to discriminatorName (#142) --- model.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model.mustache b/model.mustache index 5668793b3f..7184f4192a 100644 --- a/model.mustache +++ b/model.mustache @@ -60,7 +60,7 @@ class {{classname}}(object): {{/-first}} self._{{name}} = None {{/vars}} - self.discriminator = {{#discriminator}}'{{discriminator}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} + self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} {{#vars}}{{#-first}} {{/-first}} {{#required}} From ae4219847a2b8ea69e0ddad2fe4566afbf9a9977 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Sat, 21 Apr 2018 05:54:40 +0200 Subject: [PATCH 005/180] fix: python clients (#136) * fix: python client * fix: regenerate petstore samples for python-asyncio/tornado * fix: python-asyncio tests * fix: python-tornado tests * chore: update python samples * fix: enable tests for python-tornado * fix: discriminator property * fix: file type * python: regenerate samples * fix: define file as generic type --- setup.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.mustache b/setup.mustache index e7107e9be9..597136a8d1 100644 --- a/setup.mustache +++ b/setup.mustache @@ -21,7 +21,7 @@ REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] REQUIRES.append("aiohttp") {{/asyncio}} {{#tornado}} -REQUIRES.append("tornado") +REQUIRES.append("tornado>=4.2,<5") {{/tornado}} setup( From 8b0eb01650fabb67592135f9ec43e345dd595020 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 2 May 2018 01:12:32 +0800 Subject: [PATCH 006/180] update default user agent (#284) --- api_client.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index a6df41b072..0339fbd81a 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -67,7 +67,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}Swagger-Codegen/{{{packageVersion}}}/python{{/httpUserAgent}}' + self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' def __del__(self): self.pool.close() From e154b6d70f7c4f3fd5d919a0b64afb37d0eadfc4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 3 May 2018 20:12:24 +0800 Subject: [PATCH 007/180] Update wordings (#301) * update wordings * update git_push wordings * update git clone * update homepage url * update meta-codegen sample --- README.mustache | 2 +- api.mustache | 4 ++-- api_client.mustache | 4 ++-- configuration.mustache | 4 ++-- git_push.sh.mustache | 2 +- model.mustache | 2 +- partial_header.mustache | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.mustache b/README.mustache index c1355be778..184dbdc61d 100644 --- a/README.mustache +++ b/README.mustache @@ -3,7 +3,7 @@ {{{appDescription}}} {{/appDescription}} -This Python package is automatically generated by the [Swagger Codegen](https://github.com/swagger-api/swagger-codegen) project: +This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - API version: {{appVersion}} - Package version: {{packageVersion}} diff --git a/api.mustache b/api.mustache index 512d2570b1..1925d4d164 100644 --- a/api.mustache +++ b/api.mustache @@ -14,10 +14,10 @@ from {{packageName}}.api_client import ApiClient {{#operations}} class {{classname}}(object): - """NOTE: This class is auto generated by the swagger code generator program. + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). Do not edit the class manually. - Ref: https://github.com/swagger-api/swagger-codegen + Ref: https://openapi-generator.tech """ def __init__(self, api_client=None): diff --git a/api_client.mustache b/api_client.mustache index 0339fbd81a..4b7b2bf86a 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -30,8 +30,8 @@ class ApiClient(object): the methods and models for each application are generated from the Swagger templates. - NOTE: This class is auto generated by the swagger code generator program. - Ref: https://github.com/swagger-api/swagger-codegen + NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + Ref: https://openapi-generator.tech Do not edit the class manually. :param configuration: .Configuration object for this client diff --git a/configuration.mustache b/configuration.mustache index 84e6ad4d20..72702d8d1f 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -29,9 +29,9 @@ class TypeWithDefault(type): class Configuration(six.with_metaclass(TypeWithDefault, object)): - """NOTE: This class is auto generated by the swagger code generator program. + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - Ref: https://github.com/swagger-api/swagger-codegen + Ref: https://openapi-generator.tech Do not edit the class manually. """ diff --git a/git_push.sh.mustache b/git_push.sh.mustache index a2d7523483..8a32e53995 100755 --- a/git_push.sh.mustache +++ b/git_push.sh.mustache @@ -1,7 +1,7 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 swagger-petstore-perl "minor update" +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" git_user_id=$1 git_repo_id=$2 diff --git a/model.mustache b/model.mustache index 7184f4192a..9d7a6f9a6b 100644 --- a/model.mustache +++ b/model.mustache @@ -15,7 +15,7 @@ import six {{#models}} {{#model}} class {{classname}}(object): - """NOTE: This class is auto generated by the swagger code generator program. + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). Do not edit the class manually. """{{#allowableValues}} diff --git a/partial_header.mustache b/partial_header.mustache index 513ad04cdb..929e512e08 100644 --- a/partial_header.mustache +++ b/partial_header.mustache @@ -9,5 +9,5 @@ {{#version}}OpenAPI spec version: {{{version}}}{{/version}} {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} - Generated by: https://github.com/swagger-api/swagger-codegen.git + Generated by: https://openapi-generator.tech """ From 512ddfcb739a20c3f6356229112ba34a722307e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Sat, 5 May 2018 16:40:52 +0200 Subject: [PATCH 008/180] Merge 'master' branch of 'swagger-codegen' into 'openapi-generator' (#327) --- README.mustache | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.mustache b/README.mustache index 184dbdc61d..cf92dc583d 100644 --- a/README.mustache +++ b/README.mustache @@ -60,17 +60,21 @@ from {{{packageName}}}.rest import ApiException from pprint import pprint {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} # Configure HTTP basic authorization: {{{name}}} -{{{packageName}}}.configuration.username = 'YOUR_USERNAME' -{{{packageName}}}.configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +configuration = {{{packageName}}}.Configuration() +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} # Configure API key authorization: {{{name}}} -{{{packageName}}}.configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +configuration = {{{packageName}}}.Configuration() +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# {{{packageName}}}.configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} # Configure OAuth2 access token for authorization: {{{name}}} -{{{packageName}}}.configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} +configuration = {{{packageName}}}.Configuration() +configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} {{/hasAuthMethods}} + # create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}() +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} From 30b63c01b3561175e57ff3b7234e26dcba749b08 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 8 May 2018 01:23:49 +0800 Subject: [PATCH 009/180] Update python default value (#360) * update pythong default value * fix example, update python sample * update python petstore sample (asyncio, tornado) --- api.mustache | 1 - api_client.mustache | 19 +++++++++---------- model.mustache | 8 ++++---- partial_header.mustache | 8 ++++++-- rest.mustache | 2 +- setup.mustache | 2 +- 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/api.mustache b/api.mustache index 1925d4d164..ebafd266e9 100644 --- a/api.mustache +++ b/api.mustache @@ -17,7 +17,6 @@ class {{classname}}(object): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). Do not edit the class manually. - Ref: https://openapi-generator.tech """ def __init__(self, api_client=None): diff --git a/api_client.mustache b/api_client.mustache index 4b7b2bf86a..bd72c76769 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -23,15 +23,14 @@ from {{packageName}} import rest class ApiClient(object): - """Generic API client for Swagger client library builds. + """Generic API client for OpenAPI client library builds. - Swagger generic API client. This client handles the client- + OpenAPI generic API client. This client handles the client- server communication, and is invariant across implementations. Specifics of - the methods and models for each application are generated from the Swagger + the methods and models for each application are generated from the OpenAPI templates. NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - Ref: https://openapi-generator.tech Do not edit the class manually. :param configuration: .Configuration object for this client @@ -183,7 +182,7 @@ class ApiClient(object): convert to string in iso8601 format. If obj is list, sanitize each element in the list. If obj is dict, return the dict. - If obj is swagger model, return the properties dict. + If obj is OpenAPI model, return the properties dict. :param obj: The data to serialize. :return: The serialized form of data. @@ -205,12 +204,12 @@ class ApiClient(object): obj_dict = obj else: # Convert model obj to dict except - # attributes `swagger_types`, `attribute_map` + # attributes `openapi_types`, `attribute_map` # and attributes which value is not None. # Convert attribute name to json key in # model definition for request. obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) - for attr, _ in six.iteritems(obj.swagger_types) + for attr, _ in six.iteritems(obj.openapi_types) if getattr(obj, attr) is not None} return {key: self.sanitize_for_serialization(val) @@ -605,13 +604,13 @@ class ApiClient(object): :return: model object. """ - if not klass.swagger_types and not hasattr(klass, + if not klass.openapi_types and not hasattr(klass, 'get_real_child_model'): return data kwargs = {} - if klass.swagger_types is not None: - for attr, attr_type in six.iteritems(klass.swagger_types): + if klass.openapi_types is not None: + for attr, attr_type in six.iteritems(klass.openapi_types): if (data is not None and klass.attribute_map[attr] in data and isinstance(data, (list, dict))): diff --git a/model.mustache b/model.mustache index 9d7a6f9a6b..3d69ce83b1 100644 --- a/model.mustache +++ b/model.mustache @@ -30,12 +30,12 @@ class {{classname}}(object): """ Attributes: - swagger_types (dict): The key is attribute name + openapi_types (dict): The key is attribute name and the value is attribute type. attribute_map (dict): The key is attribute name and the value is json key in definition. """ - swagger_types = { + openapi_types = { {{#vars}} '{{name}}': '{{{datatype}}}'{{#hasMore}},{{/hasMore}} {{/vars}} @@ -55,7 +55,7 @@ class {{classname}}(object): {{/discriminator}} def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 - """{{classname}} - a model defined in Swagger""" # noqa: E501 + """{{classname}} - a model defined in OpenAPI""" # noqa: E501 {{#vars}}{{#-first}} {{/-first}} self._{{name}} = None @@ -177,7 +177,7 @@ class {{classname}}(object): """Returns the model properties as a dict""" result = {} - for attr, _ in six.iteritems(self.swagger_types): + for attr, _ in six.iteritems(self.openapi_types): value = getattr(self, attr) if isinstance(value, list): result[attr] = list(map( diff --git a/partial_header.mustache b/partial_header.mustache index 929e512e08..b83479cdbb 100644 --- a/partial_header.mustache +++ b/partial_header.mustache @@ -7,7 +7,11 @@ {{{appDescription}}} # noqa: E501 {{/appDescription}} - {{#version}}OpenAPI spec version: {{{version}}}{{/version}} - {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}} + {{#version}} + OpenAPI spec version: {{{version}}} + {{/version}} + {{#infoEmail}} + Contact: {{{infoEmail}}} + {{/infoEmail}} Generated by: https://openapi-generator.tech """ diff --git a/rest.mustache b/rest.mustache index ff9b019dc5..8418ec2a0f 100644 --- a/rest.mustache +++ b/rest.mustache @@ -18,7 +18,7 @@ from six.moves.urllib.parse import urlencode try: import urllib3 except ImportError: - raise ImportError('Swagger python client requires urllib3.') + raise ImportError('OpenAPI Python client requires urllib3.') logger = logging.getLogger(__name__) diff --git a/setup.mustache b/setup.mustache index 597136a8d1..15d2450471 100644 --- a/setup.mustache +++ b/setup.mustache @@ -30,7 +30,7 @@ setup( description="{{appName}}", author_email="{{infoEmail}}", url="{{packageUrl}}", - keywords=["Swagger", "{{appName}}"], + keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], install_requires=REQUIRES, packages=find_packages(), include_package_data=True, From 604c88b98f2b041a2713f463e43886354e1acec6 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 12 May 2018 09:54:19 +0800 Subject: [PATCH 010/180] Update python test (#426) * update python test folders * update python template * update python samples * fix python comment too long * update ruby test case --- api.mustache | 3 ++- api_client.mustache | 3 ++- configuration.mustache | 2 +- model.mustache | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api.mustache b/api.mustache index ebafd266e9..60ec9ff0a4 100644 --- a/api.mustache +++ b/api.mustache @@ -14,7 +14,8 @@ from {{packageName}}.api_client import ApiClient {{#operations}} class {{classname}}(object): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech Do not edit the class manually. """ diff --git a/api_client.mustache b/api_client.mustache index bd72c76769..b044229828 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -30,7 +30,8 @@ class ApiClient(object): the methods and models for each application are generated from the OpenAPI templates. - NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech Do not edit the class manually. :param configuration: .Configuration object for this client diff --git a/configuration.mustache b/configuration.mustache index 72702d8d1f..398c1d3dab 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -29,7 +29,7 @@ class TypeWithDefault(type): class Configuration(six.with_metaclass(TypeWithDefault, object)): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + """NOTE: This class is auto generated by OpenAPI Generator Ref: https://openapi-generator.tech Do not edit the class manually. diff --git a/model.mustache b/model.mustache index 3d69ce83b1..a2f899eeea 100644 --- a/model.mustache +++ b/model.mustache @@ -15,7 +15,8 @@ import six {{#models}} {{#model}} class {{classname}}(object): - """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech Do not edit the class manually. """{{#allowableValues}} From 3ca216f935061b4cd2972c8b17da2bae443c5d25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Bresson?= Date: Fri, 18 May 2018 18:06:37 +0200 Subject: [PATCH 011/180] Rename datatype to dataType in CodegenProperty (#69) --- model.mustache | 6 +++--- model_doc.mustache | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/model.mustache b/model.mustache index a2f899eeea..acac422fd6 100644 --- a/model.mustache +++ b/model.mustache @@ -38,7 +38,7 @@ class {{classname}}(object): """ openapi_types = { {{#vars}} - '{{name}}': '{{{datatype}}}'{{#hasMore}},{{/hasMore}} + '{{name}}': '{{{dataType}}}'{{#hasMore}},{{/hasMore}} {{/vars}} } @@ -83,7 +83,7 @@ class {{classname}}(object): {{/description}} :return: The {{name}} of this {{classname}}. # noqa: E501 - :rtype: {{datatype}} + :rtype: {{dataType}} """ return self._{{name}} @@ -96,7 +96,7 @@ class {{classname}}(object): {{/description}} :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 - :type: {{datatype}} + :type: {{dataType}} """ {{#required}} if {{name}} is None: diff --git a/model_doc.mustache b/model_doc.mustache index 569550df37..0216a3372c 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{datatype}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{datatype}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} {{/vars}} [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) From 719ab23beabdee87de680d525d286af678c0dc16 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Thu, 24 May 2018 17:10:07 +0200 Subject: [PATCH 012/180] [python] asyncio supports _preload_content; remove unsed imports (#107) * chore: update python samples * feat: python/asyncio support for _preload_content * feat: remove unused imports from python clients; fix discriminator --- asyncio/rest.mustache | 16 +++++++++++----- model.mustache | 6 +----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 39003abfbf..8c9d49dc14 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -10,6 +10,7 @@ import ssl import aiohttp import certifi +import asyncio # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode @@ -70,6 +71,9 @@ class RESTClientObject(object): connector=connector ) + def __del__(self): + asyncio.ensure_future(self.pool_manager.close()) + async def request(self, method, url, query_params=None, headers=None, body=None, post_params=None, _preload_content=True, _request_timeout=None): @@ -152,15 +156,17 @@ class RESTClientObject(object): declared content type.""" raise ApiException(status=0, reason=msg) - async with self.pool_manager.request(**args) as r: + r = await self.pool_manager.request(**args) + if _preload_content: + data = await r.text() r = RESTResponse(r, data) - # log response body - logger.debug("response body: %s", r.data) + # log response body + logger.debug("response body: %s", r.data) - if not 200 <= r.status <= 299: - raise ApiException(http_resp=r) + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) return r diff --git a/model.mustache b/model.mustache index acac422fd6..123577adb8 100644 --- a/model.mustache +++ b/model.mustache @@ -6,10 +6,6 @@ import pprint import re # noqa: F401 import six -{{#imports}}{{#-first}} -{{/-first}} -{{import}} # noqa: F401,E501 -{{/imports}} {{#models}} @@ -170,7 +166,7 @@ class {{classname}}(object): {{#discriminator}} def get_real_child_model(self, data): """Returns the real base class specified by the discriminator""" - discriminator_value = data[self.discriminator].lower() + discriminator_value = data[self.discriminator] return self.discriminator_value_class_map.get(discriminator_value) {{/discriminator}} From d4895f437a3b8287293d545f9350507959b0d9cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 16 Jun 2018 19:49:01 +0300 Subject: [PATCH 013/180] Grammar and spelling fixes (#329) --- api_client.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index b044229828..61807efaec 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -552,7 +552,7 @@ class ApiClient(object): return data def __deserialize_object(self, value): - """Return a original value. + """Return an original value. :return: object. """ From 87a87314b0d4dd92368482ac158ea2b6d9f275de Mon Sep 17 00:00:00 2001 From: William Cheng Date: Tue, 10 Jul 2018 22:12:09 +0800 Subject: [PATCH 014/180] Improve logging in Python client (#480) * improve logging in python client * update samples --- configuration.mustache | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 398c1d3dab..8077c1ccf0 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -125,17 +125,6 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): self.logger_file_handler.setFormatter(self.logger_formatter) for _, logger in six.iteritems(self.logger): logger.addHandler(self.logger_file_handler) - if self.logger_stream_handler: - logger.removeHandler(self.logger_stream_handler) - else: - # If not set logging file, - # then add stream handler and remove file handler. - self.logger_stream_handler = logging.StreamHandler() - self.logger_stream_handler.setFormatter(self.logger_formatter) - for _, logger in six.iteritems(self.logger): - logger.addHandler(self.logger_stream_handler) - if self.logger_file_handler: - logger.removeHandler(self.logger_file_handler) @property def debug(self): From 0480fa141923aa576a48783978825df857aac7eb Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Thu, 12 Jul 2018 15:30:57 +0200 Subject: [PATCH 015/180] feat: use local_var_params to avoid collision with api parameters (#521) --- api.mustache | 63 ++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/api.mustache b/api.mustache index 60ec9ff0a4..5d937ec32a 100644 --- a/api.mustache +++ b/api.mustache @@ -82,26 +82,27 @@ class {{classname}}(object): returns the request thread. """ + local_var_params = locals() + all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 all_params.append('async') all_params.append('_return_http_data_only') all_params.append('_preload_content') all_params.append('_request_timeout') - params = locals() - for key, val in six.iteritems(params['kwargs']): + for key, val in six.iteritems(local_var_params['kwargs']): if key not in all_params: raise TypeError( "Got an unexpected keyword argument '%s'" " to method {{operationId}}" % key ) - params[key] = val - del params['kwargs'] + local_var_params[key] = val + del local_var_params['kwargs'] {{#allParams}} {{#required}} # verify the required parameter '{{paramName}}' is set - if ('{{paramName}}' not in params or - params['{{paramName}}'] is None): + if ('{{paramName}}' not in local_var_params or + local_var_params['{{paramName}}'] is None): raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 {{/required}} {{/allParams}} @@ -109,35 +110,35 @@ class {{classname}}(object): {{#allParams}} {{#hasValidation}} {{#maxLength}} - if ('{{paramName}}' in params and - len(params['{{paramName}}']) > {{maxLength}}): + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) > {{maxLength}}): raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 {{/maxLength}} {{#minLength}} - if ('{{paramName}}' in params and - len(params['{{paramName}}']) < {{minLength}}): + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) < {{minLength}}): raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 {{/minLength}} {{#maximum}} - if '{{paramName}}' in params and params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 {{/maximum}} {{#minimum}} - if '{{paramName}}' in params and params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} - if '{{paramName}}' in params and not re.search('{{{vendorExtensions.x-regex}}}', params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + if '{{paramName}}' in local_var_params and not re.search('{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} - if ('{{paramName}}' in params and - len(params['{{paramName}}']) > {{maxItems}}): + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) > {{maxItems}}): raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 {{/maxItems}} {{#minItems}} - if ('{{paramName}}' in params and - len(params['{{paramName}}']) < {{minItems}}): + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) < {{minItems}}): raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 {{/minItems}} {{/hasValidation}} @@ -148,37 +149,37 @@ class {{classname}}(object): path_params = {} {{#pathParams}} - if '{{paramName}}' in params: - path_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + if '{{paramName}}' in local_var_params: + path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/pathParams}} query_params = [] {{#queryParams}} - if '{{paramName}}' in params: - query_params.append(('{{baseName}}', params['{{paramName}}'])){{#isListContainer}} # noqa: E501 + if '{{paramName}}' in local_var_params: + query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/queryParams}} header_params = {} {{#headerParams}} - if '{{paramName}}' in params: - header_params['{{baseName}}'] = params['{{paramName}}']{{#isListContainer}} # noqa: E501 + if '{{paramName}}' in local_var_params: + header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/headerParams}} form_params = [] local_var_files = {} {{#formParams}} - if '{{paramName}}' in params: - {{^isFile}}form_params.append(('{{baseName}}', params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 + if '{{paramName}}' in local_var_params: + {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/formParams}} body_params = None {{#bodyParam}} - if '{{paramName}}' in params: - body_params = params['{{paramName}}'] + if '{{paramName}}' in local_var_params: + body_params = local_var_params['{{paramName}}'] {{/bodyParam}} {{#hasProduces}} # HTTP header `Accept` @@ -205,10 +206,10 @@ class {{classname}}(object): files=local_var_files, response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 auth_settings=auth_settings, - async=params.get('async'), - _return_http_data_only=params.get('_return_http_data_only'), - _preload_content=params.get('_preload_content', True), - _request_timeout=params.get('_request_timeout'), + async=local_var_params.get('async'), + _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 + _preload_content=local_var_params.get('_preload_content', True), + _request_timeout=local_var_params.get('_request_timeout'), collection_formats=collection_formats) {{/operation}} {{/operations}} From 00acbc9df8b8a390b2ab889a8ddebd8a41a3c246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Berthom=C3=A9?= Date: Mon, 16 Jul 2018 09:49:08 +0200 Subject: [PATCH 016/180] [Python][Client] pure library client package (#470) * Python client pure library package * check onlyPackage CLI option * run /bin/python-petstore.sh, update the python samples for CI * onlyPackage local variable instead of classp property * fix CI: __future__ absolute_import must be first in file * update samples * generateSourceCodeOnly * updated samples --- README.mustache | 76 +------------------------------------ README_onlypackage.mustache | 44 +++++++++++++++++++++ __init__package.mustache | 2 + common_README.mustache | 75 ++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+), 75 deletions(-) create mode 100644 README_onlypackage.mustache create mode 100644 common_README.mustache diff --git a/README.mustache b/README.mustache index cf92dc583d..be83533906 100644 --- a/README.mustache +++ b/README.mustache @@ -52,78 +52,4 @@ import {{{packageName}}} Please follow the [installation procedure](#installation--usage) and then run the following: -```python -from __future__ import print_function -import time -import {{{packageName}}} -from {{{packageName}}}.rest import ApiException -from pprint import pprint -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} -# Configure HTTP basic authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.username = 'YOUR_USERNAME' -configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} -# Configure API key authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} -# Configure OAuth2 access token for authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} -{{/hasAuthMethods}} - -# create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} - -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} -``` - -## Documentation for API Endpoints - -All URIs are relative to *{{basePath}}* - -Class | Method | HTTP request | Description ------------- | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} - -## Documentation For Models - -{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) -{{/model}}{{/models}} - -## Documentation For Authorization - -{{^authMethods}} All endpoints do not require authorization. -{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} -{{#authMethods}}## {{{name}}} - -{{#isApiKey}}- **Type**: API key -- **API key parameter name**: {{{keyParamName}}} -- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} -{{/isApiKey}} -{{#isBasic}}- **Type**: HTTP basic authentication -{{/isBasic}} -{{#isOAuth}}- **Type**: OAuth -- **Flow**: {{{flow}}} -- **Authorization URL**: {{{authorizationUrl}}} -- **Scopes**: {{^scopes}}N/A{{/scopes}} -{{#scopes}} - **{{{scope}}}**: {{{description}}} -{{/scopes}} -{{/isOAuth}} - -{{/authMethods}} - -## Author - -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{> common_README }} diff --git a/README_onlypackage.mustache b/README_onlypackage.mustache new file mode 100644 index 0000000000..826454b1ea --- /dev/null +++ b/README_onlypackage.mustache @@ -0,0 +1,44 @@ +# {{{projectName}}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +The `{{packageName}}` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage + +This python library package is generated without supporting files like setup.py or requirements files + +To be able to use it, you will need these dependencies in your own package that uses this library: + +* urllib3 >= 1.15 +* six >= 1.10 +* certifi +* python-dateutil +{{#asyncio}} +* aiohttp +{{/asyncio}} +{{#tornado}} +* tornado>=4.2,<5 +{{/tornado}} + +## Getting Started + +In your own code, to use this library to connect and interact with {{{projectName}}}, +you can run the following: + +{{> common_README }} diff --git a/__init__package.mustache b/__init__package.mustache index cd42506f54..a21c6dbac9 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -6,6 +6,8 @@ from __future__ import absolute_import +__version__ = "{{packageVersion}}" + # import apis into sdk package {{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} {{/apis}}{{/apiInfo}} diff --git a/common_README.mustache b/common_README.mustache new file mode 100644 index 0000000000..f203456f20 --- /dev/null +++ b/common_README.mustache @@ -0,0 +1,75 @@ +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} +{{/hasAuthMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} All endpoints do not require authorization. +{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} +{{#authMethods}}## {{{name}}} + +{{#isApiKey}}- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}}- **Type**: HTTP basic authentication +{{/isBasic}} +{{#isOAuth}}- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} From 80f5fa7b6babcde2102b74c6189f03d440da562d Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Fri, 20 Jul 2018 16:14:18 +0200 Subject: [PATCH 017/180] Support for python 3.7 by renaming `async` to `async_req` (#519) * feat: support for python 3.7 * fix: regenerate other sample clients --- api.mustache | 22 +++++++++++----------- api_client.mustache | 12 ++++++------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/api.mustache b/api.mustache index 5d937ec32a..ff4835b3b1 100644 --- a/api.mustache +++ b/api.mustache @@ -33,16 +33,16 @@ class {{classname}}(object): {{{notes}}} # noqa: E501 {{/notes}} This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async=True + asynchronous HTTP request, please pass async_req=True {{#sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} {{^sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async bool + :param async_req bool {{#allParams}} :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} {{/allParams}} @@ -51,7 +51,7 @@ class {{classname}}(object): returns the request thread. """ kwargs['_return_http_data_only'] = True - if kwargs.get('async'): + if kwargs.get('async_req'): return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 else: (data) = self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 @@ -64,16 +64,16 @@ class {{classname}}(object): {{{notes}}} # noqa: E501 {{/notes}} This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async=True + asynchronous HTTP request, please pass async_req=True {{#sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async=True) + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} {{^sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async=True) + >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async bool + :param async_req bool {{#allParams}} :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/optional}} {{/allParams}} @@ -85,7 +85,7 @@ class {{classname}}(object): local_var_params = locals() all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 - all_params.append('async') + all_params.append('async_req') all_params.append('_return_http_data_only') all_params.append('_preload_content') all_params.append('_request_timeout') @@ -206,7 +206,7 @@ class {{classname}}(object): files=local_var_files, response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 auth_settings=auth_settings, - async=local_var_params.get('async'), + async_req=local_var_params.get('async_req'), _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 _preload_content=local_var_params.get('_preload_content', True), _request_timeout=local_var_params.get('_request_timeout'), diff --git a/api_client.mustache b/api_client.mustache index 61807efaec..659d267a2d 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -280,12 +280,12 @@ class ApiClient(object): def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, - response_type=None, auth_settings=None, async=None, + response_type=None, auth_settings=None, async_req=None, _return_http_data_only=None, collection_formats=None, _preload_content=True, _request_timeout=None): """Makes the HTTP request (synchronous) and returns deserialized data. - To make an async request, set the async parameter. + To make an async_req request, set the async_req parameter. :param resource_path: Path to method endpoint. :param method: Method to call. @@ -300,7 +300,7 @@ class ApiClient(object): :param response: Response data type. :param files dict: key -> filename, value -> filepath, for `multipart/form-data`. - :param async bool: execute request asynchronously + :param async_req bool: execute request asynchronously :param _return_http_data_only: response data without head status code and headers :param collection_formats: dict of collection formats for path, query, @@ -313,13 +313,13 @@ class ApiClient(object): timeout. It can also be a pair (tuple) of (connection, read) timeouts. :return: - If async parameter is True, + If async_req parameter is True, the request will be called asynchronously. The method will return the request thread. - If parameter async is False or missing, + If parameter async_req is False or missing, then the method will return the response directly. """ - if not async: + if not async_req: return self.__call_api(resource_path, method, path_params, query_params, header_params, body, post_params, files, From 51305f2f25119e5dff3d0e4aca50f2912c5267f4 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Fri, 24 Aug 2018 03:43:32 +0200 Subject: [PATCH 018/180] fix: python-asyncio/aiohttp with disabled ssl verification (#891) --- asyncio/rest.mustache | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 8c9d49dc14..528e550d74 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -38,21 +38,24 @@ class RESTClientObject(object): def __init__(self, configuration, pools_size=4, maxsize=4): # maxsize is number of requests to host that are allowed in parallel - # ca_certs vs cert_file vs key_file - # http://stackoverflow.com/a/23957365/2985775 - # ca_certs - if configuration.ssl_ca_cert: - ca_certs = configuration.ssl_ca_cert - else: - # if not set certificate file, use Mozilla's root certificates. - ca_certs = certifi.where() + if configuration.verify_ssl: - ssl_context = ssl.create_default_context(cafile=ca_certs) - if configuration.cert_file: - ssl_context.load_cert_chain( - configuration.cert_file, keyfile=configuration.key_file - ) + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + ssl_context = ssl.create_default_context(cafile=ca_certs) + + if configuration.cert_file: + ssl_context.load_cert_chain( + configuration.cert_file, keyfile=configuration.key_file + ) + else: + ssl_context = None connector = aiohttp.TCPConnector( limit=maxsize, From 9a83d8862fce8ed448cf06b52e5df9293eb09d8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Berthom=C3=A9?= Date: Fri, 31 Aug 2018 15:35:37 +0200 Subject: [PATCH 019/180] [PYTHON] Api doc python with multiple authentications (#928) * [PYTHON] better code snippet for API usage with authentication * update python samples --- api_doc.mustache | 43 +++++----------------------------------- api_doc_example.mustache | 40 +++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 38 deletions(-) create mode 100644 api_doc_example.mustache diff --git a/api_doc.mustache b/api_doc.mustache index 32c26d929d..c16779a5f9 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -18,47 +18,14 @@ Method | HTTP request | Description {{{notes}}}{{/notes}} ### Example -```python -from __future__ import print_function -import time -import {{{packageName}}} -from {{{packageName}}}.rest import ApiException -from pprint import pprint -{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} -# Configure HTTP basic authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.username = 'YOUR_USERNAME' -configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} -# Configure API key authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} -# Configure OAuth2 access token for authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() -configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} - -# create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +{{#hasAuthMethods}}{{#authMethods}} +{{#isBasic}}* Basic Authentication ({{name}}): {{/isBasic }}{{#isApiKey}}* Api Key Authentication ({{name}}): {{/isApiKey }}{{#isOAuth}}* OAuth Authentication ({{name}}): {{/isOAuth }} +{{> api_doc_example }} +{{/authMethods}} {{/hasAuthMethods}} {{^hasAuthMethods}} - -# create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}() -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +{{> api_doc_example }} {{/hasAuthMethods}} - -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -``` - ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes diff --git a/api_doc_example.mustache b/api_doc_example.mustache new file mode 100644 index 0000000000..42e0f32bf7 --- /dev/null +++ b/api_doc_example.mustache @@ -0,0 +1,40 @@ +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{#hasAuthMethods}}{{#isBasic}} +# Configure HTTP basic authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} +# Configure API key authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration() +configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} +{{^hasAuthMethods}} + +# create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} +{{/hasAuthMethods}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +``` From af07b4c2be49a151fe22b0918df40072c7a2507b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Sat, 29 Sep 2018 17:01:13 +0800 Subject: [PATCH 020/180] Add nullable support to Python client (#1073) * add nullable support to python client * update PR template --- api.mustache | 2 ++ model.mustache | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/api.mustache b/api.mustache index ff4835b3b1..cfdf88cf09 100644 --- a/api.mustache +++ b/api.mustache @@ -99,12 +99,14 @@ class {{classname}}(object): local_var_params[key] = val del local_var_params['kwargs'] {{#allParams}} +{{^isNullable}} {{#required}} # verify the required parameter '{{paramName}}' is set if ('{{paramName}}' not in local_var_params or local_var_params['{{paramName}}'] is None): raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 {{/required}} +{{/isNullable}} {{/allParams}} {{#allParams}} diff --git a/model.mustache b/model.mustache index 123577adb8..2652a3090e 100644 --- a/model.mustache +++ b/model.mustache @@ -64,8 +64,13 @@ class {{classname}}(object): self.{{name}} = {{name}} {{/required}} {{^required}} +{{#isNullable}} + self.{{name}} = {{name}} +{{/isNullable}} +{{^isNullable}} if {{name}} is not None: self.{{name}} = {{name}} +{{/isNullable}} {{/required}} {{/vars}} @@ -94,10 +99,12 @@ class {{classname}}(object): :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 :type: {{dataType}} """ +{{^isNullable}} {{#required}} if {{name}} is None: raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 {{/required}} +{{/isNullable}} {{#isEnum}} {{#isContainer}} allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 From 633170aa28e892fa262e9407e7fec7dbd14d4bb1 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Fri, 12 Oct 2018 11:05:01 +0200 Subject: [PATCH 021/180] fix: python/asyncio no-ssl-verify affects verification of server certs only (#1211) Bug fix: python/asyncio no-ssl-verify affects verification of server certs --- asyncio/rest.mustache | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 528e550d74..9c1a0cc81d 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -39,28 +39,26 @@ class RESTClientObject(object): def __init__(self, configuration, pools_size=4, maxsize=4): # maxsize is number of requests to host that are allowed in parallel - if configuration.verify_ssl: - - # ca_certs - if configuration.ssl_ca_cert: - ca_certs = configuration.ssl_ca_cert - else: - # if not set certificate file, use Mozilla's root certificates. - ca_certs = certifi.where() + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() - ssl_context = ssl.create_default_context(cafile=ca_certs) + ssl_context = ssl.create_default_context(cafile=ca_certs) + if configuration.cert_file: + ssl_context.load_cert_chain( + configuration.cert_file, keyfile=configuration.key_file + ) - if configuration.cert_file: - ssl_context.load_cert_chain( - configuration.cert_file, keyfile=configuration.key_file - ) - else: - ssl_context = None + if not configuration.verify_ssl: + ssl_context.check_hostname = False + ssl_context.verify_mode = ssl.CERT_NONE connector = aiohttp.TCPConnector( limit=maxsize, - ssl_context=ssl_context, - verify_ssl=configuration.verify_ssl + ssl_context=ssl_context ) # https pool manager From e4d88532bdbaed12f3d2bb6b413f89ad9e8a33c9 Mon Sep 17 00:00:00 2001 From: micw523 Date: Sat, 27 Oct 2018 22:16:54 -0500 Subject: [PATCH 022/180] Fix W605 Warning and reenable flake8 (#1334) --- api.mustache | 6 +++--- api_client.mustache | 4 ++-- model.mustache | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api.mustache b/api.mustache index cfdf88cf09..1109aaebdc 100644 --- a/api.mustache +++ b/api.mustache @@ -27,7 +27,7 @@ class {{classname}}(object): {{#operation}} def {{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 - """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 {{#notes}} {{{notes}}} # noqa: E501 @@ -58,7 +58,7 @@ class {{classname}}(object): return data def {{operationId}}_with_http_info(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 - """{{#summary}}{{.}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 {{#notes}} {{{notes}}} # noqa: E501 @@ -130,7 +130,7 @@ class {{classname}}(object): raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} - if '{{paramName}}' in local_var_params and not re.search('{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + if '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} diff --git a/api_client.mustache b/api_client.mustache index 659d267a2d..4e630dc34b 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -251,12 +251,12 @@ class ApiClient(object): if type(klass) == str: if klass.startswith('list['): - sub_kls = re.match('list\[(.*)\]', klass).group(1) + sub_kls = re.match(r'list\[(.*)\]', klass).group(1) return [self.__deserialize(sub_data, sub_kls) for sub_data in data] if klass.startswith('dict('): - sub_kls = re.match('dict\(([^,]*), (.*)\)', klass).group(2) + sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) return {k: self.__deserialize(v, sub_kls) for k, v in six.iteritems(data)} diff --git a/model.mustache b/model.mustache index 2652a3090e..cde5cb3718 100644 --- a/model.mustache +++ b/model.mustache @@ -153,8 +153,8 @@ class {{classname}}(object): raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} - if {{name}} is not None and not re.search('{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 + if {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError(r"Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} if {{name}} is not None and len({{name}}) > {{maxItems}}: From 3f328472f9bd68b1f7771b8b37c9f834b4dadc42 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 8 Nov 2018 17:39:20 +0800 Subject: [PATCH 023/180] [python] Avoid creating unused ThreadPools (#1387) * Avoid creating unused ThreadPools Instead, create ApiClient.pool on first request for .pool property. avoids spawning n-cpus threads (the default for ThreadPool) at instantiation of every ApiClient * update doc * set pool_thread to None --- api_client.mustache | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 4e630dc34b..b89911d51d 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -40,6 +40,8 @@ class ApiClient(object): the API. :param cookie: a cookie to include in the header when making calls to the API + :param pool_threads: The number of threads to use for async requests + to the API. More threads means more concurrent API requests. """ PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types @@ -53,14 +55,15 @@ class ApiClient(object): 'datetime': datetime.datetime, 'object': object, } + _pool = None def __init__(self, configuration=None, header_name=None, header_value=None, - cookie=None): + cookie=None, pool_threads=None): if configuration is None: configuration = Configuration() self.configuration = configuration + self.pool_threads = pool_threads - self.pool = ThreadPool() self.rest_client = rest.RESTClientObject(configuration) self.default_headers = {} if header_name is not None: @@ -70,8 +73,19 @@ class ApiClient(object): self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' def __del__(self): - self.pool.close() - self.pool.join() + if self._pool: + self._pool.close() + self._pool.join() + self._pool = None + + @property + def pool(self): + """Create thread pool on first request + avoids instantiating unused threadpool for blocking clients. + """ + if self._pool is None: + self._pool = ThreadPool(self.pool_threads) + return self._pool @property def user_agent(self): From 41140be176471d8cb9b642784901bdc853b38209 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 9 Nov 2018 23:44:47 +0800 Subject: [PATCH 024/180] change python pool_thread default to 1 (#1403) --- api_client.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index b89911d51d..b0976ba9f2 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -58,7 +58,7 @@ class ApiClient(object): _pool = None def __init__(self, configuration=None, header_name=None, header_value=None, - cookie=None, pool_threads=None): + cookie=None, pool_threads=1): if configuration is None: configuration = Configuration() self.configuration = configuration From 11e8658fc555ea0abad49503b7fd86ee99d8baed Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Fri, 21 Dec 2018 02:52:27 +0100 Subject: [PATCH 025/180] feat: [python/asyncio] use ssl argument instead of ssl_context (deprecated from aiohttp>=3.0.0) (#1724) --- asyncio/rest.mustache | 2 +- setup.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 9c1a0cc81d..727dfae423 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -58,7 +58,7 @@ class RESTClientObject(object): connector = aiohttp.TCPConnector( limit=maxsize, - ssl_context=ssl_context + ssl=ssl_context ) # https pool manager diff --git a/setup.mustache b/setup.mustache index 15d2450471..201b79e217 100644 --- a/setup.mustache +++ b/setup.mustache @@ -18,7 +18,7 @@ VERSION = "{{packageVersion}}" REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] {{#asyncio}} -REQUIRES.append("aiohttp") +REQUIRES.append("aiohttp >= 3.0.0") {{/asyncio}} {{#tornado}} REQUIRES.append("tornado>=4.2,<5") From 24ef7989fec06f1d09c1c914c0b7ac629b2f6a2b Mon Sep 17 00:00:00 2001 From: Justin Black Date: Tue, 8 Jan 2019 19:18:35 -0800 Subject: [PATCH 026/180] [python-client] Add model default values (#1776) * Adds two models to the v2.0 spec, uses examples as defaults in python client * Adds array default and type_holder_default and type_holder_example tests * Re-generated python security client with ./bin/security/python-petstore.sh * Changes comment text, rebased master * Updates client + server samples * Adds missing samples updates * Changes python client to look for true or false with booleans in toDefaultValue * Changes boolean casting to use Boolean.valueOf * Adds deserialization fix for python tests * Changes Mock to namedtuple in python deserialization tests * Actually remove unittest.mock --- model.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/model.mustache b/model.mustache index cde5cb3718..c3ab5cb020 100644 --- a/model.mustache +++ b/model.mustache @@ -173,7 +173,8 @@ class {{classname}}(object): {{#discriminator}} def get_real_child_model(self, data): """Returns the real base class specified by the discriminator""" - discriminator_value = data[self.discriminator] + discriminator_key = self.attribute_map[self.discriminator] + discriminator_value = data[discriminator_key] return self.discriminator_value_class_map.get(discriminator_value) {{/discriminator}} From 34bb18001a84bc33306d566adeb1ba2d933edb75 Mon Sep 17 00:00:00 2001 From: Jacob Floyd Date: Fri, 11 Jan 2019 05:15:03 -0600 Subject: [PATCH 027/180] Python: Update api_doc_example for multiple auth (#1870) APIs may more than one auth method (for example both an app key and basic auth). This changes the example to only initialize the config option once instead of once per auth method. --- api_doc_example.mustache | 6 ++---- common_README.mustache | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/api_doc_example.mustache b/api_doc_example.mustache index 42e0f32bf7..282bacf69c 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -4,18 +4,16 @@ import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint -{{#hasAuthMethods}}{{#isBasic}} +{{#hasAuthMethods}} +configuration = {{{packageName}}}.Configuration(){{#isBasic}} # Configure HTTP basic authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.username = 'YOUR_USERNAME' configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} # Configure API key authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} # Configure OAuth2 access token for authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}} # create an instance of the API class diff --git a/common_README.mustache b/common_README.mustache index f203456f20..194fb14b59 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -4,18 +4,16 @@ import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}} +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}} +configuration = {{{packageName}}}.Configuration(){{#isBasic}} # Configure HTTP basic authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.username = 'YOUR_USERNAME' configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} # Configure API key authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} # Configure OAuth2 access token for authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} {{/hasAuthMethods}} From f7d300cd94f92e59c3c1291fb6d8d8f452f9eee9 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sat, 26 Jan 2019 01:26:38 -0800 Subject: [PATCH 028/180] [Spec] adds XmlItem model and route for xml testing (#1883) * Adds xmlitem model and route, rest-assured Api suffix fix, updates pytest and pytest-cov versions * Adds python client sample files * Adds samples update * Adds rest-assured sample client update * Adds sample updates in ensure-up-to-date * Changes rest-assured files back to master version, removes fix for issue #13 * Updates samples --- test-requirements.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-requirements.mustache b/test-requirements.mustache index 31f8d94d99..d9e3f20b53 100644 --- a/test-requirements.mustache +++ b/test-requirements.mustache @@ -3,8 +3,8 @@ coverage>=4.0.3 nose>=1.3.7 {{/asyncio}} {{#asyncio}} -pytest>=3.3.1 -pytest-cov>=2.5.1 +pytest>=3.6.0 +pytest-cov>=2.6.1 {{/asyncio}} pluggy>=0.3.1 py>=1.4.31 From fc3247e0066dcf30e3807b0641251d99f0babdda Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 28 Jan 2019 11:24:48 +0800 Subject: [PATCH 029/180] Add multiple servers support to Python client (#1969) * add multiple server support to python client * various fixes * minor fixes, add tests * test oas2 python first * fix tests * fix issues reported by flake8 * update code format * add python petstore to ensure up-to-date * rearrange test * fix E501 * fix tests * add new files * fix script permission * fix index check * update samples --- configuration.mustache | 74 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index 8077c1ccf0..562c036e9f 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -247,3 +247,77 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): "Version of the API: {{version}}\n"\ "SDK Package Version: {{packageVersion}}".\ format(env=sys.platform, pyversion=sys.version) + + def get_host_settings(self): + """Gets an array of host settings + + :return: An array of host settings + """ + return [ + {{#servers}} + { + 'url': "{{{url}}}", + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + 'variables': { + {{/-first}} + '{{{name}}}': { + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + 'default_value': "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + 'enum_values': [ + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ] + {{/-last}} + {{/enumValues}} + }{{^-last}},{{/-last}} + {{#-last}} + } + {{/-last}} + {{/variables}} + }{{^-last}},{{/-last}} + {{/servers}} + ] + + def get_host_from_settings(self, index, variables={}): + """Gets host URL based on the index and variables + :param index: array index of the host settings + :param variables: hash of variable and the corresponding value + :return: URL based on host settings + """ + + servers = self.get_host_settings() + + # check array index out of bound + if index < 0 or index >= len(servers): + raise ValueError( + "Invalid index {} when selecting the host settings. Must be less than {}" # noqa: E501 + .format(index, len(servers))) + + server = servers[index] + url = server['url'] + + # go through variable and assign a value + for variable_name in server['variables']: + if variable_name in variables: + if variables[variable_name] in server['variables'][ + variable_name]['enum_values']: + url = url.replace("{" + variable_name + "}", + variables[variable_name]) + else: + raise ValueError( + "The variable `{}` in the host URL has invalid value {}. Must be {}." # noqa: E501 + .format( + variable_name, variables[variable_name], + server['variables'][variable_name]['enum_values'])) + else: + # use default value + url = url.replace( + "{" + variable_name + "}", + server['variables'][variable_name]['default_value']) + + return url From 8c057335e07ec056ff105fa5a07972487b4435e9 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 30 Jan 2019 22:16:53 +0800 Subject: [PATCH 030/180] Add Bearer authentication support to Python client (#1999) * add bearer auth support to python * add bearer auth support to python * update python oas2 petstore samples * update samples * add bearer format * update php symfony samle --- api_doc.mustache | 19 ++++++++++++++-- api_doc_example.mustache | 13 +---------- common_README.mustache | 38 ++++++++++++++++---------------- configuration.mustache | 32 ++++++++++++++++++++++----- python_doc_auth_partial.mustache | 26 ++++++++++++++++++++++ 5 files changed, 90 insertions(+), 38 deletions(-) create mode 100644 python_doc_auth_partial.mustache diff --git a/api_doc.mustache b/api_doc.mustache index c16779a5f9..210ac86d2e 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -18,8 +18,23 @@ Method | HTTP request | Description {{{notes}}}{{/notes}} ### Example -{{#hasAuthMethods}}{{#authMethods}} -{{#isBasic}}* Basic Authentication ({{name}}): {{/isBasic }}{{#isApiKey}}* Api Key Authentication ({{name}}): {{/isApiKey }}{{#isOAuth}}* OAuth Authentication ({{name}}): {{/isOAuth }} + +{{#hasAuthMethods}} +{{#authMethods}} +{{#isBasic}} +{{^isBasicBearer}} +* Basic Authentication ({{name}}): +{{/isBasicBearer}} +{{#isBasicBearer}} +* Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}): +{{/isBasicBearer}} +{{/isBasic}} +{{#isApiKey}} +* Api Key Authentication ({{name}}): +{{/isApiKey }} +{{#isOAuth}} +* OAuth Authentication ({{name}}): +{{/isOAuth }} {{> api_doc_example }} {{/authMethods}} {{/hasAuthMethods}} diff --git a/api_doc_example.mustache b/api_doc_example.mustache index 282bacf69c..c8f0d8b554 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -4,25 +4,14 @@ import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint +{{> python_doc_auth_partial}} {{#hasAuthMethods}} -configuration = {{{packageName}}}.Configuration(){{#isBasic}} -# Configure HTTP basic authorization: {{{name}}} -configuration.username = 'YOUR_USERNAME' -configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} -# Configure API key authorization: {{{name}}} -configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} -# Configure OAuth2 access token for authorization: {{{name}}} -configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}} - # create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} - # create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}() {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} diff --git a/common_README.mustache b/common_README.mustache index 194fb14b59..d8e9f94c58 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -4,19 +4,8 @@ import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}} -configuration = {{{packageName}}}.Configuration(){{#isBasic}} -# Configure HTTP basic authorization: {{{name}}} -configuration.username = 'YOUR_USERNAME' -configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}} -# Configure API key authorization: {{{name}}} -configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}} -# Configure OAuth2 access token for authorization: {{{name}}} -configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}} -{{/hasAuthMethods}} - +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +{{> python_doc_auth_partial}} # create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} @@ -47,17 +36,28 @@ Class | Method | HTTP request | Description ## Documentation For Authorization -{{^authMethods}} All endpoints do not require authorization. -{{/authMethods}}{{#authMethods}}{{#last}} Authentication schemes defined for the API:{{/last}}{{/authMethods}} -{{#authMethods}}## {{{name}}} +{{^authMethods}} + All endpoints do not require authorization. +{{/authMethods}} +{{#authMethods}} +{{#last}} Authentication schemes defined for the API:{{/last}} +## {{{name}}} -{{#isApiKey}}- **Type**: API key +{{#isApiKey}} +- **Type**: API key - **API key parameter name**: {{{keyParamName}}} - **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} {{/isApiKey}} -{{#isBasic}}- **Type**: HTTP basic authentication +{{#isBasic}} +{{^isBasicBearer}} +- **Type**: HTTP basic authentication +{{/isBasicBearer}} +{{#isBasicBearer}} +- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} +{{/isBasicBearer}} {{/isBasic}} -{{#isOAuth}}- **Type**: OAuth +{{#isOAuth}} +- **Type**: OAuth - **Flow**: {{{flow}}} - **Authorization URL**: {{{authorizationUrl}}} - **Scopes**: {{^scopes}}N/A{{/scopes}} diff --git a/configuration.mustache b/configuration.mustache index 562c036e9f..2aaf9851d7 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -51,10 +51,16 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): self.username = "" # Password for HTTP basic authentication self.password = "" -{{#authMethods}}{{#isOAuth}} - # access token for OAuth +{{#hasOAuthMethods}} + # access token for OAuth/Bearer self.access_token = "" -{{/isOAuth}}{{/authMethods}} +{{/hasOAuthMethods}} +{{^hasOAuthMethods}} +{{#hasBearerMethods}} + # access token for OAuth/Bearer + self.access_token = "" +{{/hasBearerMethods}} +{{/hasOAuthMethods}} # Logging Settings self.logger = {} self.logger["package_logger"] = logging.getLogger("{{packageName}}") @@ -218,6 +224,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): }, {{/isApiKey}} {{#isBasic}} + {{^isBasicBearer}} '{{name}}': { 'type': 'basic', @@ -225,7 +232,21 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): 'key': 'Authorization', 'value': self.get_basic_auth_token() }, -{{/isBasic}}{{#isOAuth}} + {{/isBasicBearer}} + {{#isBasicBearer}} + '{{name}}': + { + 'type': 'bearer', + 'in': 'header', + {{#bearerFormat}} + 'format': '{{{.}}}', + {{/bearerFormat}} + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + }, + {{/isBasicBearer}} +{{/isBasic}} +{{#isOAuth}} '{{name}}': { 'type': 'oauth2', @@ -233,7 +254,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): 'key': 'Authorization', 'value': 'Bearer ' + self.access_token }, -{{/isOAuth}}{{/authMethods}} +{{/isOAuth}} +{{/authMethods}} } def to_debug_report(self): diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache new file mode 100644 index 0000000000..899e4b58b9 --- /dev/null +++ b/python_doc_auth_partial.mustache @@ -0,0 +1,26 @@ +{{#hasAuthMethods}} +{{#authMethods}} +configuration = {{{packageName}}}.Configuration() +{{#isBasic}} +{{^isBasicBearer}} +# Configure HTTP basic authorization: {{{name}}} +configuration.username = 'YOUR_USERNAME' +configuration.password = 'YOUR_PASSWORD' +{{/isBasicBearer}} +{{#isBasicBearer}} +# Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}} +configuration.access_token = 'YOUR_BEARER_TOKEN' +{{/isBasicBearer}} +{{/isBasic}} +{{#isApiKey}} +# Configure API key authorization: {{{name}}} +configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed +# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer' +{{/isApiKey}} +{{#isOAuth}} +# Configure OAuth2 access token for authorization: {{{name}}} +configuration.access_token = 'YOUR_ACCESS_TOKEN' +{{/isOAuth}} +{{/authMethods}} +{{/hasAuthMethods}} From 3650fb973c0153e3aca3f96546b63c0577e22bd8 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 8 Feb 2019 11:48:37 +0800 Subject: [PATCH 031/180] [Python] Add "servers" support in path, operation (#2052) * add servers to path, operation * add path/operation server support to python client * update python samples * fix index * fix python code style --- api.mustache | 13 ++++++++++++- api_client.mustache | 16 +++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/api.mustache b/api.mustache index 1109aaebdc..5e8027e839 100644 --- a/api.mustache +++ b/api.mustache @@ -82,6 +82,14 @@ class {{classname}}(object): returns the request thread. """ + {{#servers.0}} + local_var_hosts = [{{#servers}}'{{{url}}}'{{^-last}}, {{/-last}}{{/servers}}] # noqa: E501 + local_var_host = local_var_hosts[0] + if kwargs.get('_host_index'): + if int(kwags.get('_host_index')) < 0 or int(kawgs.get('_host_index')) >= len(local_var_hosts): + raise ValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) + local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] + {{/servers.0}} local_var_params = locals() all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 @@ -91,7 +99,7 @@ class {{classname}}(object): all_params.append('_request_timeout') for key, val in six.iteritems(local_var_params['kwargs']): - if key not in all_params: + if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: raise TypeError( "Got an unexpected keyword argument '%s'" " to method {{operationId}}" % key @@ -212,6 +220,9 @@ class {{classname}}(object): _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 _preload_content=local_var_params.get('_preload_content', True), _request_timeout=local_var_params.get('_request_timeout'), + {{#servers.0}} + _host=local_var_host, + {{/servers.0}} collection_formats=collection_formats) {{/operation}} {{/operations}} diff --git a/api_client.mustache b/api_client.mustache index b0976ba9f2..5325a63cfa 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -107,7 +107,7 @@ class ApiClient(object): query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None): + _preload_content=True, _request_timeout=None, _host=None): config = self.configuration @@ -154,7 +154,11 @@ class ApiClient(object): body = self.sanitize_for_serialization(body) # request url - url = self.configuration.host + resource_path + if _host is None: + url = self.configuration.host + resource_path + else: + # use server/host defined in path or operation instead + url = _host + resource_path # perform request and return response response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( @@ -296,7 +300,7 @@ class ApiClient(object): body=None, post_params=None, files=None, response_type=None, auth_settings=None, async_req=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None): + _preload_content=True, _request_timeout=None, _host=None): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -339,7 +343,7 @@ class ApiClient(object): body, post_params, files, response_type, auth_settings, _return_http_data_only, collection_formats, - _preload_content, _request_timeout) + _preload_content, _request_timeout, _host) else: thread = self.pool.apply_async(self.__call_api, (resource_path, method, path_params, query_params, @@ -348,7 +352,9 @@ class ApiClient(object): response_type, auth_settings, _return_http_data_only, collection_formats, - _preload_content, _request_timeout)) + _preload_content, + _request_timeout, + _host)) return thread def request(self, method, url, query_params=None, headers=None, From 7937a0fff5eb6a09fb0ec53a316d8daa72518dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Berthom=C3=A9?= Date: Sat, 9 Feb 2019 15:08:47 +0100 Subject: [PATCH 032/180] [Python] handle nullable parameters with None added to allowed_values (#2034) * handle nullable parameters with None added to allowed_values * update samples * spec for testing enum with null/nullable --- model.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model.mustache b/model.mustache index c3ab5cb020..16c8dadbf6 100644 --- a/model.mustache +++ b/model.mustache @@ -107,7 +107,7 @@ class {{classname}}(object): {{/isNullable}} {{#isEnum}} {{#isContainer}} - allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 {{#isListContainer}} if not set({{{name}}}).issubset(set(allowed_values)): raise ValueError( @@ -126,7 +126,7 @@ class {{classname}}(object): {{/isMapContainer}} {{/isContainer}} {{^isContainer}} - allowed_values = [{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 if {{{name}}} not in allowed_values: raise ValueError( "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 From a47a1e640c2cc765091d7aa4be15215730ec6b11 Mon Sep 17 00:00:00 2001 From: Tom Ghyselinck Date: Thu, 14 Mar 2019 09:33:35 +0100 Subject: [PATCH 033/180] Python apikey cookie (#2367) * The `ApiClient` will now have support to store and use HTTP Cookies (as APIKey auth). * Use Cookie authentication for user management. * - Updated Python related samples. --- api_client.mustache | 2 ++ configuration.mustache | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index 5325a63cfa..84f6716131 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -523,6 +523,8 @@ class ApiClient(object): if auth_setting: if not auth_setting['value']: continue + elif auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] elif auth_setting['in'] == 'header': headers[auth_setting['key']] = auth_setting['value'] elif auth_setting['in'] == 'query': diff --git a/configuration.mustache b/configuration.mustache index 2aaf9851d7..25eb5dd054 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -218,7 +218,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): '{{name}}': { 'type': 'api_key', - 'in': {{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, 'key': '{{keyParamName}}', 'value': self.get_api_key_with_prefix('{{keyParamName}}') }, From 118afc75d7173deb795ab3e59e4a05f2de48aef1 Mon Sep 17 00:00:00 2001 From: Gaurav Yadav Date: Fri, 22 Mar 2019 05:54:23 +0530 Subject: [PATCH 034/180] Adding retries option to override default value 3 of urllib3 (#2460) * adding retries option to override default value 3 of urllib3 * running petstore for python * adding files for samples in petstore run * running ensure-up-to-date --- configuration.mustache | 2 ++ rest.mustache | 3 +++ 2 files changed, 5 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index 25eb5dd054..b6219f987c 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -100,6 +100,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): self.proxy = None # Safe chars for path_param self.safe_chars_for_path_param = '' + # Adding retries to override urllib3 default value 3 + self.retries = None @property def logger_file(self): diff --git a/rest.mustache b/rest.mustache index 8418ec2a0f..d1580e1c22 100644 --- a/rest.mustache +++ b/rest.mustache @@ -67,6 +67,9 @@ class RESTClientObject(object): if configuration.assert_hostname is not None: addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + if configuration.retries is not None: + addition_pool_args['retries'] = configuration.retries + if maxsize is None: if configuration.connection_pool_maxsize is not None: maxsize = configuration.connection_pool_maxsize From 780e7901240a17e640c7d9cdb2b38a5294fcaebf Mon Sep 17 00:00:00 2001 From: Justin Black Date: Thu, 21 Mar 2019 19:40:32 -0700 Subject: [PATCH 035/180] Adds exceptions module to python clients (#2393) * Adds python client exceptions module and updates samples * Adds python style updates, detects integers in exception paths with six * Updates to ruby samples which circleci needs * Removes petstore-security-tests samples * readme char removal (triggers ci tests) * Readme fix, triggers CI tests * Updates python client sample --- __init__package.mustache | 7 ++- api.mustache | 24 +++++---- api_client.mustache | 5 +- asyncio/rest.mustache | 31 ++--------- exceptions.mustache | 112 +++++++++++++++++++++++++++++++++++++++ rest.mustache | 36 ++----------- tornado/rest.mustache | 32 ++--------- 7 files changed, 144 insertions(+), 103 deletions(-) create mode 100644 exceptions.mustache diff --git a/__init__package.mustache b/__init__package.mustache index a21c6dbac9..72376acdc3 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -14,6 +14,11 @@ __version__ = "{{packageVersion}}" # import ApiClient from {{packageName}}.api_client import ApiClient from {{packageName}}.configuration import Configuration +from {{packageName}}.exceptions import OpenApiException +from {{packageName}}.exceptions import ApiTypeError +from {{packageName}}.exceptions import ApiValueError +from {{packageName}}.exceptions import ApiKeyError +from {{packageName}}.exceptions import ApiException # import models into sdk package {{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} -{{/model}}{{/models}} \ No newline at end of file +{{/model}}{{/models}} diff --git a/api.mustache b/api.mustache index 5e8027e839..e1f9f53dca 100644 --- a/api.mustache +++ b/api.mustache @@ -10,6 +10,10 @@ import re # noqa: F401 import six from {{packageName}}.api_client import ApiClient +from {{packageName}}.exceptions import ( + ApiTypeError, + ApiValueError +) {{#operations}} @@ -87,7 +91,7 @@ class {{classname}}(object): local_var_host = local_var_hosts[0] if kwargs.get('_host_index'): if int(kwags.get('_host_index')) < 0 or int(kawgs.get('_host_index')) >= len(local_var_hosts): - raise ValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) + raise ApiValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] {{/servers.0}} local_var_params = locals() @@ -100,7 +104,7 @@ class {{classname}}(object): for key, val in six.iteritems(local_var_params['kwargs']): if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: - raise TypeError( + raise ApiTypeError( "Got an unexpected keyword argument '%s'" " to method {{operationId}}" % key ) @@ -112,7 +116,7 @@ class {{classname}}(object): # verify the required parameter '{{paramName}}' is set if ('{{paramName}}' not in local_var_params or local_var_params['{{paramName}}'] is None): - raise ValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 + raise ApiValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 {{/required}} {{/isNullable}} {{/allParams}} @@ -122,34 +126,34 @@ class {{classname}}(object): {{#maxLength}} if ('{{paramName}}' in local_var_params and len(local_var_params['{{paramName}}']) > {{maxLength}}): - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 {{/maxLength}} {{#minLength}} if ('{{paramName}}' in local_var_params and len(local_var_params['{{paramName}}']) < {{minLength}}): - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 {{/minLength}} {{#maximum}} if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 {{/maximum}} {{#minimum}} if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} if '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} if ('{{paramName}}' in local_var_params and len(local_var_params['{{paramName}}']) > {{maxItems}}): - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 {{/maxItems}} {{#minItems}} if ('{{paramName}}' in local_var_params and len(local_var_params['{{paramName}}']) < {{minItems}}): - raise ValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 {{/minItems}} {{/hasValidation}} {{#-last}} diff --git a/api_client.mustache b/api_client.mustache index 84f6716131..34021481bf 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -20,6 +20,7 @@ import tornado.gen from {{packageName}}.configuration import Configuration import {{modelPackage}} from {{packageName}} import rest +from {{packageName}}.exceptions import ApiValueError class ApiClient(object): @@ -413,7 +414,7 @@ class ApiClient(object): _request_timeout=_request_timeout, body=body) else: - raise ValueError( + raise ApiValueError( "http method must be `GET`, `HEAD`, `OPTIONS`," " `POST`, `PATCH`, `PUT` or `DELETE`." ) @@ -530,7 +531,7 @@ class ApiClient(object): elif auth_setting['in'] == 'query': querys.append((auth_setting['key'], auth_setting['value'])) else: - raise ValueError( + raise ApiValueError( 'Authentication token must be in `query` or `header`' ) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 727dfae423..36b061f8f4 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -14,6 +14,8 @@ import asyncio # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode +from {{packageName}}.exceptions import ApiException, ApiValueError + logger = logging.getLogger(__name__) @@ -100,7 +102,7 @@ class RESTClientObject(object): 'PATCH', 'OPTIONS'] if post_params and body: - raise ValueError( + raise ApiValueError( "body parameter cannot be used with post_params parameter." ) @@ -238,30 +240,3 @@ class RESTClientObject(object): _preload_content=_preload_content, _request_timeout=_request_timeout, body=body)) - - -class ApiException(Exception): - - def __init__(self, status=None, reason=None, http_resp=None): - if http_resp: - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - else: - self.status = status - self.reason = reason - self.body = None - self.headers = None - - def __str__(self): - """Custom error messages for exception""" - error_message = "({0})\nReason: {1}\n".format(self.status, self.reason) - if self.headers: - error_message += "HTTP response headers: {0}\n".format( - self.headers) - - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) - - return error_message diff --git a/exceptions.mustache b/exceptions.mustache new file mode 100644 index 0000000000..dd012f34a0 --- /dev/null +++ b/exceptions.mustache @@ -0,0 +1,112 @@ +# coding: utf-8 + +{{>partial_header}} + +import six + + +class OpenApiException(Exception): + """The base exception class for all OpenAPIExceptions""" + + +class ApiTypeError(OpenApiException, TypeError): + def __init__(self, msg, path_to_item=None, valid_classes=None, + key_type=None): + """ Raises an exception for TypeErrors + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list): a list of keys an indices to get to the + current_item + None if unset + valid_classes (tuple): the primitive classes that current item + should be an instance of + None if unset + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + None if unset + """ + self.path_to_item = path_to_item + self.valid_classes = valid_classes + self.key_type = key_type + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiTypeError, self).__init__(full_msg) + + +class ApiValueError(OpenApiException, ValueError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list) the path to the exception in the + received_data dict. None if unset + """ + + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiValueError, self).__init__(full_msg) + + +class ApiKeyError(OpenApiException, KeyError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiKeyError, self).__init__(full_msg) + + +class ApiException(OpenApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message + + +def render_path(path_to_item): + """Returns a string representation of a path""" + result = "" + for pth in path_to_item: + if isinstance(pth, six.integer_types): + result += "[{0}]".format(pth) + else: + result += "['{0}']".format(pth) + return result diff --git a/rest.mustache b/rest.mustache index d1580e1c22..0ce998c5f9 100644 --- a/rest.mustache +++ b/rest.mustache @@ -14,11 +14,9 @@ import certifi # python 2 and python 3 compatibility library import six from six.moves.urllib.parse import urlencode +import urllib3 -try: - import urllib3 -except ImportError: - raise ImportError('OpenAPI Python client requires urllib3.') +from {{packageName}}.exceptions import ApiException, ApiValueError logger = logging.getLogger(__name__) @@ -125,7 +123,7 @@ class RESTClientObject(object): 'PATCH', 'OPTIONS'] if post_params and body: - raise ValueError( + raise ApiValueError( "body parameter cannot be used with post_params parameter." ) @@ -287,31 +285,3 @@ class RESTClientObject(object): _preload_content=_preload_content, _request_timeout=_request_timeout, body=body) - - -class ApiException(Exception): - - def __init__(self, status=None, reason=None, http_resp=None): - if http_resp: - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - else: - self.status = status - self.reason = reason - self.body = None - self.headers = None - - def __str__(self): - """Custom error messages for exception""" - error_message = "({0})\n"\ - "Reason: {1}\n".format(self.status, self.reason) - if self.headers: - error_message += "HTTP response headers: {0}\n".format( - self.headers) - - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) - - return error_message diff --git a/tornado/rest.mustache b/tornado/rest.mustache index bc74fbc295..e7a760f370 100644 --- a/tornado/rest.mustache +++ b/tornado/rest.mustache @@ -15,6 +15,8 @@ import tornado.gen from tornado import httpclient from urllib3.filepost import encode_multipart_formdata +from {{packageName}}.exceptions import ApiException, ApiValueError + logger = logging.getLogger(__name__) @@ -87,7 +89,7 @@ class RESTClientObject(object): 'PATCH', 'OPTIONS'] if post_params and body: - raise ValueError( + raise ApiValueError( "body parameter cannot be used with post_params parameter." ) @@ -225,31 +227,3 @@ class RESTClientObject(object): _request_timeout=_request_timeout, body=body) raise tornado.gen.Return(result) - - -class ApiException(Exception): - - def __init__(self, status=None, reason=None, http_resp=None): - if http_resp: - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - else: - self.status = status - self.reason = reason - self.body = None - self.headers = None - - def __str__(self): - """Custom error messages for exception""" - error_message = "({0})\nReason: {1}\n".format( - self.status, self.reason) - if self.headers: - error_message += "HTTP response headers: {0}\n".format( - self.headers) - - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) - - return error_message From 35a841e7b89d554cc1e736af61c9fd0beff7f191 Mon Sep 17 00:00:00 2001 From: Gaurav Yadav Date: Fri, 22 Mar 2019 08:52:10 +0530 Subject: [PATCH 036/180] Added proxy headers option for urllib3 (#2467) * adding headers option to pass in rest client * running ensure uptodate --- configuration.mustache | 2 ++ rest.mustache | 1 + 2 files changed, 3 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index b6219f987c..a1a7e9babf 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -98,6 +98,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): # Proxy URL self.proxy = None + # Proxy headers + self.proxy_headers = None # Safe chars for path_param self.safe_chars_for_path_param = '' # Adding retries to override urllib3 default value 3 diff --git a/rest.mustache b/rest.mustache index 0ce998c5f9..98f2c502a9 100644 --- a/rest.mustache +++ b/rest.mustache @@ -84,6 +84,7 @@ class RESTClientObject(object): cert_file=configuration.cert_file, key_file=configuration.key_file, proxy_url=configuration.proxy, + proxy_headers=configuration.proxy_headers, **addition_pool_args ) else: From 2841f1207a148ed2511954f8582a10080aa1aab6 Mon Sep 17 00:00:00 2001 From: Sebastien Arod Date: Fri, 26 Apr 2019 19:45:34 +0200 Subject: [PATCH 037/180] [Bug][Python]Support body as bytes when Content-Type is unknown (#2626) * Support body as bytes when Content-Type is unknownfix #2623 * Revert unwanted import changes * update samples/openapi3 --- rest.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest.mustache b/rest.mustache index 98f2c502a9..772efe91b3 100644 --- a/rest.mustache +++ b/rest.mustache @@ -181,7 +181,7 @@ class RESTClientObject(object): # Pass a `string` parameter directly in the body to support # other content types than Json when `body` argument is # provided in serialized form - elif isinstance(body, str): + elif isinstance(body, str) or isinstance(body, bytes): request_body = body r = self.pool_manager.request( method, url, From 70479dcb83a608ac11a27bceb5967857a9f3671e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthieu=20Berthom=C3=A9?= Date: Tue, 7 May 2019 15:27:01 +0200 Subject: [PATCH 038/180] python: api_client: add the multipart files after sanitization (#2122) * python: api_client: add the multipart files after sanitization * simplify prepare_post_parameters * fix case of both post params and files set * update samples * update samples --- api_client.mustache | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 34021481bf..768b8d973f 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -142,10 +142,11 @@ class ApiClient(object): # post parameters if post_params or files: - post_params = self.prepare_post_parameters(post_params, files) + post_params = post_params if post_params else [] post_params = self.sanitize_for_serialization(post_params) post_params = self.parameters_to_tuples(post_params, collection_formats) + post_params.extend(self.files_parameters(files)) # auth setting self.update_params_for_auth(header_params, query_params, auth_settings) @@ -449,18 +450,14 @@ class ApiClient(object): new_params.append((k, v)) return new_params - def prepare_post_parameters(self, post_params=None, files=None): + def files_parameters(self, files=None): """Builds form parameters. - :param post_params: Normal form parameters. :param files: File parameters. :return: Form parameters with files. """ params = [] - if post_params: - params = post_params - if files: for k, v in six.iteritems(files): if not v: From 6cf06582d33ab5c3de25a2d78cf3e82ca4dba5a9 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Mon, 13 May 2019 15:59:59 +0800 Subject: [PATCH 039/180] Minor wording change (#2875) * better wording for version of openapi doc * update petstore samples --- partial_header.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partial_header.mustache b/partial_header.mustache index b83479cdbb..c52fbceb13 100644 --- a/partial_header.mustache +++ b/partial_header.mustache @@ -8,7 +8,7 @@ {{/appDescription}} {{#version}} - OpenAPI spec version: {{{version}}} + The version of the OpenAPI document: {{{version}}} {{/version}} {{#infoEmail}} Contact: {{{infoEmail}}} From 3636d86966089522db75bf6eaf20d976fdf95837 Mon Sep 17 00:00:00 2001 From: Shenghan Gao Date: Fri, 24 May 2019 09:10:11 -0700 Subject: [PATCH 040/180] [Python] Remove unnecessary if else. (#2985) * Remove Unnecessary `if else` * update samples --- api.mustache | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/api.mustache b/api.mustache index e1f9f53dca..4e0612d87d 100644 --- a/api.mustache +++ b/api.mustache @@ -55,11 +55,7 @@ class {{classname}}(object): returns the request thread. """ kwargs['_return_http_data_only'] = True - if kwargs.get('async_req'): - return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 - else: - (data) = self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 - return data + return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 def {{operationId}}_with_http_info(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 From c4e8a40ee08b99bd9825717928312bd1f3c029a5 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Wed, 29 May 2019 17:08:42 +0530 Subject: [PATCH 041/180] [Python] ModuleNotFoundError when packagename contains dots (#2992) * feat(python): Support package names with dots * feat(python): Fixing tests * feat(python): Adding comment * fix(python): Fixing indentation * fix(python): Fixing indentation --- __init__test.mustache => __init__.mustache | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename __init__test.mustache => __init__.mustache (100%) diff --git a/__init__test.mustache b/__init__.mustache similarity index 100% rename from __init__test.mustache rename to __init__.mustache From d440913526ad980b58eb84579af1094cac64dfd8 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Wed, 29 May 2019 22:20:26 +0530 Subject: [PATCH 042/180] [python] Adding constructor parameters to Configuration and improving documentation (#3002) * feat(python): Updated configuration's constructor and documentation * feat(python): Updated documentation * feat(python): Updated pet project * feat(python): Updated pet project * feat(python): Fixing host * feat(python): Updating pet project * feat(python): Fixing indentation --- api.mustache | 22 ++++++-- api_doc.mustache | 9 ++++ configuration.mustache | 112 ++++++++++++++++++++++++++--------------- 3 files changed, 100 insertions(+), 43 deletions(-) diff --git a/api.mustache b/api.mustache index 4e0612d87d..590299dc5f 100644 --- a/api.mustache +++ b/api.mustache @@ -46,10 +46,17 @@ class {{classname}}(object): {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async_req bool + :param async_req bool: execute request asynchronously {{#allParams}} :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} {{/allParams}} + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} If the method is called asynchronously, returns the request thread. @@ -73,11 +80,20 @@ class {{classname}}(object): {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async_req bool + :param async_req bool: execute request asynchronously {{#allParams}} :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/optional}} {{/allParams}} - :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + :param _return_http_data_only: response data without head status code + and headers + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: {{#returnType}}tuple({{returnType}}, status_code(int), headers(HTTPHeaderDict)){{/returnType}}{{^returnType}}None{{/returnType}} If the method is called asynchronously, returns the request thread. """ diff --git a/api_doc.mustache b/api_doc.mustache index 210ac86d2e..1df5389c5c 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -61,6 +61,15 @@ Name | Type | Description | Notes - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) {{/operation}} diff --git a/configuration.mustache b/configuration.mustache index a1a7e9babf..b6c134aa1c 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -19,9 +19,9 @@ class TypeWithDefault(type): super(TypeWithDefault, cls).__init__(name, bases, dct) cls._default = None - def __call__(cls): + def __call__(cls, **kwargs): if cls._default is None: - cls._default = type.__call__(cls) + cls._default = type.__call__(cls, **kwargs) return copy.copy(cls._default) def set_default(cls, default): @@ -33,77 +33,109 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): Ref: https://openapi-generator.tech Do not edit the class manually. + + :param host: Base url + :param api_key: Dict to store API key(s) + :param api_key_prefix: Dict to store API prefix (e.g. Bearer) + :param username: Username for HTTP basic authentication + :param password: Password for HTTP basic authentication """ - def __init__(self): - """Constructor""" - # Default Base url - self.host = "{{{basePath}}}" - # Temp file folder for downloading files + def __init__(self, host="{{{basePath}}}", + api_key={}, api_key_prefix={}, + username="", password=""): + """Constructor + """ + self.host = host + """Default Base url + """ self.temp_folder_path = None - + """Temp file folder for downloading files + """ # Authentication Settings - # dict to store API key(s) - self.api_key = {} - # dict to store API prefix (e.g. Bearer) - self.api_key_prefix = {} - # Username for HTTP basic authentication - self.username = "" - # Password for HTTP basic authentication - self.password = "" + self.api_key = api_key + """dict to store API key(s) + """ + self.api_key_prefix = api_key_prefix + """dict to store API prefix (e.g. Bearer) + """ + self.username = username + """Username for HTTP basic authentication + """ + self.password = password + """Password for HTTP basic authentication + """ {{#hasOAuthMethods}} - # access token for OAuth/Bearer self.access_token = "" + """access token for OAuth/Bearer + """ {{/hasOAuthMethods}} {{^hasOAuthMethods}} {{#hasBearerMethods}} - # access token for OAuth/Bearer self.access_token = "" + """access token for OAuth/Bearer + """ {{/hasBearerMethods}} {{/hasOAuthMethods}} - # Logging Settings self.logger = {} + """Logging Settings + """ self.logger["package_logger"] = logging.getLogger("{{packageName}}") self.logger["urllib3_logger"] = logging.getLogger("urllib3") - # Log format self.logger_format = '%(asctime)s %(levelname)s %(message)s' - # Log stream handler + """Log format + """ self.logger_stream_handler = None - # Log file handler + """Log stream handler + """ self.logger_file_handler = None - # Debug file location + """Log file handler + """ self.logger_file = None - # Debug switch + """Debug file location + """ self.debug = False + """Debug switch + """ - # SSL/TLS verification - # Set this to false to skip verifying SSL certificate when calling API - # from https server. self.verify_ssl = True - # Set this to customize the certificate file to verify the peer. + """SSL/TLS verification + Set this to false to skip verifying SSL certificate when calling API + from https server. + """ self.ssl_ca_cert = None - # client certificate file + """Set this to customize the certificate file to verify the peer. + """ self.cert_file = None - # client key file + """client certificate file + """ self.key_file = None - # Set this to True/False to enable/disable SSL hostname verification. + """client key file + """ self.assert_hostname = None + """Set this to True/False to enable/disable SSL hostname verification. + """ - # urllib3 connection pool's maximum number of connections saved - # per pool. urllib3 uses 1 connection as default value, but this is - # not the best value when you are making a lot of possibly parallel - # requests to the same host, which is often the case here. - # cpu_count * 5 is used as default value to increase performance. self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + """urllib3 connection pool's maximum number of connections saved + per pool. urllib3 uses 1 connection as default value, but this is + not the best value when you are making a lot of possibly parallel + requests to the same host, which is often the case here. + cpu_count * 5 is used as default value to increase performance. + """ - # Proxy URL self.proxy = None - # Proxy headers + """Proxy URL + """ self.proxy_headers = None - # Safe chars for path_param + """Proxy headers + """ self.safe_chars_for_path_param = '' - # Adding retries to override urllib3 default value 3 + """Safe chars for path_param + """ self.retries = None + """Adding retries to override urllib3 default value 3 + """ @property def logger_file(self): From 08aa948ef02e0768645427aac6ab0be8223701c2 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Tue, 25 Jun 2019 08:13:43 +0200 Subject: [PATCH 043/180] feat: configurable limit of simultaneous connections (python/asyncio) (#3200) * feat: configurable limit of simultaneous connections (python/asyncio) * fix: remove unused import (python/asyncio) --- asyncio/rest.mustache | 5 ++++- configuration.mustache | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 36b061f8f4..4585f1c6ad 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -38,8 +38,11 @@ class RESTResponse(io.IOBase): class RESTClientObject(object): - def __init__(self, configuration, pools_size=4, maxsize=4): + def __init__(self, configuration, pools_size=4, maxsize=None): + # maxsize is number of requests to host that are allowed in parallel + if maxsize is None: + maxsize = configuration.connection_pool_maxsize # ca_certs if configuration.ssl_ca_cert: diff --git a/configuration.mustache b/configuration.mustache index b6c134aa1c..6d0d5c62e1 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -6,7 +6,9 @@ from __future__ import absolute_import import copy import logging +{{^asyncio}} import multiprocessing +{{/asyncio}} import sys import urllib3 @@ -116,6 +118,13 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): """Set this to True/False to enable/disable SSL hostname verification. """ + {{#asyncio}} + self.connection_pool_maxsize = 100 + """This value is passed to the aiohttp to limit simultaneous connections. + Default values is 100, None means no-limit. + """ + {{/asyncio}} + {{^asyncio}} self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 """urllib3 connection pool's maximum number of connections saved per pool. urllib3 uses 1 connection as default value, but this is @@ -123,6 +132,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): requests to the same host, which is often the case here. cpu_count * 5 is used as default value to increase performance. """ + {{/asyncio}} self.proxy = None """Proxy URL From 8f5b42adcd7429391da4c0a3bc454d365b6889df Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Fri, 28 Jun 2019 15:23:25 +0530 Subject: [PATCH 044/180] [python] : Make example code snippet compilable (#3148) * feat(python): Making example compilable * feat(python): Updating pet project * feat(python): Updating comments * feat(documentation): Fixing comments style * feat(documentation): Updating documentation * feat(documentation): Fixing comments style --- api_doc_example.mustache | 6 ++++-- common_README.mustache | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api_doc_example.mustache b/api_doc_example.mustache index c8f0d8b554..f2d6117a7c 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -6,13 +6,15 @@ from {{{packageName}}}.rest import ApiException from pprint import pprint {{> python_doc_auth_partial}} {{#hasAuthMethods}} -# create an instance of the API class +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} -# create an instance of the API class +# Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}() {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} diff --git a/common_README.mustache b/common_README.mustache index d8e9f94c58..7238703c4b 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -6,7 +6,9 @@ from {{{packageName}}}.rest import ApiException from pprint import pprint {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} {{> python_doc_auth_partial}} -# create an instance of the API class +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} From 33aee95af93122bf14c825dcf0ce3c44c541be52 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Wed, 31 Jul 2019 06:18:30 -0700 Subject: [PATCH 045/180] [python-experimental] automatically use values for enums of length1 (#3118) * Update python client java generator * Updates python generator mustache files * Python sample regenerated * Switches from getfullargspec to getargspec for python2 compatibility * Uses getattr to get model class init method to correctly see its arguments, linting fixes to pass python tests * Updates comment in python centerator to restart CI tests * Adds bin/windows/python-experimental-petstore.bat * CHanges spec update to apply to the python-experimental spec * Moves new python templates to python-experimental * Moves generator python java code to python-experimental * Reverts python generator mustache files * Regenerates python, v3 python, python-experimental samples * Test moved to python-experimental, unused python files removed --- python-experimental/api.mustache | 294 ++++++++ python-experimental/api_client.mustache | 665 +++++++++++++++++++ python-experimental/api_doc.mustache | 78 +++ python-experimental/api_doc_example.mustache | 58 ++ python-experimental/model.mustache | 241 +++++++ python-experimental/model_doc.mustache | 13 + 6 files changed, 1349 insertions(+) create mode 100644 python-experimental/api.mustache create mode 100644 python-experimental/api_client.mustache create mode 100644 python-experimental/api_doc.mustache create mode 100644 python-experimental/api_doc_example.mustache create mode 100644 python-experimental/model.mustache create mode 100644 python-experimental/model_doc.mustache diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache new file mode 100644 index 0000000000..edf76be03b --- /dev/null +++ b/python-experimental/api.mustache @@ -0,0 +1,294 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import re # noqa: F401 + +# python 2 and python 3 compatibility library +import six + +from {{packageName}}.api_client import ApiClient +from {{packageName}}.exceptions import ( # noqa: F401 + ApiTypeError, + ApiValueError +) + + +{{#operations}} +class {{classname}}(object): + """NOTE: This class is auto generated by OpenAPI Generator + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """ + + def __init__(self, api_client=None): + if api_client is None: + api_client = ApiClient() + self.api_client = api_client +{{#operation}} + + def {{operationId}}(self{{#requiredParams}}{{^defaultValue}}, {{paramName}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}, {{paramName}}={{{defaultValue}}}{{/defaultValue}}{{/requiredParams}}, **kwargs): # noqa: E501 + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) + >>> result = thread.get() + +{{#requiredParams}} +{{^hasMore}} + Args: +{{/hasMore}} +{{/requiredParams}} +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}}{{/requiredParams}} + + Keyword Args:{{#optionalParams}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} + async_req (bool): execute request asynchronously + param _preload_content (bool): if False, the urllib3.HTTPResponse + object will be returned without reading/decoding response data. + Default is True. + param _request_timeout (float/tuple): timeout setting for this + request. If one number provided, it will be total request + timeout. It can also be a pair (tuple) of (connection, read) + timeouts. + + Returns: + {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}: + """ + kwargs['_return_http_data_only'] = True + if kwargs.get('async_req'): + return self.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{paramName}}, {{/defaultValue}}{{/requiredParams}}**kwargs) # noqa: E501 + else: + (data) = self.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{paramName}}, {{/defaultValue}}{{/requiredParams}}**kwargs) # noqa: E501 + return data + + def {{operationId}}_with_http_info(self{{#requiredParams}}{{^defaultValue}}, {{paramName}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}, {{paramName}}=None{{/defaultValue}}{{/requiredParams}}, **kwargs): # noqa: E501 + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + +{{#notes}} + {{{notes}}} # noqa: E501 +{{/notes}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True + >>> thread = api.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}async_req=True) + >>> result = thread.get() + +{{#requiredParams}} +{{^hasMore}} + Args: +{{/hasMore}} +{{/requiredParams}} +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}}{{/requiredParams}} + + Keyword Args:{{#optionalParams}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} + async_req (bool): execute request asynchronously + param _preload_content (bool): if False, the urllib3.HTTPResponse + object will be returned without reading/decoding response data. + Default is True. + param _request_timeout (float/tuple): timeout setting for this + request. If one number provided, it will be total request + timeout. It can also be a pair (tuple) of (connection, read) + timeouts. + + Returns: + {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}: + """ + + {{#servers.0}} + local_var_hosts = [{{#servers}} + '{{{url}}}'{{^-last}},{{/-last}}{{/servers}} + ] + local_var_host = local_var_hosts[0] + if kwargs.get('_host_index'): + if (int(kwargs.get('_host_index')) < 0 or + int(kwargs.get('_host_index')) >= len(local_var_hosts)): + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" % + len(local_var_host) + ) + local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] + {{/servers.0}} + local_var_params = locals() + + all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') + + for key, val in six.iteritems(local_var_params['kwargs']): + if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: + raise ApiTypeError( + "Got an unexpected keyword argument '%s'" + " to method {{operationId}}" % key + ) + local_var_params[key] = val + del local_var_params['kwargs'] +{{#allParams}} +{{^isNullable}} +{{#required}} + # verify the required parameter '{{paramName}}' is set + if ('{{paramName}}' not in local_var_params or + local_var_params['{{paramName}}'] is None): + raise ApiValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 +{{/required}} +{{/isNullable}} +{{#-last}} +{{/-last}} +{{/allParams}} +{{#allParams}} +{{#isEnum}} +{{#isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 +{{#isListContainer}} + if ('{{{paramName}}}' in local_var_params and + not set(local_var_params['{{{paramName}}}']).issubset(set(allowed_values))): # noqa: E501 + raise ValueError( + "Invalid values for `{{{paramName}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set(local_var_params['{{{paramName}}}']) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isListContainer}} +{{#isMapContainer}} + if ('{{{paramName}}}' in local_var_params and + not set(local_var_params['{{{paramName}}}'].keys()).issubset(set(allowed_values))): + raise ValueError( + "Invalid keys in `{{{paramName}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set(local_var_params['{{{paramName}}}'].keys()) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isMapContainer}} +{{/isContainer}} +{{^isContainer}} + allowed_values = [{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + if ('{{{paramName}}}' in local_var_params and + local_var_params['{{{paramName}}}'] not in allowed_values): + raise ValueError( + "Invalid value for `{{{paramName}}}` ({0}), must be one of {1}" # noqa: E501 + .format(local_var_params['{{{paramName}}}'], allowed_values) + ) +{{/isContainer}} +{{/isEnum}} +{{/allParams}} +{{#allParams}} +{{#hasValidation}} + {{#maxLength}} + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) > {{maxLength}}): + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 + {{/maxLength}} + {{#minLength}} + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) < {{minLength}}): + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 + {{/minLength}} + {{#maximum}} + if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 + {{/maximum}} + {{#minimum}} + if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 + {{/minimum}} + {{#pattern}} + if '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 + {{/pattern}} + {{#maxItems}} + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) > {{maxItems}}): + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 + {{/maxItems}} + {{#minItems}} + if ('{{paramName}}' in local_var_params and + len(local_var_params['{{paramName}}']) < {{minItems}}): + raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 + {{/minItems}} +{{/hasValidation}} +{{/allParams}} + + collection_formats = {} + + path_params = {} +{{#pathParams}} + if '{{paramName}}' in local_var_params: + path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/pathParams}} + + query_params = [] +{{#queryParams}} + if '{{paramName}}' in local_var_params: + query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/queryParams}} + + header_params = {} +{{#headerParams}} + if '{{paramName}}' in local_var_params: + header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/headerParams}} + + form_params = [] + local_var_files = {} +{{#formParams}} + if '{{paramName}}' in local_var_params: + {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 +{{/formParams}} + + body_params = None +{{#bodyParam}} + if '{{paramName}}' in local_var_params: + body_params = local_var_params['{{paramName}}'] +{{/bodyParam}} + {{#hasProduces}} + # HTTP header `Accept` + header_params['Accept'] = self.api_client.select_header_accept( + [{{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) # noqa: E501 + + {{/hasProduces}} + {{#hasConsumes}} + # HTTP header `Content-Type` + header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 + [{{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) # noqa: E501 + + {{/hasConsumes}} + # Authentication setting + auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + + return self.api_client.call_api( + '{{{path}}}', '{{httpMethod}}', + path_params, + query_params, + header_params, + body=body_params, + post_params=form_params, + files=local_var_files, + response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 + auth_settings=auth_settings, + async_req=local_var_params.get('async_req'), + _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 + _preload_content=local_var_params.get('_preload_content', True), + _request_timeout=local_var_params.get('_request_timeout'), + {{#servers.0}} + _host=local_var_host, + {{/servers.0}} + collection_formats=collection_formats) +{{/operation}} +{{/operations}} diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache new file mode 100644 index 0000000000..e955eb0570 --- /dev/null +++ b/python-experimental/api_client.mustache @@ -0,0 +1,665 @@ +# coding: utf-8 +{{>partial_header}} +from __future__ import absolute_import + +import datetime +import inspect +import json +import mimetypes +from multiprocessing.pool import ThreadPool +import os +import re +import tempfile + +# python 2 and python 3 compatibility library +import six +from six.moves.urllib.parse import quote +{{#tornado}} +import tornado.gen +{{/tornado}} + +from {{packageName}}.configuration import Configuration +import {{modelPackage}} +from {{packageName}} import rest +from {{packageName}}.exceptions import ApiValueError + + +class ApiClient(object): + """Generic API client for OpenAPI client library builds. + + OpenAPI generic API client. This client handles the client- + server communication, and is invariant across implementations. Specifics of + the methods and models for each application are generated from the OpenAPI + templates. + + NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + Do not edit the class manually. + + :param configuration: .Configuration object for this client + :param header_name: a header to pass when making calls to the API. + :param header_value: a header value to pass when making calls to + the API. + :param cookie: a cookie to include in the header when making calls + to the API + :param pool_threads: The number of threads to use for async requests + to the API. More threads means more concurrent API requests. + """ + + PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types + NATIVE_TYPES_MAPPING = { + 'int': int, + 'long': int if six.PY3 else long, # noqa: F821 + 'float': float, + 'str': str, + 'bool': bool, + 'date': datetime.date, + 'datetime': datetime.datetime, + 'object': object, + } + _pool = None + + def __init__(self, configuration=None, header_name=None, header_value=None, + cookie=None, pool_threads=1): + if configuration is None: + configuration = Configuration() + self.configuration = configuration + self.pool_threads = pool_threads + + self.rest_client = rest.RESTClientObject(configuration) + self.default_headers = {} + if header_name is not None: + self.default_headers[header_name] = header_value + self.cookie = cookie + # Set default User-Agent. + self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' + + def __del__(self): + if self._pool: + self._pool.close() + self._pool.join() + self._pool = None + + @property + def pool(self): + """Create thread pool on first request + avoids instantiating unused threadpool for blocking clients. + """ + if self._pool is None: + self._pool = ThreadPool(self.pool_threads) + return self._pool + + @property + def user_agent(self): + """User agent for this API client""" + return self.default_headers['User-Agent'] + + @user_agent.setter + def user_agent(self, value): + self.default_headers['User-Agent'] = value + + def set_default_header(self, header_name, header_value): + self.default_headers[header_name] = header_value + + {{#tornado}} + @tornado.gen.coroutine + {{/tornado}} + {{#asyncio}}async {{/asyncio}}def __call_api( + self, resource_path, method, path_params=None, + query_params=None, header_params=None, body=None, post_params=None, + files=None, response_type=None, auth_settings=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None, _host=None): + + config = self.configuration + + # header parameters + header_params = header_params or {} + header_params.update(self.default_headers) + if self.cookie: + header_params['Cookie'] = self.cookie + if header_params: + header_params = self.sanitize_for_serialization(header_params) + header_params = dict(self.parameters_to_tuples(header_params, + collection_formats)) + + # path parameters + if path_params: + path_params = self.sanitize_for_serialization(path_params) + path_params = self.parameters_to_tuples(path_params, + collection_formats) + for k, v in path_params: + # specified safe chars, encode everything + resource_path = resource_path.replace( + '{%s}' % k, + quote(str(v), safe=config.safe_chars_for_path_param) + ) + + # query parameters + if query_params: + query_params = self.sanitize_for_serialization(query_params) + query_params = self.parameters_to_tuples(query_params, + collection_formats) + + # post parameters + if post_params or files: + post_params = post_params if post_params else [] + post_params = self.sanitize_for_serialization(post_params) + post_params = self.parameters_to_tuples(post_params, + collection_formats) + post_params.extend(self.files_parameters(files)) + + # auth setting + self.update_params_for_auth(header_params, query_params, auth_settings) + + # body + if body: + body = self.sanitize_for_serialization(body) + + # request url + if _host is None: + url = self.configuration.host + resource_path + else: + # use server/host defined in path or operation instead + url = _host + resource_path + + # perform request and return response + response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + + self.last_response = response_data + + return_data = response_data + if _preload_content: + # deserialize response data + if response_type: + return_data = self.deserialize(response_data, response_type) + else: + return_data = None + +{{^tornado}} + if _return_http_data_only: + return (return_data) + else: + return (return_data, response_data.status, + response_data.getheaders()) +{{/tornado}} +{{#tornado}} + if _return_http_data_only: + raise tornado.gen.Return(return_data) + else: + raise tornado.gen.Return((return_data, response_data.status, + response_data.getheaders())) +{{/tornado}} + + def sanitize_for_serialization(self, obj): + """Builds a JSON POST object. + + If obj is None, return None. + If obj is str, int, long, float, bool, return directly. + If obj is datetime.datetime, datetime.date + convert to string in iso8601 format. + If obj is list, sanitize each element in the list. + If obj is dict, return the dict. + If obj is OpenAPI model, return the properties dict. + + :param obj: The data to serialize. + :return: The serialized form of data. + """ + if obj is None: + return None + elif isinstance(obj, self.PRIMITIVE_TYPES): + return obj + elif isinstance(obj, list): + return [self.sanitize_for_serialization(sub_obj) + for sub_obj in obj] + elif isinstance(obj, tuple): + return tuple(self.sanitize_for_serialization(sub_obj) + for sub_obj in obj) + elif isinstance(obj, (datetime.datetime, datetime.date)): + return obj.isoformat() + + if isinstance(obj, dict): + obj_dict = obj + else: + # Convert model obj to dict except + # attributes `openapi_types`, `attribute_map` + # and attributes which value is not None. + # Convert attribute name to json key in + # model definition for request. + obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) + for attr, _ in six.iteritems(obj.openapi_types) + if getattr(obj, attr) is not None} + + return {key: self.sanitize_for_serialization(val) + for key, val in six.iteritems(obj_dict)} + + def deserialize(self, response, response_type): + """Deserializes response into an object. + + :param response: RESTResponse object to be deserialized. + :param response_type: class literal for + deserialized object, or string of class name. + + :return: deserialized object. + """ + # handle file downloading + # save response body into a tmp file and return the instance + if response_type == "file": + return self.__deserialize_file(response) + + # fetch data from response object + try: + data = json.loads(response.data) + except ValueError: + data = response.data + + return self.__deserialize(data, response_type) + + def __deserialize(self, data, klass): + """Deserializes dict, list, str into an object. + + :param data: dict, list or str. + :param klass: class literal, or string of class name. + + :return: object. + """ + if data is None: + return None + + if type(klass) == str: + if klass.startswith('list['): + sub_kls = re.match(r'list\[(.*)\]', klass).group(1) + return [self.__deserialize(sub_data, sub_kls) + for sub_data in data] + + if klass.startswith('dict('): + sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) + return {k: self.__deserialize(v, sub_kls) + for k, v in six.iteritems(data)} + + # convert str to class + if klass in self.NATIVE_TYPES_MAPPING: + klass = self.NATIVE_TYPES_MAPPING[klass] + else: + klass = getattr({{modelPackage}}, klass) + + if klass in self.PRIMITIVE_TYPES: + return self.__deserialize_primitive(data, klass) + elif klass == object: + return self.__deserialize_object(data) + elif klass == datetime.date: + return self.__deserialize_date(data) + elif klass == datetime.datetime: + return self.__deserialize_datatime(data) + else: + return self.__deserialize_model(data, klass) + + def call_api(self, resource_path, method, + path_params=None, query_params=None, header_params=None, + body=None, post_params=None, files=None, + response_type=None, auth_settings=None, async_req=None, + _return_http_data_only=None, collection_formats=None, + _preload_content=True, _request_timeout=None, _host=None): + """Makes the HTTP request (synchronous) and returns deserialized data. + + To make an async_req request, set the async_req parameter. + + :param resource_path: Path to method endpoint. + :param method: Method to call. + :param path_params: Path parameters in the url. + :param query_params: Query parameters in the url. + :param header_params: Header parameters to be + placed in the request header. + :param body: Request body. + :param post_params dict: Request post form parameters, + for `application/x-www-form-urlencoded`, `multipart/form-data`. + :param auth_settings list: Auth Settings names for the request. + :param response: Response data type. + :param files dict: key -> filename, value -> filepath, + for `multipart/form-data`. + :param async_req bool: execute request asynchronously + :param _return_http_data_only: response data without head status code + and headers + :param collection_formats: dict of collection formats for path, query, + header, and post parameters. + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :return: + If async_req parameter is True, + the request will be called asynchronously. + The method will return the request thread. + If parameter async_req is False or missing, + then the method will return the response directly. + """ + if not async_req: + return self.__call_api(resource_path, method, + path_params, query_params, header_params, + body, post_params, files, + response_type, auth_settings, + _return_http_data_only, collection_formats, + _preload_content, _request_timeout, _host) + else: + thread = self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, query_params, + header_params, body, + post_params, files, + response_type, auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, + _request_timeout, + _host)) + return thread + + def request(self, method, url, query_params=None, headers=None, + post_params=None, body=None, _preload_content=True, + _request_timeout=None): + """Makes the HTTP request using RESTClient.""" + if method == "GET": + return self.rest_client.GET(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "HEAD": + return self.rest_client.HEAD(url, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + headers=headers) + elif method == "OPTIONS": + return self.rest_client.OPTIONS(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "POST": + return self.rest_client.POST(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PUT": + return self.rest_client.PUT(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "PATCH": + return self.rest_client.PATCH(url, + query_params=query_params, + headers=headers, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + elif method == "DELETE": + return self.rest_client.DELETE(url, + query_params=query_params, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + else: + raise ApiValueError( + "http method must be `GET`, `HEAD`, `OPTIONS`," + " `POST`, `PATCH`, `PUT` or `DELETE`." + ) + + def parameters_to_tuples(self, params, collection_formats): + """Get parameters as list of tuples, formatting collections. + + :param params: Parameters as dict or list of two-tuples + :param dict collection_formats: Parameter collection formats + :return: Parameters as list of tuples, collections formatted + """ + new_params = [] + if collection_formats is None: + collection_formats = {} + for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + if k in collection_formats: + collection_format = collection_formats[k] + if collection_format == 'multi': + new_params.extend((k, value) for value in v) + else: + if collection_format == 'ssv': + delimiter = ' ' + elif collection_format == 'tsv': + delimiter = '\t' + elif collection_format == 'pipes': + delimiter = '|' + else: # csv is the default + delimiter = ',' + new_params.append( + (k, delimiter.join(str(value) for value in v))) + else: + new_params.append((k, v)) + return new_params + + def files_parameters(self, files=None): + """Builds form parameters. + + :param files: File parameters. + :return: Form parameters with files. + """ + params = [] + + if files: + for k, v in six.iteritems(files): + if not v: + continue + file_names = v if type(v) is list else [v] + for n in file_names: + with open(n, 'rb') as f: + filename = os.path.basename(f.name) + filedata = f.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([k, tuple([filename, filedata, mimetype])])) + + return params + + def select_header_accept(self, accepts): + """Returns `Accept` based on an array of accepts provided. + + :param accepts: List of headers. + :return: Accept (e.g. application/json). + """ + if not accepts: + return + + accepts = [x.lower() for x in accepts] + + if 'application/json' in accepts: + return 'application/json' + else: + return ', '.join(accepts) + + def select_header_content_type(self, content_types): + """Returns `Content-Type` based on an array of content_types provided. + + :param content_types: List of content-types. + :return: Content-Type (e.g. application/json). + """ + if not content_types: + return 'application/json' + + content_types = [x.lower() for x in content_types] + + if 'application/json' in content_types or '*/*' in content_types: + return 'application/json' + else: + return content_types[0] + + def update_params_for_auth(self, headers, querys, auth_settings): + """Updates header and query params based on authentication setting. + + :param headers: Header parameters dict to be updated. + :param querys: Query parameters tuple list to be updated. + :param auth_settings: Authentication setting identifiers list. + """ + if not auth_settings: + return + + for auth in auth_settings: + auth_setting = self.configuration.auth_settings().get(auth) + if auth_setting: + if not auth_setting['value']: + continue + elif auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] + elif auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ApiValueError( + 'Authentication token must be in `query` or `header`' + ) + + def __deserialize_file(self, response): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + :param response: RESTResponse. + :return: file path. + """ + fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + content_disposition = response.getheader("Content-Disposition") + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "wb") as f: + f.write(response.data) + + return path + + def __deserialize_primitive(self, data, klass): + """Deserializes string to primitive type. + + :param data: str. + :param klass: class literal. + + :return: int, long, float, str, bool. + """ + try: + return klass(data) + except UnicodeEncodeError: + return six.text_type(data) + except TypeError: + return data + + def __deserialize_object(self, value): + """Return an original value. + + :return: object. + """ + return value + + def __deserialize_date(self, string): + """Deserializes string to date. + + :param string: str. + :return: date. + """ + try: + from dateutil.parser import parse + return parse(string).date() + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason="Failed to parse `{0}` as date object".format(string) + ) + + def __deserialize_datatime(self, string): + """Deserializes string to datetime. + + The string should be in iso8601 datetime format. + + :param string: str. + :return: datetime. + """ + try: + from dateutil.parser import parse + return parse(string) + except ImportError: + return string + except ValueError: + raise rest.ApiException( + status=0, + reason=( + "Failed to parse `{0}` as datetime object" + .format(string) + ) + ) + + def __deserialize_model(self, data, klass): + """Deserializes list or dict to model. + + :param data: dict, list. + :param klass: class literal. + :return: model object. + """ + + if not klass.openapi_types and not hasattr(klass, + 'get_real_child_model'): + return data + + used_data = data + if not isinstance(data, (list, dict)): + used_data = [data] + keyword_args = {} + positional_args = [] + if klass.openapi_types is not None: + for attr, attr_type in six.iteritems(klass.openapi_types): + if (data is not None and + klass.attribute_map[attr] in used_data): + value = used_data[klass.attribute_map[attr]] + keyword_args[attr] = self.__deserialize(value, attr_type) + + end_index = None + argspec = inspect.getargspec(getattr(klass, '__init__')) + if argspec.defaults: + end_index = -len(argspec.defaults) + required_positional_args = argspec.args[1:end_index] + + for index, req_positional_arg in enumerate(required_positional_args): + if keyword_args and req_positional_arg in keyword_args: + positional_args.append(keyword_args[req_positional_arg]) + del keyword_args[req_positional_arg] + elif (not keyword_args and index < len(used_data) and + isinstance(used_data, list)): + positional_args.append(used_data[index]) + + instance = klass(*positional_args, **keyword_args) + + if hasattr(instance, 'get_real_child_model'): + klass_name = instance.get_real_child_model(data) + if klass_name: + instance = self.__deserialize(data, klass_name) + return instance diff --git a/python-experimental/api_doc.mustache b/python-experimental/api_doc.mustache new file mode 100644 index 0000000000..5cc638a2eb --- /dev/null +++ b/python-experimental/api_doc.mustache @@ -0,0 +1,78 @@ +# {{packageName}}.{{classname}}{{#description}} +{{description}}{{/description}} + +All URIs are relative to *{{basePath}}* + +Method | HTTP request | Description +------------- | ------------- | ------------- +{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}} + +{{#operations}} +{{#operation}} +# **{{{operationId}}}** +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}) + +{{{summary}}}{{#notes}} + +{{{notes}}}{{/notes}} + +### Example + +{{#hasAuthMethods}} +{{#authMethods}} +{{#isBasic}} +{{^isBasicBearer}} +* Basic Authentication ({{name}}): +{{/isBasicBearer}} +{{#isBasicBearer}} +* Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}): +{{/isBasicBearer}} +{{/isBasic}} +{{#isApiKey}} +* Api Key Authentication ({{name}}): +{{/isApiKey }} +{{#isOAuth}} +* OAuth Authentication ({{name}}): +{{/isOAuth }} +{{> api_doc_example }} +{{/authMethods}} +{{/hasAuthMethods}} +{{^hasAuthMethods}} +{{> api_doc_example }} +{{/hasAuthMethods}} +### Parameters +{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} +Name | Type | Description | Notes +------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} +{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | +{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | defaults to {{{.}}} +{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{/optionalParams}} + +### Return type + +{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} + +### Authorization + +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} + +### HTTP request headers + + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + +{{#responses.0}} +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +{{#responses}} +**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | +{{/responses}} +{{/responses.0}} + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + +{{/operation}} +{{/operations}} diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache new file mode 100644 index 0000000000..e5eeee6b0e --- /dev/null +++ b/python-experimental/api_doc_example.mustache @@ -0,0 +1,58 @@ +```python +from __future__ import print_function +import time +import {{{packageName}}} +from {{{packageName}}}.rest import ApiException +from pprint import pprint +{{> python_doc_auth_partial}} +{{#hasAuthMethods}} +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{/hasAuthMethods}} +{{^hasAuthMethods}} +# Create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}() +{{/hasAuthMethods}} +{{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} +{{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} +{{/optionalParams}} + +{{#requiredParams}} +{{^hasMore}} +# example passing only required values which don't have defaults set +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/hasMore}} +{{/requiredParams}} + +{{#optionalParams}} +{{^hasMore}} +# example passing only required values which don't have defaults set +# and optional values +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/hasMore}} +{{/optionalParams}} + +{{^requiredParams}} +{{^optionalParams}} +# example, this endpoint has no required or optional parameters +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}(){{#returnType}} + pprint(api_response){{/returnType}} +except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/optionalParams}} +{{/requiredParams}} +``` diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache new file mode 100644 index 0000000000..7dc8e01fa6 --- /dev/null +++ b/python-experimental/model.mustache @@ -0,0 +1,241 @@ +# coding: utf-8 + +{{>partial_header}} + +import pprint +import re # noqa: F401 + +import six + + +{{#models}} +{{#model}} +class {{classname}}(object): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + """{{#allowableValues}} + + """ + allowed enum values + """ +{{#enumVars}} + {{name}} = {{{value}}}{{^-last}} +{{/-last}} +{{/enumVars}}{{/allowableValues}} + + """ + Attributes: + openapi_types (dict): The key is attribute name + and the value is attribute type. + attribute_map (dict): The key is attribute name + and the value is json key in definition. + """ + openapi_types = { +{{#requiredVars}} + '{{name}}': '{{{dataType}}}', +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': '{{{dataType}}}', +{{/optionalVars}} + } + + attribute_map = { +{{#requiredVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/optionalVars}} + } +{{#discriminator}} + + discriminator_value_class_map = { + {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, + {{/-last}}{{/children}} + } +{{/discriminator}} + + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}, {{name}}=None{{/optionalVars}}): # noqa: E501 + """{{classname}} - a model defined in OpenAPI + +{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} + {{name}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}} + + Keyword Args:{{#requiredVars}}{{#defaultValue}} + {{name}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}} # noqa: E501{{/requiredVars}}{{#optionalVars}} + {{name}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} + """ +{{#vars}}{{#-first}} +{{/-first}} + self._{{name}} = None +{{/vars}} + self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} +{{#vars}}{{#-first}} +{{/-first}} +{{#required}} + self.{{name}} = {{name}} +{{/required}} +{{^required}} +{{#isNullable}} + self.{{name}} = {{name}} +{{/isNullable}} +{{^isNullable}} + if {{name}} is not None: + self.{{name}} = {{name}} # noqa: E501 +{{/isNullable}} +{{/required}} +{{/vars}} + +{{#vars}} + @property + def {{name}}(self): + """Gets the {{name}} of this {{classname}}. # noqa: E501 + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :return: The {{name}} of this {{classname}}. # noqa: E501 + :rtype: {{dataType}} + """ + return self._{{name}} + + @{{name}}.setter + def {{name}}( + self, + {{name}}): + """Sets the {{name}} of this {{classname}}. + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 + :type: {{dataType}} + """ +{{^isNullable}} +{{#required}} + if {{name}} is None: + raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 +{{/required}} +{{/isNullable}} +{{#isEnum}} +{{#isContainer}} + allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 +{{#isListContainer}} + if not set({{{name}}}).issubset(set(allowed_values)): + raise ValueError( + "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isListContainer}} +{{#isMapContainer}} + if not set({{{name}}}.keys()).issubset(set(allowed_values)): + raise ValueError( + "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 + .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 + ", ".join(map(str, allowed_values))) + ) +{{/isMapContainer}} +{{/isContainer}} +{{^isContainer}} + allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 + if {{{name}}} not in allowed_values: + raise ValueError( + "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 + .format({{{name}}}, allowed_values) + ) +{{/isContainer}} +{{/isEnum}} +{{^isEnum}} +{{#hasValidation}} +{{#maxLength}} + if {{name}} is not None and len({{name}}) > {{maxLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 +{{/maxLength}} +{{#minLength}} + if {{name}} is not None and len({{name}}) < {{minLength}}: + raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 +{{/minLength}} +{{#maximum}} + if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 +{{/maximum}} +{{#minimum}} + if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 +{{/minimum}} +{{#pattern}} + if {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + raise ValueError(r"Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 +{{/pattern}} +{{#maxItems}} + if {{name}} is not None and len({{name}}) > {{maxItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 +{{/maxItems}} +{{#minItems}} + if {{name}} is not None and len({{name}}) < {{minItems}}: + raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 +{{/minItems}} +{{/hasValidation}} +{{/isEnum}} + + self._{{name}} = ( + {{name}}) + +{{/vars}} +{{#discriminator}} + def get_real_child_model(self, data): + """Returns the real base class specified by the discriminator""" + discriminator_key = self.attribute_map[self.discriminator] + discriminator_value = data[discriminator_key] + return self.discriminator_value_class_map.get(discriminator_value) + +{{/discriminator}} + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.openapi_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other +{{/model}} +{{/models}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache new file mode 100644 index 0000000000..b6e1b263fc --- /dev/null +++ b/python-experimental/model_doc.mustache @@ -0,0 +1,13 @@ +{{#models}}{{#model}}# {{classname}} + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +{{#requiredVars}}{{^defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#readOnly}}[readonly] {{/readOnly}} +{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} +{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{/optionalVars}} + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + +{{/model}}{{/models}} From fbb5a181635d5ef3ada6d69fbb1571537448e130 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Mon, 12 Aug 2019 22:55:45 -0700 Subject: [PATCH 046/180] [Python] avoid unnecessary dictionary lookup in get_api_key method (#3592) --- configuration.mustache | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 6d0d5c62e1..b82ff7db89 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -238,11 +238,13 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): :param identifier: The identifier of apiKey. :return: The token for api key authentication. """ - if (self.api_key.get(identifier) and - self.api_key_prefix.get(identifier)): - return self.api_key_prefix[identifier] + ' ' + self.api_key[identifier] # noqa: E501 - elif self.api_key.get(identifier): - return self.api_key[identifier] + key = self.api_key.get(identifier) + if key: + prefix = self.api_key_prefix.get(identifier) + if prefix: + return "%s %s" % (prefix, key) + else: + return key def get_basic_auth_token(self): """Gets HTTP basic authentication header (string). From 8218fa2546d51d050f330ad8061d2b9f69a9acdc Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Thu, 15 Aug 2019 07:06:36 -0700 Subject: [PATCH 047/180] [Python] support api key refresh in configuration module (#3594) --- configuration.mustache | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index b82ff7db89..2afcb7478e 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -61,6 +61,9 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): self.api_key_prefix = api_key_prefix """dict to store API prefix (e.g. Bearer) """ + self.refresh_api_key_hook = None + """function hook to refresh API key if expired + """ self.username = username """Username for HTTP basic authentication """ @@ -238,6 +241,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): :param identifier: The identifier of apiKey. :return: The token for api key authentication. """ + if self.refresh_api_key_hook is not None: + self.refresh_api_key_hook(self) key = self.api_key.get(identifier) if key: prefix = self.api_key_prefix.get(identifier) From 91d4c6eb3aaf5f06b4732ce3a43e3ad1ae99510a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20K=C3=A4gi?= Date: Sun, 25 Aug 2019 11:59:38 +0200 Subject: [PATCH 048/180] Exclude "test" from packages so that it is not installed as top-level package when "pip installing" the generated sdk (#3731) --- setup.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.mustache b/setup.mustache index 201b79e217..588851cc7b 100644 --- a/setup.mustache +++ b/setup.mustache @@ -32,7 +32,7 @@ setup( url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], install_requires=REQUIRES, - packages=find_packages(), + packages=find_packages(exclude=["test", "tests"]), include_package_data=True, long_description="""\ {{appDescription}} # noqa: E501 From e8a3a27447a400357f89ab361a81ca8f0e94f992 Mon Sep 17 00:00:00 2001 From: Quim Muntal Date: Tue, 3 Sep 2019 15:35:49 +0200 Subject: [PATCH 049/180] Support custom git repository (#3757) * add gitHost param to GeneratorSettings and related * parameterize gitHost in READMEs * parameterize gitHost in go.mod * parameterize gitHost in git_push * update petstore samples * run ./bin/utils/export_docs_generators.sh * run meta-codehen.sh * Revert "run meta-codehen.sh" This reverts commit d6d579f6159186531257cdfdd73b9caf9e9ffeba. * Revert "run ./bin/utils/export_docs_generators.sh" This reverts commit 1b81538198d4319fd1b4e97447303e3cc0e8dc99. * Revert "update petstore samples" This reverts commit f513add88396707f6991ae2e4920359583ec88f1. * run ensure-up-to-date --- README.mustache | 6 +++--- git_push.sh.mustache | 16 +++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/README.mustache b/README.mustache index be83533906..144f72427e 100644 --- a/README.mustache +++ b/README.mustache @@ -22,12 +22,12 @@ Python 2.7 and 3.4+ ## Installation & Usage ### pip install -If the python package is hosted on Github, you can install directly from Github +If the python package is hosted on a repository, you can install directly using: ```sh -pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git +pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git ``` -(you may need to run `pip` with root permission: `sudo pip install git+https://github.com/{{{gitUserId}}}/{{{gitRepoId}}}.git`) +(you may need to run `pip` with root permission: `sudo pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git`) Then import the package: ```python diff --git a/git_push.sh.mustache b/git_push.sh.mustache index 8a32e53995..8b3f689c91 100755 --- a/git_push.sh.mustache +++ b/git_push.sh.mustache @@ -1,11 +1,17 @@ #!/bin/sh # ref: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/ # -# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" +# Usage example: /bin/sh ./git_push.sh wing328 openapi-pestore-perl "minor update" "gitlab.com" git_user_id=$1 git_repo_id=$2 release_note=$3 +git_host=$4 + +if [ "$git_host" = "" ]; then + git_host="{{{gitHost}}}" + echo "[INFO] No command line input provided. Set \$git_host to $git_host" +fi if [ "$git_user_id" = "" ]; then git_user_id="{{{gitUserId}}}" @@ -28,7 +34,7 @@ git init # Adds the files in the local repository and stages them for commit. git add . -# Commits the tracked changes and prepares them to be pushed to a remote repository. +# Commits the tracked changes and prepares them to be pushed to a remote repository. git commit -m "$release_note" # Sets the new remote @@ -37,9 +43,9 @@ if [ "$git_remote" = "" ]; then # git remote not defined if [ "$GIT_TOKEN" = "" ]; then echo "[INFO] \$GIT_TOKEN (environment variable) is not set. Using the git credential in your environment." - git remote add origin https://github.com/${git_user_id}/${git_repo_id}.git + git remote add origin https://${git_host}/${git_user_id}/${git_repo_id}.git else - git remote add origin https://${git_user_id}:${GIT_TOKEN}@github.com/${git_user_id}/${git_repo_id}.git + git remote add origin https://${git_user_id}:${GIT_TOKEN}@${git_host}/${git_user_id}/${git_repo_id}.git fi fi @@ -47,6 +53,6 @@ fi git pull origin master # Pushes (Forces) the changes in the local repository up to the remote repository -echo "Git pushing to https://github.com/${git_user_id}/${git_repo_id}.git" +echo "Git pushing to https://${git_host}/${git_user_id}/${git_repo_id}.git" git push origin master 2>&1 | grep -v 'To https' From 9af5c1ace36150bf663052cb0d52fa72bb4125ae Mon Sep 17 00:00:00 2001 From: Justin Black Date: Tue, 24 Sep 2019 03:44:28 -0700 Subject: [PATCH 050/180] [python-experimental] generate model if type != object if enums/validations exist (#2757) * Python-experimental adds model_utils module, refactors python api class * Fixes python-experimental so the sample sare generated in the petstore_api folder * FIxes python samples tests * Updates python and python-experimental tests * Fixes python-experimental tests * Adds newlines back to python templates + samples * Reverts files with newline tweaks back to master branch versions * Fixes indentation errors in python-experimental api_client * Removes unused files * Python files now generated in correct folders * Adds logging when the user tries to set generateAliasAsModel in python-experimental * Fixes typo --- python-experimental/api.mustache | 589 +++++++++++------- python-experimental/api_client.mustache | 25 +- python-experimental/model.mustache | 250 +------- .../model_templates/classvar_allowed.mustache | 16 + .../classvar_openapi_validations.mustache | 25 + .../docstring_allowed.mustache | 4 + .../docstring_openapi_validations.mustache | 7 + .../methods_init_properties.mustache | 76 +++ .../model_templates/model_normal.mustache | 83 +++ .../model_templates/model_simple.mustache | 34 + python-experimental/model_utils.mustache | 175 ++++++ 11 files changed, 813 insertions(+), 471 deletions(-) create mode 100644 python-experimental/model_templates/classvar_allowed.mustache create mode 100644 python-experimental/model_templates/classvar_openapi_validations.mustache create mode 100644 python-experimental/model_templates/docstring_allowed.mustache create mode 100644 python-experimental/model_templates/docstring_openapi_validations.mustache create mode 100644 python-experimental/model_templates/methods_init_properties.mustache create mode 100644 python-experimental/model_templates/model_normal.mustache create mode 100644 python-experimental/model_templates/model_simple.mustache create mode 100644 python-experimental/model_utils.mustache diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index edf76be03b..dd650b37d7 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -10,10 +10,14 @@ import re # noqa: F401 import six from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( # noqa: F401 +from {{packageName}}.exceptions import ( ApiTypeError, ApiValueError ) +from {{packageName}}.model_utils import ( + check_allowed_values, + check_validations +) {{#operations}} @@ -30,265 +34,384 @@ class {{classname}}(object): self.api_client = api_client {{#operation}} - def {{operationId}}(self{{#requiredParams}}{{^defaultValue}}, {{paramName}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}, {{paramName}}={{{defaultValue}}}{{/defaultValue}}{{/requiredParams}}, **kwargs): # noqa: E501 - """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + def __{{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 {{#notes}} - {{{notes}}} # noqa: E501 + {{{notes}}} # noqa: E501 {{/notes}} - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) - >>> result = thread.get() - -{{#requiredParams}} -{{^hasMore}} - Args: -{{/hasMore}} -{{/requiredParams}} -{{#requiredParams}} -{{^defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}}{{/requiredParams}} + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True +{{#sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) +{{/sortParamsByRequiredFlag}} +{{^sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) +{{/sortParamsByRequiredFlag}} + >>> result = thread.get() - Keyword Args:{{#optionalParams}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} - async_req (bool): execute request asynchronously - param _preload_content (bool): if False, the urllib3.HTTPResponse - object will be returned without reading/decoding response data. + :param async_req bool: execute request asynchronously +{{#allParams}} + :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} +{{/allParams}} + :param _return_http_data_only: response data without head status + code and headers + :param _preload_content: if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. Default is True. - param _request_timeout (float/tuple): timeout setting for this - request. If one number provided, it will be total request - timeout. It can also be a pair (tuple) of (connection, read) - timeouts. - - Returns: - {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}: - """ - kwargs['_return_http_data_only'] = True - if kwargs.get('async_req'): - return self.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{paramName}}, {{/defaultValue}}{{/requiredParams}}**kwargs) # noqa: E501 - else: - (data) = self.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{paramName}}, {{/defaultValue}}{{/requiredParams}}**kwargs) # noqa: E501 - return data - - def {{operationId}}_with_http_info(self{{#requiredParams}}{{^defaultValue}}, {{paramName}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}, {{paramName}}=None{{/defaultValue}}{{/requiredParams}}, **kwargs): # noqa: E501 - """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 - -{{#notes}} - {{{notes}}} # noqa: E501 -{{/notes}} - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - >>> thread = api.{{operationId}}_with_http_info({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}async_req=True) - >>> result = thread.get() - + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, returns the request + thread. + """ + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) {{#requiredParams}} -{{^hasMore}} - Args: -{{/hasMore}} + kwargs['{{paramName}}'] = {{paramName}} {{/requiredParams}} -{{#requiredParams}} -{{^defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}}{{/requiredParams}} - - Keyword Args:{{#optionalParams}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} - async_req (bool): execute request asynchronously - param _preload_content (bool): if False, the urllib3.HTTPResponse - object will be returned without reading/decoding response data. - Default is True. - param _request_timeout (float/tuple): timeout setting for this - request. If one number provided, it will be total request - timeout. It can also be a pair (tuple) of (connection, read) - timeouts. - - Returns: - {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}}: - """ + return self.call_with_http_info(**kwargs) - {{#servers.0}} - local_var_hosts = [{{#servers}} - '{{{url}}}'{{^-last}},{{/-last}}{{/servers}} - ] - local_var_host = local_var_hosts[0] - if kwargs.get('_host_index'): - if (int(kwargs.get('_host_index')) < 0 or - int(kwargs.get('_host_index')) >= len(local_var_hosts)): - raise ApiValueError( - "Invalid host index. Must be 0 <= index < %s" % - len(local_var_host) - ) - local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] - {{/servers.0}} - local_var_params = locals() - - all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 - all_params.append('async_req') - all_params.append('_return_http_data_only') - all_params.append('_preload_content') - all_params.append('_request_timeout') - - for key, val in six.iteritems(local_var_params['kwargs']): - if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method {{operationId}}" % key - ) - local_var_params[key] = val - del local_var_params['kwargs'] + self.{{operationId}} = Endpoint( + settings={ + 'response_type': {{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, +{{#authMethods}} +{{#-first}} + 'auth': [ +{{/-first}} + '{{name}}'{{#hasMore}}, {{/hasMore}} +{{#-last}} + ], +{{/-last}} +{{/authMethods}} +{{^authMethods}} + 'auth': [], +{{/authMethods}} + 'endpoint_path': '{{{path}}}', + 'operation_id': '{{operationId}}', + 'http_method': '{{httpMethod}}', +{{#servers}} +{{#-first}} + 'servers': [ +{{/-first}} + '{{{url}}}'{{^-last}},{{/-last}} +{{#-last}} + ] +{{/-last}} +{{/servers}} +{{^servers}} + 'servers': [], +{{/servers}} + }, + params_map={ + 'all': [ {{#allParams}} -{{^isNullable}} -{{#required}} - # verify the required parameter '{{paramName}}' is set - if ('{{paramName}}' not in local_var_params or - local_var_params['{{paramName}}'] is None): - raise ApiValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 -{{/required}} -{{/isNullable}} + '{{paramName}}', +{{/allParams}} + ], +{{#requiredParams}} +{{#-first}} + 'required': [ +{{/-first}} + '{{paramName}}', {{#-last}} + ], {{/-last}} +{{/requiredParams}} +{{^requiredParams}} + 'required': [], +{{/requiredParams}} + 'nullable': [ +{{#allParams}} +{{#isNullable}} + '{{paramName}}', +{{/isNullable}} {{/allParams}} + ], + 'enum': [ {{#allParams}} {{#isEnum}} -{{#isContainer}} - allowed_values = [{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 -{{#isListContainer}} - if ('{{{paramName}}}' in local_var_params and - not set(local_var_params['{{{paramName}}}']).issubset(set(allowed_values))): # noqa: E501 - raise ValueError( - "Invalid values for `{{{paramName}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set(local_var_params['{{{paramName}}}']) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) -{{/isListContainer}} -{{#isMapContainer}} - if ('{{{paramName}}}' in local_var_params and - not set(local_var_params['{{{paramName}}}'].keys()).issubset(set(allowed_values))): - raise ValueError( - "Invalid keys in `{{{paramName}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set(local_var_params['{{{paramName}}}'].keys()) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) -{{/isMapContainer}} -{{/isContainer}} -{{^isContainer}} - allowed_values = [{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 - if ('{{{paramName}}}' in local_var_params and - local_var_params['{{{paramName}}}'] not in allowed_values): - raise ValueError( - "Invalid value for `{{{paramName}}}` ({0}), must be one of {1}" # noqa: E501 - .format(local_var_params['{{{paramName}}}'], allowed_values) - ) -{{/isContainer}} + '{{paramName}}', {{/isEnum}} {{/allParams}} + ], + 'validation': [ {{#allParams}} {{#hasValidation}} - {{#maxLength}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) > {{maxLength}}): - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 - {{/maxLength}} - {{#minLength}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) < {{minLength}}): - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 - {{/minLength}} - {{#maximum}} - if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 - {{/maximum}} - {{#minimum}} - if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 - {{/minimum}} - {{#pattern}} - if '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 - {{/pattern}} - {{#maxItems}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) > {{maxItems}}): - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 - {{/maxItems}} - {{#minItems}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) < {{minItems}}): - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 - {{/minItems}} + '{{paramName}}', {{/hasValidation}} {{/allParams}} + ] + }, + root_map={ + 'validations': { +{{#allParams}} +{{#hasValidation}} + ('{{paramName}}',): { +{{#maxLength}} + 'max_length': {{maxLength}},{{/maxLength}}{{#minLength}} + 'min_length': {{minLength}},{{/minLength}}{{#maxItems}} + 'max_items': {{maxItems}},{{/maxItems}}{{#minItems}} + 'min_items': {{minItems}},{{/minItems}}{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + },{{/pattern}} + }, +{{/hasValidation}} +{{/allParams}} + }, + 'allowed_values': { +{{#allParams}} +{{#isEnum}} + ('{{paramName}}',): { +{{#isNullable}} + 'None': None,{{/isNullable}}{{#allowableValues}}{{#enumVars}} + "{{name}}": {{{value}}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} + }, +{{/isEnum}} +{{/allParams}} + }, + 'openapi_types': { +{{#allParams}} + '{{paramName}}': '{{dataType}}', +{{/allParams}} + }, + 'attribute_map': { +{{#allParams}} +{{^isBodyParam}} + '{{paramName}}': '{{baseName}}', +{{/isBodyParam}} +{{/allParams}} + }, + 'location_map': { +{{#allParams}} + '{{paramName}}': '{{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isCookieParam}}cookie{{/isCookieParam}}{{#isBodyParam}}body{{/isBodyParam}}', +{{/allParams}} + }, + 'collection_format_map': { +{{#allParams}} +{{#collectionFormat}} + '{{paramName}}': '{{collectionFormat}}', +{{/collectionFormat}} +{{/allParams}} + } + }, + headers_map={ +{{#hasProduces}} + 'accept': [ +{{#produces}} + '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} +{{/produces}} + ], +{{/hasProduces}} +{{^hasProduces}} + 'accept': [], +{{/hasProduces}} +{{#hasConsumes}} + 'content_type': [ +{{#consumes}} + '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} +{{/consumes}} + ] +{{/hasConsumes}} +{{^hasConsumes}} + 'content_type': [], +{{/hasConsumes}} + }, + api_client=api_client, + callable=__{{operationId}} + ) +{{/operation}} +{{/operations}} + + +class Endpoint(object): + def __init__(self, settings=None, params_map=None, root_map=None, + headers_map=None, api_client=None, callable=None): + """Creates an endpoint + + Args: + settings (dict): see below key value pairs + 'response_type' (str): response type + 'auth' (list): a list of auth type keys + 'endpoint_path' (str): the endpoint path + 'operation_id' (str): endpoint string identifier + 'http_method' (str): POST/PUT/PATCH/GET etc + 'servers' (list): list of str servers that this endpoint is at + params_map (dict): see below key value pairs + 'all' (list): list of str endpoint parameter names + 'required' (list): list of required parameter names + 'nullable' (list): list of nullable parameter names + 'enum' (list): list of parameters with enum values + 'validation' (list): list of parameters with validations + root_map + 'validations' (dict): the dict mapping endpoint parameter tuple + paths to their validation dictionaries + 'allowed_values' (dict): the dict mapping endpoint parameter + tuple paths to their allowed_values (enum) dictionaries + 'openapi_types' (dict): param_name to openapi type + 'attribute_map' (dict): param_name to camelCase name + 'location_map' (dict): param_name to 'body', 'file', 'form', + 'header', 'path', 'query' + collection_format_map (dict): param_name to `csv` etc. + headers_map (dict): see below key value pairs + 'accept' (list): list of Accept header strings + 'content_type' (list): list of Content-Type header strings + api_client (ApiClient) api client instance + callable (function): the function which is invoked when the + Endpoint is called + """ + self.settings = settings + self.params_map = params_map + self.params_map['all'].extend([ + 'async_req', + '_host_index', + '_preload_content', + '_request_timeout', + '_return_http_data_only' + ]) + self.validations = root_map['validations'] + self.allowed_values = root_map['allowed_values'] + self.openapi_types = root_map['openapi_types'] + self.attribute_map = root_map['attribute_map'] + self.location_map = root_map['location_map'] + self.collection_format_map = root_map['collection_format_map'] + self.headers_map = headers_map + self.api_client = api_client + self.callable = callable + + def __validate_inputs(self, kwargs): + for param in self.params_map['enum']: + if param in kwargs: + check_allowed_values( + self.allowed_values, + (param,), + kwargs[param], + self.validations + ) + + for param in self.params_map['validation']: + if param in kwargs: + check_validations( + self.validations, + (param,), + kwargs[param] + ) + + def __gather_params(self, kwargs): + params = { + 'body': None, + 'collection_format': {}, + 'file': {}, + 'form': [], + 'header': {}, + 'path': {}, + 'query': [] + } - collection_formats = {} + for param_name, param_value in six.iteritems(kwargs): + param_location = self.location_map.get(param_name) + if param_location: + if param_location == 'body': + params['body'] = param_value + continue + base_name = self.attribute_map[param_name] + if (param_location == 'form' and + self.openapi_types[param_name] == 'file'): + param_location = 'file' + elif param_location in {'form', 'query'}: + param_value_full = (base_name, param_value) + params[param_location].append(param_value_full) + if param_location not in {'form', 'query'}: + params[param_location][base_name] = param_value + collection_format = self.collection_format_map.get(param_name) + if collection_format: + params['collection_format'][base_name] = collection_format - path_params = {} -{{#pathParams}} - if '{{paramName}}' in local_var_params: - path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 -{{/pathParams}} + return params + + def __call__(self, *args, **kwargs): + """ This method is invoked when endpoints are called + Example: + pet_api = PetApi() + pet_api.add_pet # this is an instance of the class Endpoint + pet_api.add_pet() # this invokes pet_api.add_pet.__call__() + which then invokes the callable functions stored in that endpoint at + pet_api.add_pet.callable or self.callable in this class + """ + return self.callable(self, *args, **kwargs) + + def call_with_http_info(self, **kwargs): + + if kwargs.get('_host_index') and self.settings['servers']: + _host_index = kwargs.get('_host_index') + try: + _host = self.settings['servers'][_host_index] + except IndexError: + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" % + len(self.settings['servers']) + ) + else: + try: + _host = self.settings['servers'][0] + except IndexError: + _host = None - query_params = [] -{{#queryParams}} - if '{{paramName}}' in local_var_params: - query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 -{{/queryParams}} + for key, value in six.iteritems(kwargs): + if key not in self.params_map['all']: + raise ApiTypeError( + "Got an unexpected parameter '%s'" + " to method `%s`" % + (key, self.settings['operation_id']) + ) + if key not in self.params_map['nullable'] and value is None: + raise ApiValueError( + "Value may not be None for non-nullable parameter `%s`" + " when calling `%s`" % + (key, self.settings['operation_id']) + ) - header_params = {} -{{#headerParams}} - if '{{paramName}}' in local_var_params: - header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 -{{/headerParams}} + for key in self.params_map['required']: + if key not in kwargs.keys(): + raise ApiValueError( + "Missing the required parameter `%s` when calling " + "`%s`" % (key, self.settings['operation_id']) + ) - form_params = [] - local_var_files = {} -{{#formParams}} - if '{{paramName}}' in local_var_params: - {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 -{{/formParams}} + self.__validate_inputs(kwargs) - body_params = None -{{#bodyParam}} - if '{{paramName}}' in local_var_params: - body_params = local_var_params['{{paramName}}'] -{{/bodyParam}} - {{#hasProduces}} - # HTTP header `Accept` - header_params['Accept'] = self.api_client.select_header_accept( - [{{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) # noqa: E501 + params = self.__gather_params(kwargs) - {{/hasProduces}} - {{#hasConsumes}} - # HTTP header `Content-Type` - header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 - [{{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) # noqa: E501 + accept_headers_list = self.headers_map['accept'] + if accept_headers_list: + params['header']['Accept'] = self.api_client.select_header_accept( + accept_headers_list) - {{/hasConsumes}} - # Authentication setting - auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + content_type_headers_list = self.headers_map['content_type'] + if content_type_headers_list: + header_list = self.api_client.select_header_content_type( + content_type_headers_list) + params['header']['Content-Type'] = header_list return self.api_client.call_api( - '{{{path}}}', '{{httpMethod}}', - path_params, - query_params, - header_params, - body=body_params, - post_params=form_params, - files=local_var_files, - response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 - auth_settings=auth_settings, - async_req=local_var_params.get('async_req'), - _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 - _preload_content=local_var_params.get('_preload_content', True), - _request_timeout=local_var_params.get('_request_timeout'), - {{#servers.0}} - _host=local_var_host, - {{/servers.0}} - collection_formats=collection_formats) -{{/operation}} -{{/operations}} + self.settings['endpoint_path'], self.settings['http_method'], + params['path'], + params['query'], + params['header'], + body=params['body'], + post_params=params['form'], + files=params['file'], + response_type=self.settings['response_type'], + auth_settings=self.settings['auth'], + async_req=kwargs.get('async_req'), + _return_http_data_only=kwargs.get('_return_http_data_only'), + _preload_content=kwargs.get('_preload_content', True), + _request_timeout=kwargs.get('_request_timeout'), + _host=_host, + collection_formats=params['collection_format']) diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index e955eb0570..0f02b445df 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -18,9 +18,13 @@ from six.moves.urllib.parse import quote import tornado.gen {{/tornado}} -from {{packageName}}.configuration import Configuration import {{modelPackage}} from {{packageName}} import rest +from {{packageName}}.configuration import Configuration +from {{packageName}}.model_utils import ( + ModelNormal, + ModelSimple +) from {{packageName}}.exceptions import ApiValueError @@ -224,7 +228,7 @@ class ApiClient(object): if isinstance(obj, dict): obj_dict = obj - else: + elif isinstance(obj, ModelNormal): # Convert model obj to dict except # attributes `openapi_types`, `attribute_map` # and attributes which value is not None. @@ -233,6 +237,8 @@ class ApiClient(object): obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) for attr, _ in six.iteritems(obj.openapi_types) if getattr(obj, attr) is not None} + elif isinstance(obj, ModelSimple): + return self.sanitize_for_serialization(obj.value) return {key: self.sanitize_for_serialization(val) for key, val in six.iteritems(obj_dict)} @@ -571,6 +577,8 @@ class ApiClient(object): return six.text_type(data) except TypeError: return data + except ValueError as exc: + raise ApiValueError(str(exc)) def __deserialize_object(self, value): """Return an original value. @@ -622,14 +630,15 @@ class ApiClient(object): """Deserializes list or dict to model. :param data: dict, list. - :param klass: class literal. + :param klass: class literal, ModelSimple or ModelNormal :return: model object. """ - if not klass.openapi_types and not hasattr(klass, - 'get_real_child_model'): - return data + if issubclass(klass, ModelSimple): + value = self.__deserialize(data, klass.openapi_types['value']) + return klass(value) + # code to handle ModelNormal used_data = data if not isinstance(data, (list, dict)): used_data = [data] @@ -641,13 +650,11 @@ class ApiClient(object): klass.attribute_map[attr] in used_data): value = used_data[klass.attribute_map[attr]] keyword_args[attr] = self.__deserialize(value, attr_type) - end_index = None argspec = inspect.getargspec(getattr(klass, '__init__')) if argspec.defaults: end_index = -len(argspec.defaults) required_positional_args = argspec.args[1:end_index] - for index, req_positional_arg in enumerate(required_positional_args): if keyword_args and req_positional_arg in keyword_args: positional_args.append(keyword_args[req_positional_arg]) @@ -655,9 +662,7 @@ class ApiClient(object): elif (not keyword_args and index < len(used_data) and isinstance(used_data, list)): positional_args.append(used_data[index]) - instance = klass(*positional_args, **keyword_args) - if hasattr(instance, 'get_real_child_model'): klass_name = instance.get_real_child_model(data) if klass_name: diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 7dc8e01fa6..082f4bddc4 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -2,240 +2,34 @@ {{>partial_header}} -import pprint +import pprint # noqa: F401 import re # noqa: F401 -import six +import six # noqa: F401 + +from {{packageName}}.exceptions import ApiValueError # noqa: F401 +from {{packageName}}.model_utils import ( # noqa: F401 + ModelNormal, + ModelSimple, + check_allowed_values, + check_validations +) {{#models}} {{#model}} -class {{classname}}(object): - """NOTE: This class is auto generated by OpenAPI Generator. - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """{{#allowableValues}} - - """ - allowed enum values - """ -{{#enumVars}} - {{name}} = {{{value}}}{{^-last}} +{{^interfaces}} +{{#isAlias}} +{{> python-experimental/model_templates/model_simple }} +{{/isAlias}} +{{^isAlias}} +{{> python-experimental/model_templates/model_normal }} +{{/isAlias}} +{{/interfaces}} +{{#interfaces}} +{{#-last}} +{{> python-experimental/model_templates/model_normal }} {{/-last}} -{{/enumVars}}{{/allowableValues}} - - """ - Attributes: - openapi_types (dict): The key is attribute name - and the value is attribute type. - attribute_map (dict): The key is attribute name - and the value is json key in definition. - """ - openapi_types = { -{{#requiredVars}} - '{{name}}': '{{{dataType}}}', -{{/requiredVars}} -{{#optionalVars}} - '{{name}}': '{{{dataType}}}', -{{/optionalVars}} - } - - attribute_map = { -{{#requiredVars}} - '{{name}}': '{{baseName}}', # noqa: E501 -{{/requiredVars}} -{{#optionalVars}} - '{{name}}': '{{baseName}}', # noqa: E501 -{{/optionalVars}} - } -{{#discriminator}} - - discriminator_value_class_map = { - {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, - {{/-last}}{{/children}} - } -{{/discriminator}} - - def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}, {{name}}=None{{/optionalVars}}): # noqa: E501 - """{{classname}} - a model defined in OpenAPI - -{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} - {{name}} ({{dataType}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}} - - Keyword Args:{{#requiredVars}}{{#defaultValue}} - {{name}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}]{{/defaultValue}} # noqa: E501{{/requiredVars}}{{#optionalVars}} - {{name}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} - """ -{{#vars}}{{#-first}} -{{/-first}} - self._{{name}} = None -{{/vars}} - self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} -{{#vars}}{{#-first}} -{{/-first}} -{{#required}} - self.{{name}} = {{name}} -{{/required}} -{{^required}} -{{#isNullable}} - self.{{name}} = {{name}} -{{/isNullable}} -{{^isNullable}} - if {{name}} is not None: - self.{{name}} = {{name}} # noqa: E501 -{{/isNullable}} -{{/required}} -{{/vars}} - -{{#vars}} - @property - def {{name}}(self): - """Gets the {{name}} of this {{classname}}. # noqa: E501 - -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - - :return: The {{name}} of this {{classname}}. # noqa: E501 - :rtype: {{dataType}} - """ - return self._{{name}} - - @{{name}}.setter - def {{name}}( - self, - {{name}}): - """Sets the {{name}} of this {{classname}}. - -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - - :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 - :type: {{dataType}} - """ -{{^isNullable}} -{{#required}} - if {{name}} is None: - raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 -{{/required}} -{{/isNullable}} -{{#isEnum}} -{{#isContainer}} - allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 -{{#isListContainer}} - if not set({{{name}}}).issubset(set(allowed_values)): - raise ValueError( - "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) -{{/isListContainer}} -{{#isMapContainer}} - if not set({{{name}}}.keys()).issubset(set(allowed_values)): - raise ValueError( - "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) -{{/isMapContainer}} -{{/isContainer}} -{{^isContainer}} - allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 - if {{{name}}} not in allowed_values: - raise ValueError( - "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 - .format({{{name}}}, allowed_values) - ) -{{/isContainer}} -{{/isEnum}} -{{^isEnum}} -{{#hasValidation}} -{{#maxLength}} - if {{name}} is not None and len({{name}}) > {{maxLength}}: - raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 -{{/maxLength}} -{{#minLength}} - if {{name}} is not None and len({{name}}) < {{minLength}}: - raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 -{{/minLength}} -{{#maximum}} - if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 -{{/maximum}} -{{#minimum}} - if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 -{{/minimum}} -{{#pattern}} - if {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 - raise ValueError(r"Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 -{{/pattern}} -{{#maxItems}} - if {{name}} is not None and len({{name}}) > {{maxItems}}: - raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 -{{/maxItems}} -{{#minItems}} - if {{name}} is not None and len({{name}}) < {{minItems}}: - raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 -{{/minItems}} -{{/hasValidation}} -{{/isEnum}} - - self._{{name}} = ( - {{name}}) - -{{/vars}} -{{#discriminator}} - def get_real_child_model(self, data): - """Returns the real base class specified by the discriminator""" - discriminator_key = self.attribute_map[self.discriminator] - discriminator_value = data[discriminator_key] - return self.discriminator_value_class_map.get(discriminator_value) - -{{/discriminator}} - def to_dict(self): - """Returns the model properties as a dict""" - result = {} - - for attr, _ in six.iteritems(self.openapi_types): - value = getattr(self, attr) - if isinstance(value, list): - result[attr] = list(map( - lambda x: x.to_dict() if hasattr(x, "to_dict") else x, - value - )) - elif hasattr(value, "to_dict"): - result[attr] = value.to_dict() - elif isinstance(value, dict): - result[attr] = dict(map( - lambda item: (item[0], item[1].to_dict()) - if hasattr(item[1], "to_dict") else item, - value.items() - )) - else: - result[attr] = value - - return result - - def to_str(self): - """Returns the string representation of the model""" - return pprint.pformat(self.to_dict()) - - def __repr__(self): - """For `print` and `pprint`""" - return self.to_str() - - def __eq__(self, other): - """Returns true if both objects are equal""" - if not isinstance(other, {{classname}}): - return False - - return self.__dict__ == other.__dict__ - - def __ne__(self, other): - """Returns true if both objects are not equal""" - return not self == other +{{/interfaces}} {{/model}} {{/models}} diff --git a/python-experimental/model_templates/classvar_allowed.mustache b/python-experimental/model_templates/classvar_allowed.mustache new file mode 100644 index 0000000000..6ed39521f6 --- /dev/null +++ b/python-experimental/model_templates/classvar_allowed.mustache @@ -0,0 +1,16 @@ + allowed_values = { +{{#vars}} +{{#isEnum}} + ('{{name}}',): { +{{#isNullable}} + 'None': None, +{{/isNullable}} +{{#allowableValues}} +{{#enumVars}} + '{{name}}': {{{value}}}{{^-last}},{{/-last}} +{{/enumVars}} +{{/allowableValues}} + }, +{{/isEnum}} +{{/vars}} + } \ No newline at end of file diff --git a/python-experimental/model_templates/classvar_openapi_validations.mustache b/python-experimental/model_templates/classvar_openapi_validations.mustache new file mode 100644 index 0000000000..7e89f83ef2 --- /dev/null +++ b/python-experimental/model_templates/classvar_openapi_validations.mustache @@ -0,0 +1,25 @@ + openapi_types = { +{{#vars}} + '{{name}}': '{{{dataType}}}'{{#hasMore}},{{/hasMore}} +{{/vars}} + } + + validations = { +{{#vars}} +{{#hasValidation}} + ('{{name}}',): { +{{#maxLength}} + 'max_length': {{maxLength}},{{/maxLength}}{{#minLength}} + 'min_length': {{minLength}},{{/minLength}}{{#maxItems}} + 'max_items': {{maxItems}},{{/maxItems}}{{#minItems}} + 'min_items': {{minItems}},{{/minItems}}{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + },{{/pattern}} + }, +{{/hasValidation}} +{{/vars}} + } \ No newline at end of file diff --git a/python-experimental/model_templates/docstring_allowed.mustache b/python-experimental/model_templates/docstring_allowed.mustache new file mode 100644 index 0000000000..ab20932b28 --- /dev/null +++ b/python-experimental/model_templates/docstring_allowed.mustache @@ -0,0 +1,4 @@ + allowed_values (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + with a capitalized key describing the allowed value and an allowed + value. These dicts store the allowed enum values. \ No newline at end of file diff --git a/python-experimental/model_templates/docstring_openapi_validations.mustache b/python-experimental/model_templates/docstring_openapi_validations.mustache new file mode 100644 index 0000000000..46dc1afefc --- /dev/null +++ b/python-experimental/model_templates/docstring_openapi_validations.mustache @@ -0,0 +1,7 @@ + openapi_types (dict): The key is attribute name + and the value is attribute type. + validations (dict): The key is the tuple path to the attribute + and the for var_name this is (var_name,). The value is a dict + that stores validations for max_length, min_length, max_items, + min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, + inclusive_minimum, and regex. \ No newline at end of file diff --git a/python-experimental/model_templates/methods_init_properties.mustache b/python-experimental/model_templates/methods_init_properties.mustache new file mode 100644 index 0000000000..447aa22cac --- /dev/null +++ b/python-experimental/model_templates/methods_init_properties.mustache @@ -0,0 +1,76 @@ + def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 + """{{classname}} - a model defined in OpenAPI""" # noqa: E501 +{{#vars}}{{#-first}} +{{/-first}} + self._{{name}} = None +{{/vars}} + self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} +{{#vars}}{{#-first}} +{{/-first}} +{{#required}} + self.{{name}} = {{name}} +{{/required}} +{{^required}} +{{#isNullable}} + self.{{name}} = {{name}} +{{/isNullable}} +{{^isNullable}} + if {{name}} is not None: + self.{{name}} = ( + {{name}} + ) +{{/isNullable}} +{{/required}} +{{/vars}} +{{#vars}} + + @property + def {{name}}(self): + """Gets the {{name}} of this {{classname}}. # noqa: E501 + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :return: The {{name}} of this {{classname}}. # noqa: E501 + :rtype: {{dataType}} + """ + return self._{{name}} + + @{{name}}.setter + def {{name}}(self, {{name}}): # noqa: E501 + """Sets the {{name}} of this {{classname}}. + +{{#description}} + {{{description}}} # noqa: E501 +{{/description}} + + :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 + :type: {{dataType}} + """ +{{^isNullable}} +{{#required}} + if {{name}} is None: + raise ApiValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 +{{/required}} +{{/isNullable}} +{{#isEnum}} + check_allowed_values( + self.allowed_values, + ('{{name}}',), + {{name}}, + self.validations + ) +{{/isEnum}} +{{#hasValidation}} + check_validations( + self.validations, + ('{{name}}',), + {{name}} + ) +{{/hasValidation}} + + self._{{name}} = ( + {{name}} + ) +{{/vars}} \ No newline at end of file diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache new file mode 100644 index 0000000000..bd1eaddcb4 --- /dev/null +++ b/python-experimental/model_templates/model_normal.mustache @@ -0,0 +1,83 @@ +class {{classname}}(ModelNormal): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: +{{> python-experimental/model_templates/docstring_allowed }} + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. +{{> python-experimental/model_templates/docstring_openapi_validations }} + """ + +{{> python-experimental/model_templates/classvar_allowed }} + + attribute_map = { +{{#vars}} + '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} # noqa: E501 +{{/vars}} + } +{{#discriminator}} + + discriminator_value_class_map = { + {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, + {{/-last}}{{/children}} + } +{{/discriminator}} + +{{> python-experimental/model_templates/classvar_openapi_validations }} + +{{> python-experimental/model_templates/methods_init_properties }} +{{#discriminator}} + def get_real_child_model(self, data): + """Returns the real base class specified by the discriminator""" + discriminator_key = self.attribute_map[self.discriminator] + discriminator_value = data[discriminator_key] + return self.discriminator_value_class_map.get(discriminator_value) + +{{/discriminator}} + def to_dict(self): + """Returns the model properties as a dict""" + result = {} + + for attr, _ in six.iteritems(self.openapi_types): + value = getattr(self, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + value + )) + elif hasattr(value, "to_dict"): + result[attr] = value.to_dict() + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], item[1].to_dict()) + if hasattr(item[1], "to_dict") else item, + value.items() + )) + else: + result[attr] = value + + return result + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other \ No newline at end of file diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache new file mode 100644 index 0000000000..94ad6336f9 --- /dev/null +++ b/python-experimental/model_templates/model_simple.mustache @@ -0,0 +1,34 @@ +class {{classname}}(ModelSimple): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: +{{> python-experimental/model_templates/docstring_allowed }} +{{> python-experimental/model_templates/docstring_openapi_validations }} + """ + +{{> python-experimental/model_templates/classvar_allowed }} + +{{> python-experimental/model_templates/classvar_openapi_validations }} + +{{> python-experimental/model_templates/methods_init_properties }} + def to_str(self): + """Returns the string representation of the model""" + return str(self._value) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, {{classname}}): + return False + + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache new file mode 100644 index 0000000000..c251879b10 --- /dev/null +++ b/python-experimental/model_utils.mustache @@ -0,0 +1,175 @@ +# coding: utf-8 + +{{>partial_header}} +import re + +from {{packageName}}.exceptions import ApiValueError + + +def check_allowed_values(allowed_values, input_variable_path, input_values, + validations): + """Raises an exception if the input_values are not allowed + + Args: + allowed_values (dict): the allowed_values dict + input_variable_path (tuple): the path to the input variable + input_values (list/str/int/float/date/datetime): the values that we + are checking to see if they are in allowed_values + validations (dict): the validations dict + """ + min_collection_length = ( + validations.get(input_variable_path, {}).get('min_length') or + validations.get(input_variable_path, {}).get('min_items', 0)) + these_allowed_values = list(allowed_values[input_variable_path].values()) + if (isinstance(input_values, list) + and len(input_values) > min_collection_length + and not set(input_values).issubset( + set(these_allowed_values))): + invalid_values = ", ".join( + map(str, set(input_values) - set(these_allowed_values))), + raise ApiValueError( + "Invalid values for `%s` [%s], must be a subset of [%s]" % + ( + input_variable_path[0], + invalid_values, + ", ".join(map(str, these_allowed_values)) + ) + ) + elif (isinstance(input_values, dict) + and len(input_values) > min_collection_length + and not set( + input_values.keys()).issubset(set(these_allowed_values))): + invalid_values = ", ".join( + map(str, set(input_values.keys()) - set(these_allowed_values))) + raise ApiValueError( + "Invalid keys in `%s` [%s], must be a subset of [%s]" % + ( + input_variable_path[0], + invalid_values, + ", ".join(map(str, these_allowed_values)) + ) + ) + elif (not isinstance(input_values, (list, dict)) + and input_values not in these_allowed_values): + raise ApiValueError( + "Invalid value for `%s` (%s), must be one of %s" % + ( + input_variable_path[0], + input_values, + these_allowed_values + ) + ) + + +def check_validations(validations, input_variable_path, input_values): + """Raises an exception if the input_values are invalid + + Args: + validations (dict): the validation dictionary + input_variable_path (tuple): the path to the input variable + input_values (list/str/int/float/date/datetime): the values that we + are checking + """ + current_validations = validations[input_variable_path] + if ('max_length' in current_validations and + len(input_values) > current_validations['max_length']): + raise ApiValueError( + "Invalid value for `%s`, length must be less than or equal to " + "`%s`" % ( + input_variable_path[0], + current_validations['max_length'] + ) + ) + + if ('min_length' in current_validations and + len(input_values) < current_validations['min_length']): + raise ApiValueError( + "Invalid value for `%s`, length must be greater than or equal to " + "`%s`" % ( + input_variable_path[0], + current_validations['min_length'] + ) + ) + + if ('max_items' in current_validations and + len(input_values) > current_validations['max_items']): + raise ApiValueError( + "Invalid value for `%s`, number of items must be less than or " + "equal to `%s`" % ( + input_variable_path[0], + current_validations['max_items'] + ) + ) + + if ('min_items' in current_validations and + len(input_values) < current_validations['min_items']): + raise ValueError( + "Invalid value for `%s`, number of items must be greater than or " + "equal to `%s`" % ( + input_variable_path[0], + current_validations['min_items'] + ) + ) + + if ('exclusive_maximum' in current_validations and + input_values >= current_validations['exclusive_maximum']): + raise ApiValueError( + "Invalid value for `%s`, must be a value less than `%s`" % ( + input_variable_path[0], + current_validations['exclusive_maximum'] + ) + ) + + if ('inclusive_maximum' in current_validations and + input_values > current_validations['inclusive_maximum']): + raise ApiValueError( + "Invalid value for `%s`, must be a value less than or equal to " + "`%s`" % ( + input_variable_path[0], + current_validations['inclusive_maximum'] + ) + ) + + if ('exclusive_minimum' in current_validations and + input_values <= current_validations['exclusive_minimum']): + raise ApiValueError( + "Invalid value for `%s`, must be a value greater than `%s`" % + ( + input_variable_path[0], + current_validations['exclusive_maximum'] + ) + ) + + if ('inclusive_minimum' in current_validations and + input_values < current_validations['inclusive_minimum']): + raise ApiValueError( + "Invalid value for `%s`, must be a value greater than or equal " + "to `%s`" % ( + input_variable_path[0], + current_validations['inclusive_minimum'] + ) + ) + flags = current_validations.get('regex', {}).get('flags', 0) + if ('regex' in current_validations and + not re.search(current_validations['regex']['pattern'], + input_values, flags=flags)): + raise ApiValueError( + r"Invalid value for `%s`, must be a follow pattern or equal to " + r"`%s` with flags=`%s`" % ( + input_variable_path[0], + current_validations['regex']['pattern'], + flags + ) + ) + + +class ModelSimple(object): + # the parent class of models whose type != object in their swagger/openapi + # spec + pass + + +class ModelNormal(object): + # the parent class of models whose type == object in their swagger/openapi + # spec + pass From ea771c31fd32cf9928b4e4e0b7aaa2c22bdf8e5c Mon Sep 17 00:00:00 2001 From: Pete Savage Date: Wed, 9 Oct 2019 04:16:34 +0100 Subject: [PATCH 051/180] Fixed Readonly Docs for python (#4085) --- model_doc.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model_doc.mustache b/model_doc.mustache index 0216a3372c..71c106fdc5 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} +{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} {{/vars}} [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) From 34d64ab00f6f902d8ef795420d094cadbb333df4 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 9 Oct 2019 15:16:22 +0800 Subject: [PATCH 052/180] Fix readonly with isReadOnly (#4102) * fix readonly * update samples --- python-experimental/model_doc.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index b6e1b263fc..16592869b7 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -3,9 +3,9 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#requiredVars}}{{^defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#readOnly}}[readonly] {{/readOnly}} -{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} -{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{#requiredVars}}{{^defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} +{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} +{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} {{/optionalVars}} [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) From 98bf60846ba40beadea3cd1dc255f32782a2c713 Mon Sep 17 00:00:00 2001 From: Arun Date: Wed, 16 Oct 2019 12:45:14 +0530 Subject: [PATCH 053/180] Skip adding None value in query parameters (#4161) --- api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api.mustache b/api.mustache index 590299dc5f..9ed3340627 100644 --- a/api.mustache +++ b/api.mustache @@ -182,7 +182,7 @@ class {{classname}}(object): query_params = [] {{#queryParams}} - if '{{paramName}}' in local_var_params: + if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] is not None: # noqa: E501 query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isListContainer}} # noqa: E501 collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 {{/queryParams}} From e355121075c7174062db528eb36e7bc9a1c6d5f5 Mon Sep 17 00:00:00 2001 From: Arun Date: Wed, 16 Oct 2019 13:04:22 +0530 Subject: [PATCH 054/180] [python] Remove post_params and body from OPTIONS request (#4163) * Remove post_params and body from OPTIONS * Empty commit to retrigger build --- api_client.mustache | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 768b8d973f..546313cc19 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -379,10 +379,8 @@ class ApiClient(object): return self.rest_client.OPTIONS(url, query_params=query_params, headers=headers, - post_params=post_params, _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) + _request_timeout=_request_timeout) elif method == "POST": return self.rest_client.POST(url, query_params=query_params, From 0779caf2d121dca1ff35d0b784e44c710f0cdce5 Mon Sep 17 00:00:00 2001 From: Arun Date: Wed, 16 Oct 2019 13:14:04 +0530 Subject: [PATCH 055/180] [python] Add option to skip client validations (#4137) * Adds options to skip client side validations * Runs petstore.sh * Correct typo in variable name * Consistent code styling * Rerun petstore.sh * Change position of local_vars_configuration * Make code pep8 compliant --- api.mustache | 26 ++++++++++++------------ api_client.mustache | 1 + configuration.mustache | 2 ++ model.mustache | 45 +++++++++++++++++++++++++++++------------- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/api.mustache b/api.mustache index 9ed3340627..f1a110bd47 100644 --- a/api.mustache +++ b/api.mustache @@ -126,8 +126,8 @@ class {{classname}}(object): {{^isNullable}} {{#required}} # verify the required parameter '{{paramName}}' is set - if ('{{paramName}}' not in local_var_params or - local_var_params['{{paramName}}'] is None): + if self.api_client.client_side_validation and ('{{paramName}}' not in local_var_params or # noqa: E501 + local_var_params['{{paramName}}'] is None): # noqa: E501 raise ApiValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 {{/required}} {{/isNullable}} @@ -136,35 +136,35 @@ class {{classname}}(object): {{#allParams}} {{#hasValidation}} {{#maxLength}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) > {{maxLength}}): + if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 + len(local_var_params['{{paramName}}']) > {{maxLength}}): # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 {{/maxLength}} {{#minLength}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) < {{minLength}}): + if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 + len(local_var_params['{{paramName}}']) < {{minLength}}): # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 {{/minLength}} {{#maximum}} - if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 {{/maximum}} {{#minimum}} - if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} - if '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) > {{maxItems}}): + if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 + len(local_var_params['{{paramName}}']) > {{maxItems}}): # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 {{/maxItems}} {{#minItems}} - if ('{{paramName}}' in local_var_params and - len(local_var_params['{{paramName}}']) < {{minItems}}): + if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 + len(local_var_params['{{paramName}}']) < {{minItems}}): # noqa: E501 raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 {{/minItems}} {{/hasValidation}} diff --git a/api_client.mustache b/api_client.mustache index 546313cc19..63dd91ebb5 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -72,6 +72,7 @@ class ApiClient(object): self.cookie = cookie # Set default User-Agent. self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' + self.client_side_validation = configuration.client_side_validation def __del__(self): if self._pool: diff --git a/configuration.mustache b/configuration.mustache index 2afcb7478e..9677031a8c 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -149,6 +149,8 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): self.retries = None """Adding retries to override urllib3 default value 3 """ + # Disable client side validation + self.client_side_validation = True @property def logger_file(self): diff --git a/model.mustache b/model.mustache index 16c8dadbf6..e2c39f3d6b 100644 --- a/model.mustache +++ b/model.mustache @@ -7,6 +7,8 @@ import re # noqa: F401 import six +from {{packageName}}.configuration import Configuration + {{#models}} {{#model}} @@ -51,8 +53,11 @@ class {{classname}}(object): } {{/discriminator}} - def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 + def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}, local_vars_configuration=None): # noqa: E501 """{{classname}} - a model defined in OpenAPI""" # noqa: E501 + if local_vars_configuration is None: + local_vars_configuration = Configuration() + self.local_vars_configuration = local_vars_configuration {{#vars}}{{#-first}} {{/-first}} self._{{name}} = None @@ -101,7 +106,7 @@ class {{classname}}(object): """ {{^isNullable}} {{#required}} - if {{name}} is None: + if self.local_vars_configuration.client_side_validation and {{name}} is None: # noqa: E501 raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 {{/required}} {{/isNullable}} @@ -109,7 +114,8 @@ class {{classname}}(object): {{#isContainer}} allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 {{#isListContainer}} - if not set({{{name}}}).issubset(set(allowed_values)): + if (self.local_vars_configuration.client_side_validation and + not set({{{name}}}).issubset(set(allowed_values))): raise ValueError( "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 @@ -117,7 +123,8 @@ class {{classname}}(object): ) {{/isListContainer}} {{#isMapContainer}} - if not set({{{name}}}.keys()).issubset(set(allowed_values)): + if (self.local_vars_configuration.client_side_validation and + not set({{{name}}}.keys()).issubset(set(allowed_values))): raise ValueError( "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 @@ -127,7 +134,7 @@ class {{classname}}(object): {{/isContainer}} {{^isContainer}} allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 - if {{{name}}} not in allowed_values: + if self.local_vars_configuration.client_side_validation and {{{name}}} not in allowed_values: # noqa: E501 raise ValueError( "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 .format({{{name}}}, allowed_values) @@ -137,31 +144,38 @@ class {{classname}}(object): {{^isEnum}} {{#hasValidation}} {{#maxLength}} - if {{name}} is not None and len({{name}}) > {{maxLength}}: + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and len({{name}}) > {{maxLength}}): raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 {{/maxLength}} {{#minLength}} - if {{name}} is not None and len({{name}}) < {{minLength}}: + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and len({{name}}) < {{minLength}}): raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 {{/minLength}} {{#maximum}} - if {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}): # noqa: E501 raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 {{/maximum}} {{#minimum}} - if {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}): # noqa: E501 raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 {{/minimum}} {{#pattern}} - if {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}})): # noqa: E501 raise ValueError(r"Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 {{/pattern}} {{#maxItems}} - if {{name}} is not None and len({{name}}) > {{maxItems}}: + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and len({{name}}) > {{maxItems}}): raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 {{/maxItems}} {{#minItems}} - if {{name}} is not None and len({{name}}) < {{minItems}}: + if (self.local_vars_configuration.client_side_validation and + {{name}} is not None and len({{name}}) < {{minItems}}): raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 {{/minItems}} {{/hasValidation}} @@ -215,10 +229,13 @@ class {{classname}}(object): if not isinstance(other, {{classname}}): return False - return self.__dict__ == other.__dict__ + return self.to_dict() == other.to_dict() def __ne__(self, other): """Returns true if both objects are not equal""" - return not self == other + if not isinstance(other, {{classname}}): + return True + + return self.to_dict() != other.to_dict() {{/model}} {{/models}} From c93605affafee5e042029859da9c06c8042e6f23 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 17 Oct 2019 02:34:04 +0800 Subject: [PATCH 056/180] [Python] Minor fix to code format (#4172) * test python e501 fix * 2 spaces * fix format with noqa: E501 * fix format, update samples --- model.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model.mustache b/model.mustache index e2c39f3d6b..17264bb46b 100644 --- a/model.mustache +++ b/model.mustache @@ -115,7 +115,7 @@ class {{classname}}(object): allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 {{#isListContainer}} if (self.local_vars_configuration.client_side_validation and - not set({{{name}}}).issubset(set(allowed_values))): + not set({{{name}}}).issubset(set(allowed_values))): # noqa: E501 raise ValueError( "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 @@ -124,7 +124,7 @@ class {{classname}}(object): {{/isListContainer}} {{#isMapContainer}} if (self.local_vars_configuration.client_side_validation and - not set({{{name}}}.keys()).issubset(set(allowed_values))): + not set({{{name}}}.keys()).issubset(set(allowed_values))): # noqa: E501 raise ValueError( "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 From cc11b6ed125f2912b98d10699ad1e3eb7ffa4df1 Mon Sep 17 00:00:00 2001 From: Arun Date: Thu, 24 Oct 2019 14:58:29 +0530 Subject: [PATCH 057/180] [python] Add ability to get allowed values (#4138) * Add function to get list of allowed values * [python] Add function to get list of allowed values * Remove temporary variable * Remove static method and use a variable * Remove classname --- model.mustache | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/model.mustache b/model.mustache index 17264bb46b..70f6e7489a 100644 --- a/model.mustache +++ b/model.mustache @@ -27,6 +27,10 @@ class {{classname}}(object): {{/-last}} {{/enumVars}}{{/allowableValues}} +{{#allowableValues}} + allowable_values = [{{#enumVars}}{{name}}{{^-last}}, {{/-last}}{{/enumVars}}] # noqa: E501 + +{{/allowableValues}} """ Attributes: openapi_types (dict): The key is attribute name From 62480238733d834592f3b98e379f6ecc88d2ed30 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 28 Oct 2019 06:24:31 -0700 Subject: [PATCH 058/180] [Python-experimental] types now classes, adds additionalProperties handling (#4154) * Changes python-experimental types to classes, adds additionalalproperties handling Adds model_utils update, updates model.mustache Updates api.mustache and uses model_to_dict in model_normal.mustache Updates requirements.mustache for PythonClientExperimental Passes through check_type when deserializing models Converts types from strings to classes in PythonClientExperimentalCodegen.java and PythonTest.java Creates PythonClientExperimentalTest.java Updates toInstantiationType to use ModelUtils.xxx Corrects docstring descriptions of response_type Updates python-experimental typing, partially fixes deserialization tests Adds fixes for some of the deserialization tests Fixes deserialization tests Switches model teplates to use allVars so allof props will be included Fixes tests.test_enum_arrays Fixes test_to_str Adds additional_properties_type, fixes teast_todict in test_map_test.py Correctly check the type of _request_timeout values Fixes test_upload_file test Turns off coercion when instantiating model types with client data Updates file handling to input and output an open file object Fixes linting errors Adds fixes for python2 tests, linting fixes Adds additionalproperties to docs + tests Regenerates python-experimatal client * Regenerates python-experimental client * Updates windows python-experimental bat file * Fixes addModelImport so client generation will work with the v2 spec * Reverts PythonClientCodegen.java * Acutally revert PythonClientCodegen.java * Updates the sample example for file_type in docs * Silences line too long error for python models so CI tests pass * Fixes handling of file uploads, adds tests for uploading files * Removes comment * Fixes mock installation in python2 * Limit mock addition to python-experimental test requirements only * Removes SmartBear copyright line --- python-experimental/api.mustache | 121 ++- python-experimental/api_client.mustache | 327 +++----- python-experimental/model.mustache | 21 +- python-experimental/model_doc.mustache | 18 +- .../model_templates/classvar_allowed.mustache | 6 +- .../classvar_openapi_validations.mustache | 43 +- .../docstring_openapi_validations.mustache | 4 +- .../methods_init_properties.mustache | 170 ++-- .../model_templates/model_normal.mustache | 56 +- .../model_templates/model_simple.mustache | 16 +- python-experimental/model_utils.mustache | 735 +++++++++++++++++- python-experimental/requirements.mustache | 6 + python-experimental/setup.mustache | 45 ++ .../test-requirements.mustache | 13 + requirements.mustache | 1 + 15 files changed, 1194 insertions(+), 388 deletions(-) create mode 100644 python-experimental/requirements.mustache create mode 100644 python-experimental/setup.mustache create mode 100644 python-experimental/test-requirements.mustache diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index dd650b37d7..651559cf4f 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -14,10 +14,20 @@ from {{packageName}}.exceptions import ( ApiTypeError, ApiValueError ) -from {{packageName}}.model_utils import ( +from {{packageName}}.model_utils import ( # noqa: F401 check_allowed_values, - check_validations + check_validations, + date, + datetime, + file_type, + int, + none_type, + str, + validate_and_convert_types ) +{{#imports}} +{{{import}}} +{{/imports}} {{#operations}} @@ -51,24 +61,51 @@ class {{classname}}(object): >>> result = thread.get() :param async_req bool: execute request asynchronously + Default is False. {{#allParams}} :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} {{/allParams}} :param _return_http_data_only: response data without head status - code and headers + code and headers. Default is True. :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. + Default is None. + :param _check_input_type: boolean specifying if type checking + should be done one the data sent to the server. + Default is True. + :param _check_return_type: boolean specifying if type checking + should be done one the data received from the server. + Default is True. + :param _host_index: integer specifying the index of the server + that we want to use. + Default is 0. :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} If the method is called asynchronously, returns the request thread. """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) kwargs['_return_http_data_only'] = kwargs.get( '_return_http_data_only', True ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index', 0) {{#requiredParams}} kwargs['{{paramName}}'] = {{paramName}} {{/requiredParams}} @@ -76,7 +113,7 @@ class {{classname}}(object): self.{{operationId}} = Endpoint( settings={ - 'response_type': {{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, + 'response_type': {{#returnType}}({{{returnType}}},){{/returnType}}{{^returnType}}None{{/returnType}}, {{#authMethods}} {{#-first}} 'auth': [ @@ -178,7 +215,7 @@ class {{classname}}(object): }, 'openapi_types': { {{#allParams}} - '{{paramName}}': '{{dataType}}', + '{{paramName}}': ({{{dataType}}},), {{/allParams}} }, 'attribute_map': { @@ -237,7 +274,7 @@ class Endpoint(object): Args: settings (dict): see below key value pairs - 'response_type' (str): response type + 'response_type' (tuple/None): response type 'auth' (list): a list of auth type keys 'endpoint_path' (str): the endpoint path 'operation_id' (str): endpoint string identifier @@ -273,11 +310,24 @@ class Endpoint(object): '_host_index', '_preload_content', '_request_timeout', - '_return_http_data_only' + '_return_http_data_only', + '_check_input_type', + '_check_return_type' ]) + self.params_map['nullable'].extend(['_request_timeout']) self.validations = root_map['validations'] self.allowed_values = root_map['allowed_values'] self.openapi_types = root_map['openapi_types'] + extra_types = { + 'async_req': (bool,), + '_host_index': (int,), + '_preload_content': (bool,), + '_request_timeout': (none_type, int, (int,), [int]), + '_return_http_data_only': (bool,), + '_check_input_type': (bool,), + '_check_return_type': (bool,) + } + self.openapi_types.update(extra_types) self.attribute_map = root_map['attribute_map'] self.location_map = root_map['location_map'] self.collection_format_map = root_map['collection_format_map'] @@ -291,8 +341,7 @@ class Endpoint(object): check_allowed_values( self.allowed_values, (param,), - kwargs[param], - self.validations + kwargs[param] ) for param in self.params_map['validation']: @@ -303,6 +352,20 @@ class Endpoint(object): kwargs[param] ) + if kwargs['_check_input_type'] is False: + return + + for key, value in six.iteritems(kwargs): + fixed_val = validate_and_convert_types( + value, + self.openapi_types[key], + [key], + False, + kwargs['_check_input_type'], + configuration=self.api_client.configuration + ) + kwargs[key] = fixed_val + def __gather_params(self, kwargs): params = { 'body': None, @@ -316,14 +379,20 @@ class Endpoint(object): for param_name, param_value in six.iteritems(kwargs): param_location = self.location_map.get(param_name) + if param_location is None: + continue if param_location: if param_location == 'body': params['body'] = param_value continue base_name = self.attribute_map[param_name] if (param_location == 'form' and - self.openapi_types[param_name] == 'file'): - param_location = 'file' + self.openapi_types[param_name] == (file_type,)): + params['file'][param_name] = [param_value] + elif (param_location == 'form' and + self.openapi_types[param_name] == ([file_type],)): + # param_value is already a list + params['file'][param_name] = param_value elif param_location in {'form', 'query'}: param_value_full = (base_name, param_value) params[param_location].append(param_value_full) @@ -348,20 +417,15 @@ class Endpoint(object): def call_with_http_info(self, **kwargs): - if kwargs.get('_host_index') and self.settings['servers']: - _host_index = kwargs.get('_host_index') - try: - _host = self.settings['servers'][_host_index] - except IndexError: + try: + _host = self.settings['servers'][kwargs['_host_index']] + except IndexError: + if self.settings['servers']: raise ApiValueError( "Invalid host index. Must be 0 <= index < %s" % len(self.settings['servers']) ) - else: - try: - _host = self.settings['servers'][0] - except IndexError: - _host = None + _host = None for key, value in six.iteritems(kwargs): if key not in self.params_map['all']: @@ -370,7 +434,11 @@ class Endpoint(object): " to method `%s`" % (key, self.settings['operation_id']) ) - if key not in self.params_map['nullable'] and value is None: + # only throw this nullable ApiValueError if _check_input_type + # is False, if _check_input_type==True we catch this case + # in self.__validate_inputs + if (key not in self.params_map['nullable'] and value is None + and kwargs['_check_input_type'] is False): raise ApiValueError( "Value may not be None for non-nullable parameter `%s`" " when calling `%s`" % @@ -409,9 +477,10 @@ class Endpoint(object): files=params['file'], response_type=self.settings['response_type'], auth_settings=self.settings['auth'], - async_req=kwargs.get('async_req'), - _return_http_data_only=kwargs.get('_return_http_data_only'), - _preload_content=kwargs.get('_preload_content', True), - _request_timeout=kwargs.get('_request_timeout'), + async_req=kwargs['async_req'], + _check_type=kwargs['_check_return_type'], + _return_http_data_only=kwargs['_return_http_data_only'], + _preload_content=kwargs['_preload_content'], + _request_timeout=kwargs['_request_timeout'], _host=_host, collection_formats=params['collection_format']) diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 0f02b445df..aec1ef3753 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -2,14 +2,10 @@ {{>partial_header}} from __future__ import absolute_import -import datetime -import inspect import json import mimetypes from multiprocessing.pool import ThreadPool import os -import re -import tempfile # python 2 and python 3 compatibility library import six @@ -18,14 +14,20 @@ from six.moves.urllib.parse import quote import tornado.gen {{/tornado}} -import {{modelPackage}} from {{packageName}} import rest from {{packageName}}.configuration import Configuration +from {{packageName}}.exceptions import ApiValueError from {{packageName}}.model_utils import ( ModelNormal, - ModelSimple + ModelSimple, + date, + datetime, + deserialize_file, + file_type, + model_to_dict, + str, + validate_and_convert_types ) -from {{packageName}}.exceptions import ApiValueError class ApiClient(object): @@ -50,17 +52,11 @@ class ApiClient(object): to the API. More threads means more concurrent API requests. """ - PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types - NATIVE_TYPES_MAPPING = { - 'int': int, - 'long': int if six.PY3 else long, # noqa: F821 - 'float': float, - 'str': str, - 'bool': bool, - 'date': datetime.date, - 'datetime': datetime.datetime, - 'object': object, - } + # six.binary_type python2=str, python3=bytes + # six.text_type python2=unicode, python3=str + PRIMITIVE_TYPES = ( + (float, bool, six.binary_type, six.text_type) + six.integer_types + ) _pool = None def __init__(self, configuration=None, header_name=None, header_value=None, @@ -113,7 +109,8 @@ class ApiClient(object): query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None): + _preload_content=True, _request_timeout=None, _host=None, + _check_type=None): config = self.configuration @@ -180,7 +177,11 @@ class ApiClient(object): if _preload_content: # deserialize response data if response_type: - return_data = self.deserialize(response_data, response_type) + return_data = self.deserialize( + response_data, + response_type, + _check_type + ) else: return_data = None @@ -223,93 +224,73 @@ class ApiClient(object): elif isinstance(obj, tuple): return tuple(self.sanitize_for_serialization(sub_obj) for sub_obj in obj) - elif isinstance(obj, (datetime.datetime, datetime.date)): + elif isinstance(obj, (datetime, date)): return obj.isoformat() if isinstance(obj, dict): obj_dict = obj elif isinstance(obj, ModelNormal): - # Convert model obj to dict except - # attributes `openapi_types`, `attribute_map` - # and attributes which value is not None. + # Convert model obj to dict # Convert attribute name to json key in - # model definition for request. - obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) - for attr, _ in six.iteritems(obj.openapi_types) - if getattr(obj, attr) is not None} + # model definition for request + obj_dict = model_to_dict(obj, serialize=True) elif isinstance(obj, ModelSimple): return self.sanitize_for_serialization(obj.value) return {key: self.sanitize_for_serialization(val) for key, val in six.iteritems(obj_dict)} - def deserialize(self, response, response_type): + def deserialize(self, response, response_type, _check_type): """Deserializes response into an object. :param response: RESTResponse object to be deserialized. - :param response_type: class literal for - deserialized object, or string of class name. + :param response_type: For the response, a tuple containing: + valid classes + a list containing valid classes (for list schemas) + a dict containing a tuple of valid classes as the value + Example values: + (str,) + (Pet,) + (float, none_type) + ([int, none_type],) + ({str: (bool, str, int, float, date, datetime, str, none_type)},) + :param _check_type: boolean, whether to check the types of the data + received from the server :return: deserialized object. """ # handle file downloading # save response body into a tmp file and return the instance - if response_type == "file": - return self.__deserialize_file(response) + if response_type == (file_type,): + content_disposition = response.getheader("Content-Disposition") + return deserialize_file(response.data, self.configuration, + content_disposition=content_disposition) # fetch data from response object try: - data = json.loads(response.data) + received_data = json.loads(response.data) except ValueError: - data = response.data - - return self.__deserialize(data, response_type) - - def __deserialize(self, data, klass): - """Deserializes dict, list, str into an object. - - :param data: dict, list or str. - :param klass: class literal, or string of class name. - - :return: object. - """ - if data is None: - return None - - if type(klass) == str: - if klass.startswith('list['): - sub_kls = re.match(r'list\[(.*)\]', klass).group(1) - return [self.__deserialize(sub_data, sub_kls) - for sub_data in data] - - if klass.startswith('dict('): - sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) - return {k: self.__deserialize(v, sub_kls) - for k, v in six.iteritems(data)} - - # convert str to class - if klass in self.NATIVE_TYPES_MAPPING: - klass = self.NATIVE_TYPES_MAPPING[klass] - else: - klass = getattr({{modelPackage}}, klass) - - if klass in self.PRIMITIVE_TYPES: - return self.__deserialize_primitive(data, klass) - elif klass == object: - return self.__deserialize_object(data) - elif klass == datetime.date: - return self.__deserialize_date(data) - elif klass == datetime.datetime: - return self.__deserialize_datatime(data) - else: - return self.__deserialize_model(data, klass) + received_data = response.data + + # store our data under the key of 'received_data' so users have some + # context if they are deserializing a string and the data type is wrong + deserialized_data = validate_and_convert_types( + received_data, + response_type, + ['received_data'], + True, + _check_type, + configuration=self.configuration + ) + return deserialized_data def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, async_req=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None): + _preload_content=True, _request_timeout=None, _host=None, + _check_type=None): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -324,9 +305,18 @@ class ApiClient(object): :param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`. :param auth_settings list: Auth Settings names for the request. - :param response: Response data type. - :param files dict: key -> filename, value -> filepath, - for `multipart/form-data`. + :param response_type: For the response, a tuple containing: + valid classes + a list containing valid classes (for list schemas) + a dict containing a tuple of valid classes as the value + Example values: + (str,) + (Pet,) + (float, none_type) + ([int, none_type],) + ({str: (bool, str, int, float, date, datetime, str, none_type)},) + :param files dict: key -> field name, value -> a list of open file + objects for `multipart/form-data`. :param async_req bool: execute request asynchronously :param _return_http_data_only: response data without head status code and headers @@ -339,6 +329,8 @@ class ApiClient(object): number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. + :param _check_type: boolean describing if the data back from the server + should have its type checked. :return: If async_req parameter is True, the request will be called asynchronously. @@ -352,7 +344,8 @@ class ApiClient(object): body, post_params, files, response_type, auth_settings, _return_http_data_only, collection_formats, - _preload_content, _request_timeout, _host) + _preload_content, _request_timeout, _host, + _check_type) else: thread = self.pool.apply_async(self.__call_api, (resource_path, method, path_params, query_params, @@ -363,7 +356,7 @@ class ApiClient(object): collection_formats, _preload_content, _request_timeout, - _host)) + _host, _check_type)) return thread def request(self, method, url, query_params=None, headers=None, @@ -460,24 +453,34 @@ class ApiClient(object): def files_parameters(self, files=None): """Builds form parameters. - :param files: File parameters. - :return: Form parameters with files. + :param files: None or a dict with key=param_name and + value is a list of open file objects + :return: List of tuples of form parameters with file data """ - params = [] + if files is None: + return [] - if files: - for k, v in six.iteritems(files): - if not v: + params = [] + for param_name, file_instances in six.iteritems(files): + if file_instances is None: + # if the file field is nullable, skip None values + continue + for file_instance in file_instances: + if file_instance is None: + # if the file field is nullable, skip None values continue - file_names = v if type(v) is list else [v] - for n in file_names: - with open(n, 'rb') as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = (mimetypes.guess_type(filename)[0] or - 'application/octet-stream') - params.append( - tuple([k, tuple([filename, filedata, mimetype])])) + if file_instance.closed is True: + raise ApiValueError( + "Cannot read a closed file. The passed in file_type " + "for %s must be open." % param_name + ) + filename = os.path.basename(file_instance.name) + filedata = file_instance.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([param_name, tuple([filename, filedata, mimetype])])) + file_instance.close() return params @@ -538,133 +541,3 @@ class ApiClient(object): raise ApiValueError( 'Authentication token must be in `query` or `header`' ) - - def __deserialize_file(self, response): - """Deserializes body to file - - Saves response body into a file in a temporary folder, - using the filename from the `Content-Disposition` header if provided. - - :param response: RESTResponse. - :return: file path. - """ - fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) - os.close(fd) - os.remove(path) - - content_disposition = response.getheader("Content-Disposition") - if content_disposition: - filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', - content_disposition).group(1) - path = os.path.join(os.path.dirname(path), filename) - - with open(path, "wb") as f: - f.write(response.data) - - return path - - def __deserialize_primitive(self, data, klass): - """Deserializes string to primitive type. - - :param data: str. - :param klass: class literal. - - :return: int, long, float, str, bool. - """ - try: - return klass(data) - except UnicodeEncodeError: - return six.text_type(data) - except TypeError: - return data - except ValueError as exc: - raise ApiValueError(str(exc)) - - def __deserialize_object(self, value): - """Return an original value. - - :return: object. - """ - return value - - def __deserialize_date(self, string): - """Deserializes string to date. - - :param string: str. - :return: date. - """ - try: - from dateutil.parser import parse - return parse(string).date() - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason="Failed to parse `{0}` as date object".format(string) - ) - - def __deserialize_datatime(self, string): - """Deserializes string to datetime. - - The string should be in iso8601 datetime format. - - :param string: str. - :return: datetime. - """ - try: - from dateutil.parser import parse - return parse(string) - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason=( - "Failed to parse `{0}` as datetime object" - .format(string) - ) - ) - - def __deserialize_model(self, data, klass): - """Deserializes list or dict to model. - - :param data: dict, list. - :param klass: class literal, ModelSimple or ModelNormal - :return: model object. - """ - - if issubclass(klass, ModelSimple): - value = self.__deserialize(data, klass.openapi_types['value']) - return klass(value) - - # code to handle ModelNormal - used_data = data - if not isinstance(data, (list, dict)): - used_data = [data] - keyword_args = {} - positional_args = [] - if klass.openapi_types is not None: - for attr, attr_type in six.iteritems(klass.openapi_types): - if (data is not None and - klass.attribute_map[attr] in used_data): - value = used_data[klass.attribute_map[attr]] - keyword_args[attr] = self.__deserialize(value, attr_type) - end_index = None - argspec = inspect.getargspec(getattr(klass, '__init__')) - if argspec.defaults: - end_index = -len(argspec.defaults) - required_positional_args = argspec.args[1:end_index] - for index, req_positional_arg in enumerate(required_positional_args): - if keyword_args and req_positional_arg in keyword_args: - positional_args.append(keyword_args[req_positional_arg]) - del keyword_args[req_positional_arg] - elif (not keyword_args and index < len(used_data) and - isinstance(used_data, list)): - positional_args.append(used_data[index]) - instance = klass(*positional_args, **keyword_args) - if hasattr(instance, 'get_real_child_model'): - klass_name = instance.get_real_child_model(data) - if klass_name: - instance = self.__deserialize(data, klass_name) - return instance diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 082f4bddc4..2513d6b3f8 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -7,14 +7,29 @@ import re # noqa: F401 import six # noqa: F401 -from {{packageName}}.exceptions import ApiValueError # noqa: F401 +from {{packageName}}.exceptions import ( # noqa: F401 + ApiKeyError, + ApiTypeError, + ApiValueError, +) from {{packageName}}.model_utils import ( # noqa: F401 ModelNormal, ModelSimple, check_allowed_values, - check_validations + check_validations, + date, + datetime, + file_type, + get_simple_class, + int, + model_to_dict, + none_type, + str, + type_error_message, + validate_and_convert_types ) - +{{#models}}{{#model}}{{#imports}}{{.}} +{{/imports}}{{/model}}{{/models}} {{#models}} {{#model}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index 16592869b7..70b2339985 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -3,10 +3,22 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#requiredVars}}{{^defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} -{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} -{{/defaultValue}}{{/requiredVars}}{{#optionalVars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{#requiredVars}} +{{^defaultValue}} +**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} +{{/defaultValue}} +{{/requiredVars}} +{{#requiredVars}} +{{#defaultValue}} +**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} +{{/defaultValue}} +{{/requiredVars}} +{{#optionalVars}} +**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} {{/optionalVars}} +{{#additionalPropertiesType}} +**any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional] +{{/additionalPropertiesType}} [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/python-experimental/model_templates/classvar_allowed.mustache b/python-experimental/model_templates/classvar_allowed.mustache index 6ed39521f6..2414be114a 100644 --- a/python-experimental/model_templates/classvar_allowed.mustache +++ b/python-experimental/model_templates/classvar_allowed.mustache @@ -1,5 +1,5 @@ allowed_values = { -{{#vars}} +{{#allVars}} {{#isEnum}} ('{{name}}',): { {{#isNullable}} @@ -7,10 +7,10 @@ {{/isNullable}} {{#allowableValues}} {{#enumVars}} - '{{name}}': {{{value}}}{{^-last}},{{/-last}} + '{{name}}': {{{value}}}, {{/enumVars}} {{/allowableValues}} }, {{/isEnum}} -{{/vars}} +{{/allVars}} } \ No newline at end of file diff --git a/python-experimental/model_templates/classvar_openapi_validations.mustache b/python-experimental/model_templates/classvar_openapi_validations.mustache index 7e89f83ef2..1cc7b58550 100644 --- a/python-experimental/model_templates/classvar_openapi_validations.mustache +++ b/python-experimental/model_templates/classvar_openapi_validations.mustache @@ -1,25 +1,42 @@ openapi_types = { -{{#vars}} - '{{name}}': '{{{dataType}}}'{{#hasMore}},{{/hasMore}} -{{/vars}} +{{#allVars}} + '{{name}}': ({{{dataType}}},), # noqa: E501 +{{/allVars}} } validations = { -{{#vars}} +{{#allVars}} {{#hasValidation}} ('{{name}}',): { {{#maxLength}} - 'max_length': {{maxLength}},{{/maxLength}}{{#minLength}} - 'min_length': {{minLength}},{{/minLength}}{{#maxItems}} - 'max_items': {{maxItems}},{{/maxItems}}{{#minItems}} - 'min_items': {{minItems}},{{/minItems}}{{#maximum}} - {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}} - {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}} + 'max_length': {{maxLength}}, +{{/maxLength}} +{{#minLength}} + 'min_length': {{minLength}}, +{{/minLength}} +{{#maxItems}} + 'max_items': {{maxItems}}, +{{/maxItems}} +{{#minItems}} + 'min_items': {{minItems}}, +{{/minItems}} +{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, +{{/maximum}} +{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, +{{/minimum}} +{{#pattern}} 'regex': { 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} - },{{/pattern}} + }, +{{/pattern}} }, {{/hasValidation}} -{{/vars}} - } \ No newline at end of file +{{/allVars}} + } + + additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} + + discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} \ No newline at end of file diff --git a/python-experimental/model_templates/docstring_openapi_validations.mustache b/python-experimental/model_templates/docstring_openapi_validations.mustache index 46dc1afefc..03eec953f3 100644 --- a/python-experimental/model_templates/docstring_openapi_validations.mustache +++ b/python-experimental/model_templates/docstring_openapi_validations.mustache @@ -4,4 +4,6 @@ and the for var_name this is (var_name,). The value is a dict that stores validations for max_length, min_length, max_items, min_items, exclusive_maximum, inclusive_maximum, exclusive_minimum, - inclusive_minimum, and regex. \ No newline at end of file + inclusive_minimum, and regex. + additional_properties_type (tuple): A tuple of classes accepted + as additional properties values. \ No newline at end of file diff --git a/python-experimental/model_templates/methods_init_properties.mustache b/python-experimental/model_templates/methods_init_properties.mustache index 447aa22cac..dab632efab 100644 --- a/python-experimental/model_templates/methods_init_properties.mustache +++ b/python-experimental/model_templates/methods_init_properties.mustache @@ -1,76 +1,126 @@ - def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}): # noqa: E501 - """{{classname}} - a model defined in OpenAPI""" # noqa: E501 -{{#vars}}{{#-first}} -{{/-first}} - self._{{name}} = None -{{/vars}} - self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} -{{#vars}}{{#-first}} -{{/-first}} -{{#required}} - self.{{name}} = {{name}} -{{/required}} -{{^required}} -{{#isNullable}} - self.{{name}} = {{name}} -{{/isNullable}} -{{^isNullable}} - if {{name}} is not None: - self.{{name}} = ( - {{name}} + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 + """{{classname}} - a model defined in OpenAPI + +{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} +{{/hasMore}}{{/requiredVars}} + Keyword Args:{{#requiredVars}}{{#defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _from_server (bool): True if the data is from the server + False if the data is from the client (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done.{{#optionalVars}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} + """ + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration + +{{#requiredVars}} + self.__set_item('{{name}}', {{name}}) +{{/requiredVars}} + for var_name, var_value in six.iteritems(kwargs): + self.__set_item(var_name, var_value) + + def __set_item(self, name, value): + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + + if name in self.openapi_types: + required_types_mixed = self.openapi_types[name] + elif self.additional_properties_type is None: + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) + elif self.additional_properties_type is not None: + required_types_mixed = self.additional_properties_type + + if get_simple_class(name) != str: + error_msg = type_error_message( + var_name=name, + var_value=name, + valid_classes=(str,), + key_type=True + ) + raise ApiTypeError( + error_msg, + path_to_item=path_to_item, + valid_classes=(str,), + key_type=True + ) + + if self._check_type: + value = validate_and_convert_types( + value, required_types_mixed, path_to_item, self._from_server, + self._check_type, configuration=self._configuration) + if (name,) in self.allowed_values: + check_allowed_values( + self.allowed_values, + (name,), + value + ) + if (name,) in self.validations: + check_validations( + self.validations, + (name,), + value ) -{{/isNullable}} -{{/required}} -{{/vars}} -{{#vars}} + self._data_store[name] = value + + def __get_item(self, name): + if name in self._data_store: + return self._data_store[name] + + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + [name] + ) + + def __setitem__(self, name, value): + """this allows us to set values with instance[field_name] = val""" + self.__set_item(name, value) + + def __getitem__(self, name): + """this allows us to get a value with val = instance[field_name]""" + return self.__get_item(name) +{{#allVars}} @property def {{name}}(self): """Gets the {{name}} of this {{classname}}. # noqa: E501 - {{#description}} {{{description}}} # noqa: E501 {{/description}} - :return: The {{name}} of this {{classname}}. # noqa: E501 - :rtype: {{dataType}} + Returns: + ({{{dataType}}}): The {{name}} of this {{classname}}. # noqa: E501 """ - return self._{{name}} + return self.__get_item('{{name}}') @{{name}}.setter - def {{name}}(self, {{name}}): # noqa: E501 - """Sets the {{name}} of this {{classname}}. - + def {{name}}(self, value): + """Sets the {{name}} of this {{classname}}. # noqa: E501 {{#description}} {{{description}}} # noqa: E501 {{/description}} - - :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 - :type: {{dataType}} """ -{{^isNullable}} -{{#required}} - if {{name}} is None: - raise ApiValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 -{{/required}} -{{/isNullable}} -{{#isEnum}} - check_allowed_values( - self.allowed_values, - ('{{name}}',), - {{name}}, - self.validations - ) -{{/isEnum}} -{{#hasValidation}} - check_validations( - self.validations, - ('{{name}}',), - {{name}} - ) -{{/hasValidation}} - - self._{{name}} = ( - {{name}} - ) -{{/vars}} \ No newline at end of file + return self.__set_item('{{name}}', value) +{{/allVars}} \ No newline at end of file diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache index bd1eaddcb4..c4e707e036 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/python-experimental/model_templates/model_normal.mustache @@ -16,14 +16,14 @@ class {{classname}}(ModelNormal): {{> python-experimental/model_templates/classvar_allowed }} attribute_map = { -{{#vars}} +{{#allVars}} '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} # noqa: E501 -{{/vars}} +{{/allVars}} } {{#discriminator}} discriminator_value_class_map = { - {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, + {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': {{{classname}}}{{^-last}}, {{/-last}}{{/children}} } {{/discriminator}} @@ -32,36 +32,19 @@ class {{classname}}(ModelNormal): {{> python-experimental/model_templates/methods_init_properties }} {{#discriminator}} - def get_real_child_model(self, data): - """Returns the real base class specified by the discriminator""" - discriminator_key = self.attribute_map[self.discriminator] + @classmethod + def get_real_child_model(cls, data): + """Returns the real base class specified by the discriminator + We assume that data has javascript keys + """ + discriminator_key = cls.attribute_map[cls.discriminator] discriminator_value = data[discriminator_key] - return self.discriminator_value_class_map.get(discriminator_value) + return cls.discriminator_value_class_map.get(discriminator_value) {{/discriminator}} def to_dict(self): """Returns the model properties as a dict""" - result = {} - - for attr, _ in six.iteritems(self.openapi_types): - value = getattr(self, attr) - if isinstance(value, list): - result[attr] = list(map( - lambda x: x.to_dict() if hasattr(x, "to_dict") else x, - value - )) - elif hasattr(value, "to_dict"): - result[attr] = value.to_dict() - elif isinstance(value, dict): - result[attr] = dict(map( - lambda item: (item[0], item[1].to_dict()) - if hasattr(item[1], "to_dict") else item, - value.items() - )) - else: - result[attr] = value - - return result + return model_to_dict(self, serialize=False) def to_str(self): """Returns the string representation of the model""" @@ -76,7 +59,22 @@ class {{classname}}(ModelNormal): if not isinstance(other, {{classname}}): return False - return self.__dict__ == other.__dict__ + if not set(self._data_store.keys()) == set(other._data_store.keys()): + return False + for _var_name, this_val in six.iteritems(self._data_store): + that_val = other._data_store[_var_name] + types = set() + types.add(this_val.__class__) + types.add(that_val.__class__) + vals_equal = this_val == that_val + if (not six.PY3 and + len(types) == 2 and unicode in types): # noqa: F821 + vals_equal = ( + this_val.encode('utf-8') == that_val.encode('utf-8') + ) + if not vals_equal: + return False + return True def __ne__(self, other): """Returns true if both objects are not equal""" diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index 94ad6336f9..b5939d926c 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -16,7 +16,7 @@ class {{classname}}(ModelSimple): {{> python-experimental/model_templates/methods_init_properties }} def to_str(self): """Returns the string representation of the model""" - return str(self._value) + return str(self.value) def __repr__(self): """For `print` and `pprint`""" @@ -27,7 +27,19 @@ class {{classname}}(ModelSimple): if not isinstance(other, {{classname}}): return False - return self.__dict__ == other.__dict__ + this_val = self._data_store['value'] + that_val = other._data_store['value'] + types = set() + types.add(this_val.__class__) + types.add(that_val.__class__) + vals_equal = this_val == that_val + if not six.PY3 and len(types) == 2 and unicode in types: # noqa: F821 + vals_equal = ( + this_val.encode('utf-8') == that_val.encode('utf-8') + ) + if not vals_equal: + return False + return True def __ne__(self, other): """Returns true if both objects are not equal""" diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index c251879b10..101b5466c3 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -1,13 +1,162 @@ # coding: utf-8 {{>partial_header}} + +import copy +from datetime import date, datetime # noqa: F401 +import inspect +import os import re +import tempfile + +from dateutil.parser import parse +import six + +from {{packageName}}.exceptions import ( + ApiKeyError, + ApiTypeError, + ApiValueError, +) + +none_type = type(None) +if six.PY3: + import io + file_type = io.IOBase + # these are needed for when other modules import str and int from here + str = str + int = int +else: + file_type = file # noqa: F821 + str_py2 = str + unicode_py2 = unicode # noqa: F821 + long_py2 = long # noqa: F821 + int_py2 = int + # this requires that the future library is installed + from builtins import int, str + + +class OpenApiModel(object): + """The base class for all OpenAPIModels""" + + +class ModelSimple(OpenApiModel): + """the parent class of models whose type != object in their + swagger/openapi""" -from {{packageName}}.exceptions import ApiValueError +class ModelNormal(OpenApiModel): + """the parent class of models whose type == object in their + swagger/openapi""" -def check_allowed_values(allowed_values, input_variable_path, input_values, - validations): + +COERCION_INDEX_BY_TYPE = { + ModelNormal: 0, + ModelSimple: 1, + none_type: 2, + list: 3, + dict: 4, + float: 5, + int: 6, + bool: 7, + datetime: 8, + date: 9, + str: 10, + file_type: 11, +} + +# these are used to limit what type conversions we try to do +# when we have a valid type already and we want to try converting +# to another type +UPCONVERSION_TYPE_PAIRS = ( + (str, datetime), + (str, date), + (list, ModelNormal), + (dict, ModelNormal), + (str, ModelSimple), + (int, ModelSimple), + (float, ModelSimple), + (list, ModelSimple), +) + +COERCIBLE_TYPE_PAIRS = { + False: ( # client instantiation of a model with client data + # (dict, ModelNormal), + # (list, ModelNormal), + # (str, ModelSimple), + # (int, ModelSimple), + # (float, ModelSimple), + # (list, ModelSimple), + # (str, int), + # (str, float), + # (str, datetime), + # (str, date), + # (int, str), + # (float, str), + ), + True: ( # server -> client data + (dict, ModelNormal), + (list, ModelNormal), + (str, ModelSimple), + (int, ModelSimple), + (float, ModelSimple), + (list, ModelSimple), + # (str, int), + # (str, float), + (str, datetime), + (str, date), + # (int, str), + # (float, str), + (str, file_type) + ), +} + + +def get_simple_class(input_value): + """Returns an input_value's simple class that we will use for type checking + Python2: + float and int will return int, where int is the python3 int backport + str and unicode will return str, where str is the python3 str backport + Note: float and int ARE both instances of int backport + Note: str_py2 and unicode_py2 are NOT both instances of str backport + + Args: + input_value (class/class_instance): the item for which we will return + the simple class + """ + if isinstance(input_value, type): + # input_value is a class + return input_value + elif isinstance(input_value, tuple): + return tuple + elif isinstance(input_value, list): + return list + elif isinstance(input_value, dict): + return dict + elif isinstance(input_value, none_type): + return none_type + elif isinstance(input_value, file_type): + return file_type + elif isinstance(input_value, bool): + # this must be higher than the int check because + # isinstance(True, int) == True + return bool + elif isinstance(input_value, int): + # for python2 input_value==long_instance -> return int + # where int is the python3 int backport + return int + elif isinstance(input_value, datetime): + # this must be higher than the date check because + # isinstance(datetime_instance, date) == True + return datetime + elif isinstance(input_value, date): + return date + elif (six.PY2 and isinstance(input_value, (str_py2, unicode_py2, str)) or + isinstance(input_value, str)): + return str + return type(input_value) + + +def check_allowed_values(allowed_values, input_variable_path, input_values): """Raises an exception if the input_values are not allowed Args: @@ -15,14 +164,9 @@ def check_allowed_values(allowed_values, input_variable_path, input_values, input_variable_path (tuple): the path to the input variable input_values (list/str/int/float/date/datetime): the values that we are checking to see if they are in allowed_values - validations (dict): the validations dict """ - min_collection_length = ( - validations.get(input_variable_path, {}).get('min_length') or - validations.get(input_variable_path, {}).get('min_items', 0)) these_allowed_values = list(allowed_values[input_variable_path].values()) if (isinstance(input_values, list) - and len(input_values) > min_collection_length and not set(input_values).issubset( set(these_allowed_values))): invalid_values = ", ".join( @@ -36,7 +180,6 @@ def check_allowed_values(allowed_values, input_variable_path, input_values, ) ) elif (isinstance(input_values, dict) - and len(input_values) > min_collection_length and not set( input_values.keys()).issubset(set(these_allowed_values))): invalid_values = ", ".join( @@ -111,8 +254,21 @@ def check_validations(validations, input_variable_path, input_values): ) ) + items = ('exclusive_maximum', 'inclusive_maximum', 'exclusive_minimum', + 'inclusive_minimum') + if (any(item in current_validations for item in items)): + if isinstance(input_values, list): + max_val = max(input_values) + min_val = min(input_values) + elif isinstance(input_values, dict): + max_val = max(input_values.values()) + min_val = min(input_values.values()) + else: + max_val = input_values + min_val = input_values + if ('exclusive_maximum' in current_validations and - input_values >= current_validations['exclusive_maximum']): + max_val >= current_validations['exclusive_maximum']): raise ApiValueError( "Invalid value for `%s`, must be a value less than `%s`" % ( input_variable_path[0], @@ -121,7 +277,7 @@ def check_validations(validations, input_variable_path, input_values): ) if ('inclusive_maximum' in current_validations and - input_values > current_validations['inclusive_maximum']): + max_val > current_validations['inclusive_maximum']): raise ApiValueError( "Invalid value for `%s`, must be a value less than or equal to " "`%s`" % ( @@ -131,7 +287,7 @@ def check_validations(validations, input_variable_path, input_values): ) if ('exclusive_minimum' in current_validations and - input_values <= current_validations['exclusive_minimum']): + min_val <= current_validations['exclusive_minimum']): raise ApiValueError( "Invalid value for `%s`, must be a value greater than `%s`" % ( @@ -141,7 +297,7 @@ def check_validations(validations, input_variable_path, input_values): ) if ('inclusive_minimum' in current_validations and - input_values < current_validations['inclusive_minimum']): + min_val < current_validations['inclusive_minimum']): raise ApiValueError( "Invalid value for `%s`, must be a value greater than or equal " "to `%s`" % ( @@ -163,13 +319,550 @@ def check_validations(validations, input_variable_path, input_values): ) -class ModelSimple(object): - # the parent class of models whose type != object in their swagger/openapi - # spec - pass +def order_response_types(required_types): + """Returns the required types sorted in coercion order + + Args: + required_types (list/tuple): collection of classes or instance of + list or dict with classs information inside it + + Returns: + (list): coercion order sorted collection of classes or instance + of list or dict with classs information inside it + """ + + def index_getter(class_or_instance): + if isinstance(class_or_instance, list): + return COERCION_INDEX_BY_TYPE[list] + elif isinstance(class_or_instance, dict): + return COERCION_INDEX_BY_TYPE[dict] + elif (inspect.isclass(class_or_instance) + and issubclass(class_or_instance, ModelNormal)): + return COERCION_INDEX_BY_TYPE[ModelNormal] + elif (inspect.isclass(class_or_instance) + and issubclass(class_or_instance, ModelSimple)): + return COERCION_INDEX_BY_TYPE[ModelSimple] + return COERCION_INDEX_BY_TYPE[class_or_instance] + + sorted_types = sorted( + required_types, + key=lambda class_or_instance: index_getter(class_or_instance) + ) + return sorted_types + + +def remove_uncoercible(required_types_classes, current_item, from_server, + must_convert=True): + """Only keeps the type conversions that are possible + + Args: + required_types_classes (tuple): tuple of classes that are required + these should be ordered by COERCION_INDEX_BY_TYPE + from_server (bool): a boolean of whether the data is from the server + if false, the data is from the client + current_item (any): the current item to be converted + + Keyword Args: + must_convert (bool): if True the item to convert is of the wrong + type and we want a big list of coercibles + if False, we want a limited list of coercibles + + Returns: + (list): the remaining coercible required types, classes only + """ + current_type_simple = get_simple_class(current_item) + + results_classes = [] + for required_type_class in required_types_classes: + # convert our models to OpenApiModel + required_type_class_simplified = required_type_class + if isinstance(required_type_class_simplified, type): + if issubclass(required_type_class_simplified, ModelNormal): + required_type_class_simplified = ModelNormal + elif issubclass(required_type_class_simplified, ModelSimple): + required_type_class_simplified = ModelSimple + + if required_type_class_simplified == current_type_simple: + # don't consider converting to one's own class + continue + + class_pair = (current_type_simple, required_type_class_simplified) + if must_convert and class_pair in COERCIBLE_TYPE_PAIRS[from_server]: + results_classes.append(required_type_class) + elif class_pair in UPCONVERSION_TYPE_PAIRS: + results_classes.append(required_type_class) + return results_classes + + +def get_required_type_classes(required_types_mixed): + """Converts the tuple required_types into a tuple and a dict described + below + + Args: + required_types_mixed (tuple/list): will contain either classes or + instance of list or dict + + Returns: + (valid_classes, dict_valid_class_to_child_types_mixed): + valid_classes (tuple): the valid classes that the current item + should be + dict_valid_class_to_child_types_mixed (doct): + valid_class (class): this is the key + child_types_mixed (list/dict/tuple): describes the valid child + types + """ + valid_classes = [] + child_req_types_by_current_type = {} + for required_type in required_types_mixed: + if isinstance(required_type, list): + valid_classes.append(list) + child_req_types_by_current_type[list] = required_type + elif isinstance(required_type, tuple): + valid_classes.append(tuple) + child_req_types_by_current_type[tuple] = required_type + elif isinstance(required_type, dict): + valid_classes.append(dict) + child_req_types_by_current_type[dict] = required_type[str] + else: + valid_classes.append(required_type) + return tuple(valid_classes), child_req_types_by_current_type + + +def change_keys_js_to_python(input_dict, model_class): + """ + Converts from javascript_key keys in the input_dict to python_keys in + the output dict using the mapping in model_class + """ + + output_dict = {} + reversed_attr_map = {value: key for key, value in + six.iteritems(model_class.attribute_map)} + for javascript_key, value in six.iteritems(input_dict): + python_key = reversed_attr_map.get(javascript_key) + if python_key is None: + # if the key is unknown, it is in error or it is an + # additionalProperties variable + python_key = javascript_key + output_dict[python_key] = value + return output_dict + + +def get_type_error(var_value, path_to_item, valid_classes, key_type=False): + error_msg = type_error_message( + var_name=path_to_item[-1], + var_value=var_value, + valid_classes=valid_classes, + key_type=key_type + ) + return ApiTypeError( + error_msg, + path_to_item=path_to_item, + valid_classes=valid_classes, + key_type=key_type + ) + + +def deserialize_primitive(data, klass, path_to_item): + """Deserializes string to primitive type. + + :param data: str/int/float + :param klass: str/class the class to convert to + + :return: int, float, str, bool, date, datetime + """ + additional_message = "" + try: + if klass in {datetime, date}: + additional_message = ( + "If you need your parameter to have a fallback " + "string value, please set its type as `type: {}` in your " + "spec. That allows the value to be any type. " + ) + if klass == datetime: + if len(data) < 8: + raise ValueError("This is not a datetime") + # The string should be in iso8601 datetime format. + parsed_datetime = parse(data) + date_only = ( + parsed_datetime.hour == 0 and + parsed_datetime.minute == 0 and + parsed_datetime.second == 0 and + parsed_datetime.tzinfo is None and + 8 <= len(data) <= 10 + ) + if date_only: + raise ValueError("This is a date, not a datetime") + return parsed_datetime + elif klass == date: + if len(data) < 8: + raise ValueError("This is not a date") + return parse(data).date() + else: + converted_value = klass(data) + if isinstance(data, str) and klass == float: + if str(converted_value) != data: + # '7' -> 7.0 -> '7.0' != '7' + raise ValueError('This is not a float') + return converted_value + except (OverflowError, ValueError): + # parse can raise OverflowError + raise ApiValueError( + "{0}Failed to parse {1} as {2}".format( + additional_message, repr(data), get_py3_class_name(klass) + ), + path_to_item=path_to_item + ) + + +def deserialize_model(model_data, model_class, path_to_item, check_type, + configuration, from_server): + """Deserializes model_data to model instance. + + Args: + model_data (list/dict): data to instantiate the model + model_class (OpenApiModel): the model class + path_to_item (list): path to the model in the received data + check_type (bool): whether to check the data tupe for the values in + the model + configuration (Configuration): the instance to use to convert files + from_server (bool): True if the data is from the server + False if the data is from the client + + Returns: + model instance + + Raise: + ApiTypeError + ApiValueError + ApiKeyError + """ + fixed_model_data = copy.deepcopy(model_data) + + if isinstance(fixed_model_data, dict): + fixed_model_data = change_keys_js_to_python(fixed_model_data, + model_class) + + kw_args = dict(_check_type=check_type, + _path_to_item=path_to_item, + _configuration=configuration, + _from_server=from_server) + + if hasattr(model_class, 'get_real_child_model'): + # discriminator case + discriminator_class = model_class.get_real_child_model(model_data) + if discriminator_class: + if isinstance(model_data, list): + instance = discriminator_class(*model_data, **kw_args) + elif isinstance(model_data, dict): + fixed_model_data = change_keys_js_to_python( + fixed_model_data, + discriminator_class + ) + kw_args.update(fixed_model_data) + instance = discriminator_class(**kw_args) + else: + # all other cases + if isinstance(model_data, list): + instance = model_class(*model_data, **kw_args) + if isinstance(model_data, dict): + fixed_model_data = change_keys_js_to_python(fixed_model_data, + model_class) + kw_args.update(fixed_model_data) + instance = model_class(**kw_args) + else: + instance = model_class(model_data, **kw_args) + + return instance + + +def deserialize_file(response_data, configuration, content_disposition=None): + """Deserializes body to file + + Saves response body into a file in a temporary folder, + using the filename from the `Content-Disposition` header if provided. + + Args: + param response_data (str): the file data to write + configuration (Configuration): the instance to use to convert files + + Keyword Args: + content_disposition (str): the value of the Content-Disposition + header + + Returns: + (file_type): the deserialized file which is open + The user is responsible for closing and reading the file + """ + fd, path = tempfile.mkstemp(dir=configuration.temp_folder_path) + os.close(fd) + os.remove(path) + + if content_disposition: + filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', + content_disposition).group(1) + path = os.path.join(os.path.dirname(path), filename) + + with open(path, "wb") as f: + if six.PY3 and isinstance(response_data, str): + # in python3 change str to bytes so we can write it + response_data = response_data.encode('utf-8') + f.write(response_data) + + f = open(path, "rb") + return f + + +def attempt_convert_item(input_value, valid_classes, path_to_item, + configuration, from_server, key_type=False, + must_convert=False, check_type=True): + """ + Args: + input_value (any): the data to convert + valid_classes (any): the classes that are valid + path_to_item (list): the path to the item to convert + configuration (Configuration): the instance to use to convert files + from_server (bool): True if data is from the server, False is data is + from the client + key_type (bool): if True we need to convert a key type (not supported) + must_convert (bool): if True we must convert + check_type (bool): if True we check the type or the returned data in + ModelNormal and ModelSimple instances + + Returns: + instance (any) the fixed item + + Raises: + ApiTypeError + ApiValueError + ApiKeyError + """ + valid_classes_ordered = order_response_types(valid_classes) + valid_classes_coercible = remove_uncoercible( + valid_classes_ordered, input_value, from_server) + if not valid_classes_coercible or key_type: + # we do not handle keytype errors, json will take care + # of this for us + raise get_type_error(input_value, path_to_item, valid_classes, + key_type=key_type) + for valid_class in valid_classes_coercible: + try: + if issubclass(valid_class, OpenApiModel): + return deserialize_model(input_value, valid_class, + path_to_item, check_type, + configuration, from_server) + elif valid_class == file_type: + return deserialize_file(input_value, configuration) + return deserialize_primitive(input_value, valid_class, + path_to_item) + except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc: + if must_convert: + raise conversion_exc + # if we have conversion errors when must_convert == False + # we ignore the exception and move on to the next class + continue + # we were unable to convert, must_convert == False + return input_value + + +def validate_and_convert_types(input_value, required_types_mixed, path_to_item, + from_server, _check_type, configuration=None): + """Raises a TypeError is there is a problem, otherwise returns value + + Args: + input_value (any): the data to validate/convert + required_types_mixed (list/dict/tuple): A list of + valid classes, or a list tuples of valid classes, or a dict where + the value is a tuple of value classes + path_to_item: (list) the path to the data being validated + this stores a list of keys or indices to get to the data being + validated + from_server (bool): True if data is from the server + False if data is from the client + _check_type: (boolean) if true, type will be checked and conversion + will be attempted. + configuration: (Configuration): the configuration class to use + when converting file_type items. + If passed, conversion will be attempted when possible + If not passed, no conversions will be attempted and + exceptions will be raised + + Returns: + the correctly typed value + + Raises: + ApiTypeError + """ + results = get_required_type_classes(required_types_mixed) + valid_classes, child_req_types_by_current_type = results + + input_class_simple = get_simple_class(input_value) + valid_type = input_class_simple in set(valid_classes) + if not valid_type: + if configuration: + # if input_value is not valid_type try to convert it + converted_instance = attempt_convert_item( + input_value, + valid_classes, + path_to_item, + configuration, + from_server, + key_type=False, + must_convert=True + ) + return converted_instance + else: + raise get_type_error(input_value, path_to_item, valid_classes, + key_type=False) + + # input_value's type is in valid_classes + if len(valid_classes) > 1 and configuration: + # there are valid classes which are not the current class + valid_classes_coercible = remove_uncoercible( + valid_classes, input_value, from_server, must_convert=False) + if valid_classes_coercible: + converted_instance = attempt_convert_item( + input_value, + valid_classes_coercible, + path_to_item, + configuration, + from_server, + key_type=False, + must_convert=False + ) + return converted_instance + + if child_req_types_by_current_type == {}: + # all types are of the required types and there are no more inner + # variables left to look at + return input_value + inner_required_types = child_req_types_by_current_type.get( + type(input_value) + ) + if inner_required_types is None: + # for this type, there are not more inner variables left to look at + return input_value + if isinstance(input_value, list): + if input_value == []: + # allow an empty list + return input_value + for index, inner_value in enumerate(input_value): + inner_path = list(path_to_item) + inner_path.append(index) + input_value[index] = validate_and_convert_types( + inner_value, + inner_required_types, + inner_path, + from_server, + _check_type, + configuration=configuration + ) + elif isinstance(input_value, dict): + if input_value == {}: + # allow an empty dict + return input_value + for inner_key, inner_val in six.iteritems(input_value): + inner_path = list(path_to_item) + inner_path.append(inner_key) + if get_simple_class(inner_key) != str: + raise get_type_error(inner_key, inner_path, valid_classes, + key_type=True) + input_value[inner_key] = validate_and_convert_types( + inner_val, + inner_required_types, + inner_path, + from_server, + _check_type, + configuration=configuration + ) + return input_value + + +def model_to_dict(model_instance, serialize=True): + """Returns the model properties as a dict + + Args: + model_instance (one of your model instances): the model instance that + will be converted to a dict. + + Keyword Args: + serialize (bool): if True, the keys in the dict will be values from + attribute_map + """ + result = {} + + for attr, value in six.iteritems(model_instance._data_store): + if serialize: + # we use get here because additional property key names do not + # exist in attribute_map + attr = model_instance.attribute_map.get(attr, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: model_to_dict(x, serialize=serialize) + if hasattr(x, '_data_store') else x, value + )) + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], + model_to_dict(item[1], serialize=serialize)) + if hasattr(item[1], '_data_store') else item, + value.items() + )) + elif hasattr(value, '_data_store'): + result[attr] = model_to_dict(value, serialize=serialize) + else: + result[attr] = value + + return result + + +def type_error_message(var_value=None, var_name=None, valid_classes=None, + key_type=None): + """ + Keyword Args: + var_value (any): the variable which has the type_error + var_name (str): the name of the variable which has the typ error + valid_classes (tuple): the accepted classes for current_item's + value + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + """ + key_or_value = 'value' + if key_type: + key_or_value = 'key' + valid_classes_phrase = get_valid_classes_phrase(valid_classes) + msg = ( + "Invalid type for variable '{0}'. Required {1} type {2} and " + "passed type was {3}".format( + var_name, + key_or_value, + valid_classes_phrase, + type(var_value).__name__, + ) + ) + return msg + + +def get_valid_classes_phrase(input_classes): + """Returns a string phrase describing what types are allowed + Note: Adds the extra valid classes in python2 + """ + all_classes = list(input_classes) + if six.PY2 and str in input_classes: + all_classes.extend([str_py2, unicode_py2]) + if six.PY2 and int in input_classes: + all_classes.extend([int_py2, long_py2]) + all_classes = sorted(all_classes, key=lambda cls: cls.__name__) + all_class_names = [cls.__name__ for cls in all_classes] + if len(all_class_names) == 1: + return 'is {0}'.format(all_class_names[0]) + return "is one of [{0}]".format(", ".join(all_class_names)) -class ModelNormal(object): - # the parent class of models whose type == object in their swagger/openapi - # spec - pass +def get_py3_class_name(input_class): + if six.PY2: + if input_class == str: + return 'str' + elif input_class == int: + return 'int' + return input_class.__name__ diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache new file mode 100644 index 0000000000..eb358efd5b --- /dev/null +++ b/python-experimental/requirements.mustache @@ -0,0 +1,6 @@ +certifi >= 14.05.14 +future; python_version<="2.7" +six >= 1.10 +python_dateutil >= 2.5.3 +setuptools >= 21.0.0 +urllib3 >= 1.15.1 diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache new file mode 100644 index 0000000000..80006ded16 --- /dev/null +++ b/python-experimental/setup.mustache @@ -0,0 +1,45 @@ +# coding: utf-8 + +{{>partial_header}} + +from setuptools import setup, find_packages # noqa: H301 + +NAME = "{{{projectName}}}" +VERSION = "{{packageVersion}}" +{{#apiInfo}} +{{#apis}} +{{^hasMore}} +# To install the library, run the following +# +# python setup.py install +# +# prerequisite: setuptools +# http://pypi.python.org/pypi/setuptools + +REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] +{{#asyncio}} +REQUIRES.append("aiohttp >= 3.0.0") +{{/asyncio}} +{{#tornado}} +REQUIRES.append("tornado>=4.2,<5") +{{/tornado}} +EXTRAS = {':python_version <= "2.7"': ['future']} + +setup( + name=NAME, + version=VERSION, + description="{{appName}}", + author_email="{{infoEmail}}", + url="{{packageUrl}}", + keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], + install_requires=REQUIRES, + extras_require=EXTRAS, + packages=find_packages(exclude=["test", "tests"]), + include_package_data=True, + long_description="""\ + {{appDescription}} # noqa: E501 + """ +) +{{/hasMore}} +{{/apis}} +{{/apiInfo}} diff --git a/python-experimental/test-requirements.mustache b/python-experimental/test-requirements.mustache new file mode 100644 index 0000000000..023ff96078 --- /dev/null +++ b/python-experimental/test-requirements.mustache @@ -0,0 +1,13 @@ +{{^asyncio}} +coverage>=4.0.3 +nose>=1.3.7 +{{/asyncio}} +{{#asyncio}} +pytest>=3.6.0 +pytest-cov>=2.6.1 +{{/asyncio}} +pluggy>=0.3.1 +py>=1.4.31 +randomize>=0.13 +mock; python_version<="2.7" + diff --git a/requirements.mustache b/requirements.mustache index bafdc07532..eb358efd5b 100644 --- a/requirements.mustache +++ b/requirements.mustache @@ -1,4 +1,5 @@ certifi >= 14.05.14 +future; python_version<="2.7" six >= 1.10 python_dateutil >= 2.5.3 setuptools >= 21.0.0 From 554e6cb2f5f546cd1d77a82dc49bf8be90263ed2 Mon Sep 17 00:00:00 2001 From: Arun Date: Tue, 29 Oct 2019 20:24:05 +0530 Subject: [PATCH 059/180] [Python] [Bug] Correct typo in the word datetime (#4304) --- api_client.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 63dd91ebb5..4c0be2fe86 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -294,7 +294,7 @@ class ApiClient(object): elif klass == datetime.date: return self.__deserialize_date(data) elif klass == datetime.datetime: - return self.__deserialize_datatime(data) + return self.__deserialize_datetime(data) else: return self.__deserialize_model(data, klass) @@ -594,7 +594,7 @@ class ApiClient(object): reason="Failed to parse `{0}` as date object".format(string) ) - def __deserialize_datatime(self, string): + def __deserialize_datetime(self, string): """Deserializes string to datetime. The string should be in iso8601 datetime format. From 5933bdf42abc5a799c8fa68d8b63b064d9b45086 Mon Sep 17 00:00:00 2001 From: Arun Date: Wed, 30 Oct 2019 14:32:08 +0530 Subject: [PATCH 060/180] [Python] Remove redundant else statement (#4311) * [Python] Remove redundant else condition * Add indentation * Reduce extra indent * Avoid longer than 79 chars * Remove trailing space after response_body * [Python] Fix pep8 violation in imports * Revert "[Python] Fix pep8 violation in imports" This reverts commit bc69aaae7fa7739d0d48421e47a1a446f130c225. --- api_client.mustache | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 4c0be2fe86..8cba076583 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -347,18 +347,19 @@ class ApiClient(object): response_type, auth_settings, _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host) - else: - thread = self.pool.apply_async(self.__call_api, (resource_path, - method, path_params, query_params, - header_params, body, - post_params, files, - response_type, auth_settings, - _return_http_data_only, - collection_formats, - _preload_content, - _request_timeout, - _host)) - return thread + + return self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, + query_params, + header_params, body, + post_params, files, + response_type, + auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, + _request_timeout, + _host)) def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, _preload_content=True, From d12d265ae6a8e5256b80db9eaaa1a043ae69819b Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Wed, 30 Oct 2019 14:40:02 +0530 Subject: [PATCH 061/180] [python][fix] Adding model summary to model documentation files (#4306) * feat(documentation): Adding model documentation * feat(documentation): Adding model documentation * feat(documentation): Adding model documentation * feat(documentation): Adding model documentation --- model_doc.mustache | 2 ++ python-experimental/model_doc.mustache | 2 ++ 2 files changed, 4 insertions(+) diff --git a/model_doc.mustache b/model_doc.mustache index 71c106fdc5..c1ead8680c 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -1,5 +1,7 @@ {{#models}}{{#model}}# {{classname}} +{{#description}}{{description}} +{{/description}} ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index 70b2339985..a8bfb933b6 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -1,5 +1,7 @@ {{#models}}{{#model}}# {{classname}} +{{#description}}{{description}} +{{/description}} ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- From d98b3f46c0d052ba141c120aebd546ae4fb6e756 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 31 Oct 2019 09:10:05 +0800 Subject: [PATCH 062/180] Do not HTML escaped the description in the doc (#4321) * html escaped the description in the doc * update python oas3 sample --- model_doc.mustache | 2 +- python-experimental/model_doc.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/model_doc.mustache b/model_doc.mustache index c1ead8680c..fc90a2e0fc 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -1,6 +1,6 @@ {{#models}}{{#model}}# {{classname}} -{{#description}}{{description}} +{{#description}}{{&description}} {{/description}} ## Properties Name | Type | Description | Notes diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index a8bfb933b6..79abbf6130 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -1,6 +1,6 @@ {{#models}}{{#model}}# {{classname}} -{{#description}}{{description}} +{{#description}}{{&description}} {{/description}} ## Properties Name | Type | Description | Notes From 0a9f1e302bffebb4862be820acd1e153ad91f3e4 Mon Sep 17 00:00:00 2001 From: Arun Date: Sun, 3 Nov 2019 12:18:42 +0530 Subject: [PATCH 063/180] [Python] Avoid pep8 violation (#4316) --- api_client.mustache | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 8cba076583..790ec22046 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -3,6 +3,7 @@ from __future__ import absolute_import import datetime +from dateutil.parser import parse import json import mimetypes from multiprocessing.pool import ThreadPool @@ -585,7 +586,6 @@ class ApiClient(object): :return: date. """ try: - from dateutil.parser import parse return parse(string).date() except ImportError: return string @@ -604,7 +604,6 @@ class ApiClient(object): :return: datetime. """ try: - from dateutil.parser import parse return parse(string) except ImportError: return string From b1f41083071ccb982e7b7dcb2e08279e54846545 Mon Sep 17 00:00:00 2001 From: Sai Giridhar P Date: Sun, 3 Nov 2019 12:28:39 +0530 Subject: [PATCH 064/180] [python][metadata]: Adding license and author fields (#4318) * fix(license): Fixing the license and author information * fix(license): Fixing the license and author information * fix(metadata): Adding default values for contact details and license fields * fix(metadata): Adding default values for contact details and license fields --- python-experimental/setup.mustache | 6 ++++-- setup.mustache | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 80006ded16..bf9ffe07d0 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -29,14 +29,16 @@ setup( name=NAME, version=VERSION, description="{{appName}}", - author_email="{{infoEmail}}", + author="{{#infoName}}{{infoName}}{{/infoName}}{{^infoName}}OpenAPI Generator community{{/infoName}}", + author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], install_requires=REQUIRES, extras_require=EXTRAS, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, - long_description="""\ + {{#licenseInfo}}license="{{licenseInfo}}", + {{/licenseInfo}}long_description="""\ {{appDescription}} # noqa: E501 """ ) diff --git a/setup.mustache b/setup.mustache index 588851cc7b..a41fee1467 100644 --- a/setup.mustache +++ b/setup.mustache @@ -28,13 +28,15 @@ setup( name=NAME, version=VERSION, description="{{appName}}", - author_email="{{infoEmail}}", + author="{{#infoName}}{{infoName}}{{/infoName}}{{^infoName}}OpenAPI Generator community{{/infoName}}", + author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], install_requires=REQUIRES, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, - long_description="""\ + {{#licenseInfo}}license="{{licenseInfo}}", + {{/licenseInfo}}long_description="""\ {{appDescription}} # noqa: E501 """ ) From 20f072747c3b848a1bd22cf4758aed92033d93ef Mon Sep 17 00:00:00 2001 From: Arun Date: Mon, 4 Nov 2019 14:02:53 +0530 Subject: [PATCH 065/180] [Python-Experimental]: Remove redundant else statement (#4324) * [Python-Experimental]: Remove redundant else statement * Run petstore --- python-experimental/api_client.mustache | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index aec1ef3753..25ca4b5043 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -346,18 +346,19 @@ class ApiClient(object): _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host, _check_type) - else: - thread = self.pool.apply_async(self.__call_api, (resource_path, - method, path_params, query_params, - header_params, body, - post_params, files, - response_type, auth_settings, - _return_http_data_only, - collection_formats, - _preload_content, - _request_timeout, - _host, _check_type)) - return thread + + return self.pool.apply_async(self.__call_api, (resource_path, + method, path_params, + query_params, + header_params, body, + post_params, files, + response_type, + auth_settings, + _return_http_data_only, + collection_formats, + _preload_content, + _request_timeout, + _host, _check_type)) def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, _preload_content=True, From db2880d027684a57d566f2ed77b075f1050216a5 Mon Sep 17 00:00:00 2001 From: Arun Date: Thu, 7 Nov 2019 08:19:54 +0530 Subject: [PATCH 066/180] [Python] [Performance] Avoid unnessacary checks inside the loop (#4305) --- api_client.mustache | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 790ec22046..3bf085e190 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -629,11 +629,11 @@ class ApiClient(object): return data kwargs = {} - if klass.openapi_types is not None: + if (data is not None and + klass.openapi_types is not None and + isinstance(data, (list, dict))): for attr, attr_type in six.iteritems(klass.openapi_types): - if (data is not None and - klass.attribute_map[attr] in data and - isinstance(data, (list, dict))): + if klass.attribute_map[attr] in data: value = data[klass.attribute_map[attr]] kwargs[attr] = self.__deserialize(value, attr_type) From dda753800d9986250c64f9a47f684b44b1e7a3c3 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sat, 16 Nov 2019 16:49:19 -0800 Subject: [PATCH 067/180] Fixes Python client Configuration class so each instance uses its own dicts (#4485) --- configuration.mustache | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 9677031a8c..6e02b238da 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -4,7 +4,6 @@ from __future__ import absolute_import -import copy import logging {{^asyncio}} import multiprocessing @@ -16,21 +15,7 @@ import six from six.moves import http_client as httplib -class TypeWithDefault(type): - def __init__(cls, name, bases, dct): - super(TypeWithDefault, cls).__init__(name, bases, dct) - cls._default = None - - def __call__(cls, **kwargs): - if cls._default is None: - cls._default = type.__call__(cls, **kwargs) - return copy.copy(cls._default) - - def set_default(cls, default): - cls._default = copy.copy(default) - - -class Configuration(six.with_metaclass(TypeWithDefault, object)): +class Configuration(object): """NOTE: This class is auto generated by OpenAPI Generator Ref: https://openapi-generator.tech @@ -44,7 +29,7 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): """ def __init__(self, host="{{{basePath}}}", - api_key={}, api_key_prefix={}, + api_key=None, api_key_prefix=None, username="", password=""): """Constructor """ @@ -55,10 +40,14 @@ class Configuration(six.with_metaclass(TypeWithDefault, object)): """Temp file folder for downloading files """ # Authentication Settings - self.api_key = api_key + self.api_key = {} + if api_key: + self.api_key = api_key """dict to store API key(s) """ - self.api_key_prefix = api_key_prefix + self.api_key_prefix = {} + if api_key_prefix: + self.api_key_prefix = api_key_prefix """dict to store API prefix (e.g. Bearer) """ self.refresh_api_key_hook = None From 360acdc4bdd25532e9808afea8dae4ba0b4190bd Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 9 Dec 2019 19:29:14 -0800 Subject: [PATCH 068/180] Updates python and python-flask travis CI testing to use python 3.6, 3.7, and 3.8 (#4743) --- travis.mustache | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/travis.mustache b/travis.mustache index 86211e2d4a..388de83128 100644 --- a/travis.mustache +++ b/travis.mustache @@ -6,8 +6,9 @@ python: - "3.3" - "3.4" - "3.5" - #- "3.5-dev" # 3.5 development branch - #- "nightly" # points to the latest development branch e.g. 3.6-dev + - "3.6" + - "3.7" + - "3.8" # command to install dependencies install: "pip install -r requirements.txt" # command to run tests From f543f21b343301ec0959b9b3d83de8fec19b6250 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Thu, 12 Dec 2019 21:21:28 +0800 Subject: [PATCH 069/180] fix package name in tox.ini (#4776) --- tox.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.mustache b/tox.mustache index 63d12fdeae..585feb3c68 100644 --- a/tox.mustache +++ b/tox.mustache @@ -16,5 +16,5 @@ commands= [] {{/asyncio}} {{#asyncio}} - pytest -v --cov petstore_api + pytest -v --cov {{{packageName}}} {{/asyncio}} From 52924f1e65e55e7b7abcf7f7120b648de55ad007 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sat, 14 Dec 2019 18:18:41 -0800 Subject: [PATCH 070/180] [Python] Adds allOf/oneOf/anyOf composed models (#4446) * Adds composed model support for allOf oneOf anyOf * Moves discriminator into discriminator() class method, adds test_deserialize_lizard, adds setting discriminator using allOf schema --- README.mustache | 2 +- python-experimental/README.mustache | 55 +++ python-experimental/README_common.mustache | 74 ++++ .../README_onlypackage.mustache | 44 ++ python-experimental/__init__model.mustache | 7 + python-experimental/__init__package.mustache | 36 ++ python-experimental/api.mustache | 1 + python-experimental/api_doc.mustache | 11 +- python-experimental/api_doc_example.mustache | 13 +- python-experimental/model.mustache | 26 +- python-experimental/model_doc.mustache | 6 +- .../model_templates/classvar_allowed.mustache | 16 - .../classvar_openapi_validations.mustache | 42 -- .../model_templates/classvars.mustache | 119 ++++++ .../method_discriminator.mustache | 12 + .../method_init_composed.mustache | 42 ++ .../method_init_normal.mustache | 21 + .../method_init_shared.mustache | 23 + .../method_set_attribute.mustache | 49 +++ .../methods_init_properties.mustache | 126 ------ .../methods_setattr_getattr_composed.mustache | 61 +++ .../methods_setattr_getattr_normal.mustache | 24 ++ .../model_templates/methods_shared.mustache | 15 + .../methods_todict_tostr_eq_shared.mustache | 29 ++ .../methods_tostr_eq_simple.mustache | 22 + .../model_templates/model_composed.mustache | 56 +++ .../model_templates/model_normal.mustache | 74 +--- .../model_templates/model_simple.mustache | 40 +- python-experimental/model_test.mustache | 33 ++ python-experimental/model_utils.mustache | 403 +++++++++++++++--- 30 files changed, 1103 insertions(+), 379 deletions(-) create mode 100644 python-experimental/README.mustache create mode 100644 python-experimental/README_common.mustache create mode 100644 python-experimental/README_onlypackage.mustache create mode 100644 python-experimental/__init__model.mustache create mode 100644 python-experimental/__init__package.mustache delete mode 100644 python-experimental/model_templates/classvar_allowed.mustache delete mode 100644 python-experimental/model_templates/classvar_openapi_validations.mustache create mode 100644 python-experimental/model_templates/classvars.mustache create mode 100644 python-experimental/model_templates/method_discriminator.mustache create mode 100644 python-experimental/model_templates/method_init_composed.mustache create mode 100644 python-experimental/model_templates/method_init_normal.mustache create mode 100644 python-experimental/model_templates/method_init_shared.mustache create mode 100644 python-experimental/model_templates/method_set_attribute.mustache delete mode 100644 python-experimental/model_templates/methods_init_properties.mustache create mode 100644 python-experimental/model_templates/methods_setattr_getattr_composed.mustache create mode 100644 python-experimental/model_templates/methods_setattr_getattr_normal.mustache create mode 100644 python-experimental/model_templates/methods_shared.mustache create mode 100644 python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache create mode 100644 python-experimental/model_templates/methods_tostr_eq_simple.mustache create mode 100644 python-experimental/model_templates/model_composed.mustache create mode 100644 python-experimental/model_test.mustache diff --git a/README.mustache b/README.mustache index 144f72427e..94d72af33d 100644 --- a/README.mustache +++ b/README.mustache @@ -31,7 +31,7 @@ pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git Then import the package: ```python -import {{{packageName}}} +import {{{packageName}}} ``` ### Setuptools diff --git a/python-experimental/README.mustache b/python-experimental/README.mustache new file mode 100644 index 0000000000..f26408cf66 --- /dev/null +++ b/python-experimental/README.mustache @@ -0,0 +1,55 @@ +# {{{projectName}}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage +### pip install + +If the python package is hosted on a repository, you can install directly using: + +```sh +pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git +``` +(you may need to run `pip` with root permission: `sudo pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git`) + +Then import the package: +```python +import {{{packageName}}} +``` + +### Setuptools + +Install via [Setuptools](http://pypi.python.org/pypi/setuptools). + +```sh +python setup.py install --user +``` +(or `sudo python setup.py install` to install the package for all users) + +Then import the package: +```python +import {{{packageName}}} +``` + +## Getting Started + +Please follow the [installation procedure](#installation--usage) and then run the following: + +{{> python-experimental/README_common }} diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache new file mode 100644 index 0000000000..a8b66b0bed --- /dev/null +++ b/python-experimental/README_common.mustache @@ -0,0 +1,74 @@ +```python +from __future__ import print_function +import time +import {{{packageName}}} +from pprint import pprint +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +{{> python_doc_auth_partial}} +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Create an instance of the API class +api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} +{{/allParams}} + +try: +{{#summary}} # {{{.}}} +{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} +except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +``` + +## Documentation for API Endpoints + +All URIs are relative to *{{basePath}}* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} + +## Documentation For Models + +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{unescapedDescription}}}.md) +{{/model}}{{/models}} + +## Documentation For Authorization + +{{^authMethods}} + All endpoints do not require authorization. +{{/authMethods}} +{{#authMethods}} +{{#last}} Authentication schemes defined for the API:{{/last}} +## {{{name}}} + +{{#isApiKey}} +- **Type**: API key +- **API key parameter name**: {{{keyParamName}}} +- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} +{{/isApiKey}} +{{#isBasic}} +{{^isBasicBearer}} +- **Type**: HTTP basic authentication +{{/isBasicBearer}} +{{#isBasicBearer}} +- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} +{{/isBasicBearer}} +{{/isBasic}} +{{#isOAuth}} +- **Type**: OAuth +- **Flow**: {{{flow}}} +- **Authorization URL**: {{{authorizationUrl}}} +- **Scopes**: {{^scopes}}N/A{{/scopes}} +{{#scopes}} - **{{{scope}}}**: {{{description}}} +{{/scopes}} +{{/isOAuth}} + +{{/authMethods}} + +## Author + +{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} +{{/hasMore}}{{/apis}}{{/apiInfo}} diff --git a/python-experimental/README_onlypackage.mustache b/python-experimental/README_onlypackage.mustache new file mode 100644 index 0000000000..11c002c9aa --- /dev/null +++ b/python-experimental/README_onlypackage.mustache @@ -0,0 +1,44 @@ +# {{{projectName}}} +{{#appDescription}} +{{{appDescription}}} +{{/appDescription}} + +The `{{packageName}}` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: + +- API version: {{appVersion}} +- Package version: {{packageVersion}} +{{^hideGenerationTimestamp}} +- Build date: {{generatedDate}} +{{/hideGenerationTimestamp}} +- Build package: {{generatorClass}} +{{#infoUrl}} +For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) +{{/infoUrl}} + +## Requirements. + +Python 2.7 and 3.4+ + +## Installation & Usage + +This python library package is generated without supporting files like setup.py or requirements files + +To be able to use it, you will need these dependencies in your own package that uses this library: + +* urllib3 >= 1.15 +* six >= 1.10 +* certifi +* python-dateutil +{{#asyncio}} +* aiohttp +{{/asyncio}} +{{#tornado}} +* tornado>=4.2,<5 +{{/tornado}} + +## Getting Started + +In your own code, to use this library to connect and interact with {{{projectName}}}, +you can run the following: + +{{> python-experimental/README_common }} diff --git a/python-experimental/__init__model.mustache b/python-experimental/__init__model.mustache new file mode 100644 index 0000000000..ca86cb8a62 --- /dev/null +++ b/python-experimental/__init__model.mustache @@ -0,0 +1,7 @@ +# coding: utf-8 + +# flake8: noqa +{{>partial_header}} + +# we can not import model classes here because that would create a circular +# reference which would not work in python2 diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache new file mode 100644 index 0000000000..b5224a5821 --- /dev/null +++ b/python-experimental/__init__package.mustache @@ -0,0 +1,36 @@ +# coding: utf-8 + +# flake8: noqa + +{{>partial_header}} + +from __future__ import absolute_import + +__version__ = "{{packageVersion}}" + +# import apis into sdk package +{{#apiInfo}} +{{#apis}} +from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}} +{{/apiInfo}} + +# import ApiClient +from {{packageName}}.api_client import ApiClient + +# import Configuration +from {{packageName}}.configuration import Configuration + +# import exceptions +from {{packageName}}.exceptions import OpenApiException +from {{packageName}}.exceptions import ApiTypeError +from {{packageName}}.exceptions import ApiValueError +from {{packageName}}.exceptions import ApiKeyError +from {{packageName}}.exceptions import ApiException + +# import models into sdk package +{{#models}} +{{#model}} +from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} +{{/model}} +{{/models}} diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 651559cf4f..734c490cab 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -5,6 +5,7 @@ from __future__ import absolute_import import re # noqa: F401 +import sys # noqa: F401 # python 2 and python 3 compatibility library import six diff --git a/python-experimental/api_doc.mustache b/python-experimental/api_doc.mustache index 5cc638a2eb..4feb612f1c 100644 --- a/python-experimental/api_doc.mustache +++ b/python-experimental/api_doc.mustache @@ -35,19 +35,16 @@ Method | HTTP request | Description {{#isOAuth}} * OAuth Authentication ({{name}}): {{/isOAuth }} -{{> api_doc_example }} {{/authMethods}} {{/hasAuthMethods}} -{{^hasAuthMethods}} -{{> api_doc_example }} -{{/hasAuthMethods}} +{{> python-experimental/api_doc_example }} ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes ------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | -{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | defaults to {{{.}}} -{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | +{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | defaults to {{{.}}} +{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} {{/optionalParams}} ### Return type diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index e5eeee6b0e..8a6beabd2d 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -2,7 +2,6 @@ from __future__ import print_function import time import {{{packageName}}} -from {{{packageName}}}.rest import ApiException from pprint import pprint {{> python_doc_auth_partial}} {{#hasAuthMethods}} @@ -18,40 +17,40 @@ api_instance = {{{packageName}}}.{{{classname}}}() {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} - {{#requiredParams}} {{^hasMore}} + # example passing only required values which don't have defaults set try: {{#summary}} # {{{.}}} {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}){{#returnType}} pprint(api_response){{/returnType}} -except ApiException as e: +except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/hasMore}} {{/requiredParams}} - {{#optionalParams}} {{^hasMore}} + # example passing only required values which don't have defaults set # and optional values try: {{#summary}} # {{{.}}} {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}){{#returnType}} pprint(api_response){{/returnType}} -except ApiException as e: +except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/hasMore}} {{/optionalParams}} - {{^requiredParams}} {{^optionalParams}} + # example, this endpoint has no required or optional parameters try: {{#summary}} # {{{.}}} {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}(){{#returnType}} pprint(api_response){{/returnType}} -except ApiException as e: +except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/optionalParams}} {{/requiredParams}} diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 2513d6b3f8..0ca198ddf9 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -2,37 +2,31 @@ {{>partial_header}} -import pprint # noqa: F401 +from __future__ import absolute_import import re # noqa: F401 +import sys # noqa: F401 import six # noqa: F401 -from {{packageName}}.exceptions import ( # noqa: F401 - ApiKeyError, - ApiTypeError, - ApiValueError, -) from {{packageName}}.model_utils import ( # noqa: F401 + ModelComposed, ModelNormal, ModelSimple, - check_allowed_values, - check_validations, date, datetime, file_type, - get_simple_class, int, - model_to_dict, none_type, str, - type_error_message, - validate_and_convert_types + validate_get_composed_info, ) -{{#models}}{{#model}}{{#imports}}{{.}} -{{/imports}}{{/model}}{{/models}} - {{#models}} {{#model}} +{{#imports}} +{{{.}}} +{{/imports}} + + {{^interfaces}} {{#isAlias}} {{> python-experimental/model_templates/model_simple }} @@ -43,7 +37,7 @@ from {{packageName}}.model_utils import ( # noqa: F401 {{/interfaces}} {{#interfaces}} {{#-last}} -{{> python-experimental/model_templates/model_normal }} +{{> python-experimental/model_templates/model_composed }} {{/-last}} {{/interfaces}} {{/model}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index 79abbf6130..a1e57131bc 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -7,16 +7,16 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- {{#requiredVars}} {{^defaultValue}} -**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} {{/defaultValue}} {{/requiredVars}} {{#requiredVars}} {{#defaultValue}} -**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} {{/defaultValue}} {{/requiredVars}} {{#optionalVars}} -**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} {{/optionalVars}} {{#additionalPropertiesType}} **any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional] diff --git a/python-experimental/model_templates/classvar_allowed.mustache b/python-experimental/model_templates/classvar_allowed.mustache deleted file mode 100644 index 2414be114a..0000000000 --- a/python-experimental/model_templates/classvar_allowed.mustache +++ /dev/null @@ -1,16 +0,0 @@ - allowed_values = { -{{#allVars}} -{{#isEnum}} - ('{{name}}',): { -{{#isNullable}} - 'None': None, -{{/isNullable}} -{{#allowableValues}} -{{#enumVars}} - '{{name}}': {{{value}}}, -{{/enumVars}} -{{/allowableValues}} - }, -{{/isEnum}} -{{/allVars}} - } \ No newline at end of file diff --git a/python-experimental/model_templates/classvar_openapi_validations.mustache b/python-experimental/model_templates/classvar_openapi_validations.mustache deleted file mode 100644 index 1cc7b58550..0000000000 --- a/python-experimental/model_templates/classvar_openapi_validations.mustache +++ /dev/null @@ -1,42 +0,0 @@ - openapi_types = { -{{#allVars}} - '{{name}}': ({{{dataType}}},), # noqa: E501 -{{/allVars}} - } - - validations = { -{{#allVars}} -{{#hasValidation}} - ('{{name}}',): { -{{#maxLength}} - 'max_length': {{maxLength}}, -{{/maxLength}} -{{#minLength}} - 'min_length': {{minLength}}, -{{/minLength}} -{{#maxItems}} - 'max_items': {{maxItems}}, -{{/maxItems}} -{{#minItems}} - 'min_items': {{minItems}}, -{{/minItems}} -{{#maximum}} - {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, -{{/maximum}} -{{#minimum}} - {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, -{{/minimum}} -{{#pattern}} - 'regex': { - 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} - {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} - }, -{{/pattern}} - }, -{{/hasValidation}} -{{/allVars}} - } - - additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} - - discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} \ No newline at end of file diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache new file mode 100644 index 0000000000..fcd8a71fd1 --- /dev/null +++ b/python-experimental/model_templates/classvars.mustache @@ -0,0 +1,119 @@ + allowed_values = { +{{#requiredVars}} +{{#isEnum}} + ('{{name}}',): { +{{#isNullable}} + 'None': None, +{{/isNullable}} +{{#allowableValues}} +{{#enumVars}} + '{{name}}': {{{value}}}, +{{/enumVars}} +{{/allowableValues}} + }, +{{/isEnum}} +{{/requiredVars}} +{{#optionalVars}} +{{#isEnum}} + ('{{name}}',): { +{{#isNullable}} + 'None': None, +{{/isNullable}} +{{#allowableValues}} +{{#enumVars}} + '{{name}}': {{{value}}}, +{{/enumVars}} +{{/allowableValues}} + }, +{{/isEnum}} +{{/optionalVars}} + } + + openapi_types = { +{{#requiredVars}} + '{{name}}': ({{{dataType}}},), # noqa: E501 +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': ({{{dataType}}},), # noqa: E501 +{{/optionalVars}} + } + + validations = { +{{#requiredVars}} +{{#hasValidation}} + ('{{name}}',): { +{{#maxLength}} + 'max_length': {{maxLength}}, +{{/maxLength}} +{{#minLength}} + 'min_length': {{minLength}}, +{{/minLength}} +{{#maxItems}} + 'max_items': {{maxItems}}, +{{/maxItems}} +{{#minItems}} + 'min_items': {{minItems}}, +{{/minItems}} +{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, +{{/maximum}} +{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, +{{/minimum}} +{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + }, +{{/pattern}} + }, +{{/hasValidation}} +{{/requiredVars}} +{{#optionalVars}} +{{#hasValidation}} + ('{{name}}',): { +{{#maxLength}} + 'max_length': {{maxLength}}, +{{/maxLength}} +{{#minLength}} + 'min_length': {{minLength}}, +{{/minLength}} +{{#maxItems}} + 'max_items': {{maxItems}}, +{{/maxItems}} +{{#minItems}} + 'min_items': {{minItems}}, +{{/minItems}} +{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, +{{/maximum}} +{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, +{{/minimum}} +{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + }, +{{/pattern}} + }, +{{/hasValidation}} +{{/optionalVars}} + } + + additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} + + @staticmethod + def discriminator(): + return {{^discriminator}}None{{/discriminator}}{{#discriminator}}{ + '{{{discriminatorName}}}': { +{{#children}} + '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': {{{classname}}}, +{{/children}} +{{^children}} +{{#mappedModels}} + '{{mappingName}}': {{{modelName}}}, +{{/mappedModels}} +{{/children}} + }, + }{{/discriminator}} \ No newline at end of file diff --git a/python-experimental/model_templates/method_discriminator.mustache b/python-experimental/model_templates/method_discriminator.mustache new file mode 100644 index 0000000000..c4baa722ff --- /dev/null +++ b/python-experimental/model_templates/method_discriminator.mustache @@ -0,0 +1,12 @@ + @classmethod + def get_discriminator_class(cls, from_server, data): + """Returns the child class specified by the discriminator""" + discriminator = cls.discriminator() + discr_propertyname_py = list(discriminator.keys())[0] + discr_propertyname_js = cls.attribute_map[discr_propertyname_py] + if from_server: + class_name = data[discr_propertyname_js] + else: + class_name = data[discr_propertyname_py] + class_name_to_discr_class = discriminator[discr_propertyname_py] + return class_name_to_discr_class.get(class_name) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache new file mode 100644 index 0000000000..5ed5993fe9 --- /dev/null +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -0,0 +1,42 @@ + required_properties = set([ + '_data_store', + '_check_type', + '_from_server', + '_path_to_item', + '_configuration', + '_composed_instances', + '_var_name_to_model_instances', + '_additional_properties_model_instances', + ]) + +{{> python-experimental/model_templates/method_init_shared }} + + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration + + constant_args = { + '_check_type': _check_type, + '_path_to_item': _path_to_item, + '_from_server': _from_server, + '_configuration': _configuration, + } + model_args = { +{{#requiredVars}} + '{{name}}': {{name}}, +{{/requiredVars}} + } + model_args.update(kwargs) + composed_info = validate_get_composed_info( + constant_args, model_args, self) + self._composed_instances = composed_info[0] + self._var_name_to_model_instances = composed_info[1] + self._additional_properties_model_instances = composed_info[2] + +{{#requiredVars}} + self.{{name}} = {{name}} +{{/requiredVars}} + for var_name, var_value in six.iteritems(kwargs): + setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache new file mode 100644 index 0000000000..b053427a79 --- /dev/null +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -0,0 +1,21 @@ + required_properties = set([ + '_data_store', + '_check_type', + '_from_server', + '_path_to_item', + '_configuration', + ]) + +{{> python-experimental/model_templates/method_init_shared }} + + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration + +{{#requiredVars}} + self.{{name}} = {{name}} +{{/requiredVars}} + for var_name, var_value in six.iteritems(kwargs): + setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache new file mode 100644 index 0000000000..2f3b70ea69 --- /dev/null +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -0,0 +1,23 @@ + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 + """{{classname}} - a model defined in OpenAPI + +{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} +{{/hasMore}}{{/requiredVars}} + Keyword Args:{{#requiredVars}}{{#defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _from_server (bool): True if the data is from the server + False if the data is from the client (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done.{{#optionalVars}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} + """ \ No newline at end of file diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache new file mode 100644 index 0000000000..f4a36e42f2 --- /dev/null +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -0,0 +1,49 @@ + def set_attribute(self, name, value): + # this is only used to set properties on self + + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + + if name in self.openapi_types: + required_types_mixed = self.openapi_types[name] + elif self.additional_properties_type is None: + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) + elif self.additional_properties_type is not None: + required_types_mixed = self.additional_properties_type + + if get_simple_class(name) != str: + error_msg = type_error_message( + var_name=name, + var_value=name, + valid_classes=(str,), + key_type=True + ) + raise ApiTypeError( + error_msg, + path_to_item=path_to_item, + valid_classes=(str,), + key_type=True + ) + + if self._check_type: + value = validate_and_convert_types( + value, required_types_mixed, path_to_item, self._from_server, + self._check_type, configuration=self._configuration) + if (name,) in self.allowed_values: + check_allowed_values( + self.allowed_values, + (name,), + value + ) + if (name,) in self.validations: + check_validations( + self.validations, + (name,), + value + ) + self.__dict__['_data_store'][name] = value \ No newline at end of file diff --git a/python-experimental/model_templates/methods_init_properties.mustache b/python-experimental/model_templates/methods_init_properties.mustache deleted file mode 100644 index dab632efab..0000000000 --- a/python-experimental/model_templates/methods_init_properties.mustache +++ /dev/null @@ -1,126 +0,0 @@ - def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 - """{{classname}} - a model defined in OpenAPI - -{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} -{{/hasMore}}{{/requiredVars}} - Keyword Args:{{#requiredVars}}{{#defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} - _check_type (bool): if True, values for parameters in openapi_types - will be type checked and a TypeError will be - raised if the wrong type is input. - Defaults to True - _path_to_item (tuple/list): This is a list of keys or values to - drill down to the model in received_data - when deserializing a response - _from_server (bool): True if the data is from the server - False if the data is from the client (default) - _configuration (Configuration): the instance to use when - deserializing a file_type parameter. - If passed, type conversion is attempted - If omitted no type conversion is done.{{#optionalVars}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} - """ - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration - -{{#requiredVars}} - self.__set_item('{{name}}', {{name}}) -{{/requiredVars}} - for var_name, var_value in six.iteritems(kwargs): - self.__set_item(var_name, var_value) - - def __set_item(self, name, value): - path_to_item = [] - if self._path_to_item: - path_to_item.extend(self._path_to_item) - path_to_item.append(name) - - if name in self.openapi_types: - required_types_mixed = self.openapi_types[name] - elif self.additional_properties_type is None: - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), - path_to_item - ) - elif self.additional_properties_type is not None: - required_types_mixed = self.additional_properties_type - - if get_simple_class(name) != str: - error_msg = type_error_message( - var_name=name, - var_value=name, - valid_classes=(str,), - key_type=True - ) - raise ApiTypeError( - error_msg, - path_to_item=path_to_item, - valid_classes=(str,), - key_type=True - ) - - if self._check_type: - value = validate_and_convert_types( - value, required_types_mixed, path_to_item, self._from_server, - self._check_type, configuration=self._configuration) - if (name,) in self.allowed_values: - check_allowed_values( - self.allowed_values, - (name,), - value - ) - if (name,) in self.validations: - check_validations( - self.validations, - (name,), - value - ) - self._data_store[name] = value - - def __get_item(self, name): - if name in self._data_store: - return self._data_store[name] - - path_to_item = [] - if self._path_to_item: - path_to_item.extend(self._path_to_item) - path_to_item.append(name) - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), - [name] - ) - - def __setitem__(self, name, value): - """this allows us to set values with instance[field_name] = val""" - self.__set_item(name, value) - - def __getitem__(self, name): - """this allows us to get a value with val = instance[field_name]""" - return self.__get_item(name) -{{#allVars}} - - @property - def {{name}}(self): - """Gets the {{name}} of this {{classname}}. # noqa: E501 -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - - Returns: - ({{{dataType}}}): The {{name}} of this {{classname}}. # noqa: E501 - """ - return self.__get_item('{{name}}') - - @{{name}}.setter - def {{name}}(self, value): - """Sets the {{name}} of this {{classname}}. # noqa: E501 -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - """ - return self.__set_item('{{name}}', value) -{{/allVars}} \ No newline at end of file diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache new file mode 100644 index 0000000000..e5eee88a96 --- /dev/null +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -0,0 +1,61 @@ + def __setattr__(self, name, value): + """this allows us to set a value with instance.field_name = val""" + if name in self.required_properties: + self.__dict__[name] = value + return + + # set the attribute on the correct instance + model_instances = self._var_name_to_model_instances.get( + name, self._additional_properties_model_instances) + if model_instances: + for model_instance in model_instances: + if model_instance == self: + self.set_attribute(name, value) + else: + setattr(model_instance, name, value) + if name not in self._var_name_to_model_instances: + # we assigned an additional property + self.__dict__['_var_name_to_model_instances'][name] = ( + model_instance + ) + return None + + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) + + def __getattr__(self, name): + """this allows us to get a value with val = instance.field_name""" + if name in self.required_properties: + return self.__dict__[name] + + # get the attribute from the correct instance + model_instances = self._var_name_to_model_instances.get( + name, self._additional_properties_model_instances) + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + if model_instances: + values = set() + for model_instance in model_instances: + if name in model_instance._data_store: + values.add(model_instance._data_store[name]) + if len(values) == 1: + return list(values)[0] + raise ApiValueError( + "Values stored for property {0} in {1} difffer when looking " + "at self and self's composed instances. All values must be " + "the same".format(name, type(self).__name__), + path_to_item + ) + + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) \ No newline at end of file diff --git a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache new file mode 100644 index 0000000000..f92663ab20 --- /dev/null +++ b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache @@ -0,0 +1,24 @@ + def __setattr__(self, name, value): + """this allows us to set a value with instance.field_name = val""" + if name in self.required_properties: + self.__dict__[name] = value + return + + self.set_attribute(name, value) + + def __getattr__(self, name): + """this allows us to get a value with val = instance.field_name""" + if name in self.required_properties: + return self.__dict__[name] + + if name in self.__dict__['_data_store']: + return self.__dict__['_data_store'][name] + + path_to_item = [] + if self._path_to_item: + path_to_item.extend(self._path_to_item) + path_to_item.append(name) + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + [name] + ) \ No newline at end of file diff --git a/python-experimental/model_templates/methods_shared.mustache b/python-experimental/model_templates/methods_shared.mustache new file mode 100644 index 0000000000..d3cf66e41b --- /dev/null +++ b/python-experimental/model_templates/methods_shared.mustache @@ -0,0 +1,15 @@ + def __setitem__(self, name, value): + """this allows us to set values with instance[field_name] = val""" + self.__setattr__(name, value) + + def __getitem__(self, name): + """this allows us to get a value with val = instance[field_name]""" + return self.__getattr__(name) + + def __repr__(self): + """For `print` and `pprint`""" + return self.to_str() + + def __ne__(self, other): + """Returns true if both objects are not equal""" + return not self == other \ No newline at end of file diff --git a/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache b/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache new file mode 100644 index 0000000000..d01d49ad77 --- /dev/null +++ b/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache @@ -0,0 +1,29 @@ + def to_dict(self): + """Returns the model properties as a dict""" + return model_to_dict(self, serialize=False) + + def to_str(self): + """Returns the string representation of the model""" + return pprint.pformat(self.to_dict()) + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, self.__class__): + return False + + if not set(self._data_store.keys()) == set(other._data_store.keys()): + return False + for _var_name, this_val in six.iteritems(self._data_store): + that_val = other._data_store[_var_name] + types = set() + types.add(this_val.__class__) + types.add(that_val.__class__) + vals_equal = this_val == that_val + if (not six.PY3 and + len(types) == 2 and unicode in types): # noqa: F821 + vals_equal = ( + this_val.encode('utf-8') == that_val.encode('utf-8') + ) + if not vals_equal: + return False + return True \ No newline at end of file diff --git a/python-experimental/model_templates/methods_tostr_eq_simple.mustache b/python-experimental/model_templates/methods_tostr_eq_simple.mustache new file mode 100644 index 0000000000..0bba565d22 --- /dev/null +++ b/python-experimental/model_templates/methods_tostr_eq_simple.mustache @@ -0,0 +1,22 @@ + def to_str(self): + """Returns the string representation of the model""" + return str(self.value) + + def __eq__(self, other): + """Returns true if both objects are equal""" + if not isinstance(other, self.__class__): + return False + + this_val = self._data_store['value'] + that_val = other._data_store['value'] + types = set() + types.add(this_val.__class__) + types.add(that_val.__class__) + vals_equal = this_val == that_val + if not six.PY3 and len(types) == 2 and unicode in types: # noqa: F821 + vals_equal = ( + this_val.encode('utf-8') == that_val.encode('utf-8') + ) + if not vals_equal: + return False + return True \ No newline at end of file diff --git a/python-experimental/model_templates/model_composed.mustache b/python-experimental/model_templates/model_composed.mustache new file mode 100644 index 0000000000..d53d89cef2 --- /dev/null +++ b/python-experimental/model_templates/model_composed.mustache @@ -0,0 +1,56 @@ +class {{unescapedDescription}}(ModelComposed): + """NOTE: This class is auto generated by OpenAPI Generator. + Ref: https://openapi-generator.tech + + Do not edit the class manually. + + Attributes: +{{> python-experimental/model_templates/docstring_allowed }} + attribute_map (dict): The key is attribute name + and the value is json key in definition. + discriminator_value_class_map (dict): A dict to go from the discriminator + variable value to the discriminator class name. +{{> python-experimental/model_templates/docstring_openapi_validations }} + """ + +{{> python-experimental/model_templates/classvars }} + + attribute_map = { +{{#requiredVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/optionalVars}} + } + +{{> python-experimental/model_templates/method_init_composed }} + + @staticmethod + def _composed_schemas(): + # we need this here to make our import statements work + # we must store _composed_schemas in here so the code is only run + # when we invoke this method. If we kept this at the class + # level we would get an error beause the class level + # code would be run when this module is imported, and these composed + # classes don't exist yet because their module has not finished + # loading + return { + 'anyOf': [ +{{#anyOf}} + {{{.}}}, +{{/anyOf}} + ], + 'allOf': [ +{{#allOf}} + {{{.}}}, +{{/allOf}} + ], + 'oneOf': [ +{{#oneOf}} + {{{.}}}, +{{/oneOf}} + ], + }{{#discriminator}} + +{{> python-experimental/model_templates/method_discriminator }}{{/discriminator}} \ No newline at end of file diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache index c4e707e036..8bfe6ada48 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/python-experimental/model_templates/model_normal.mustache @@ -1,4 +1,4 @@ -class {{classname}}(ModelNormal): +class {{unescapedDescription}}(ModelNormal): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -13,69 +13,21 @@ class {{classname}}(ModelNormal): {{> python-experimental/model_templates/docstring_openapi_validations }} """ -{{> python-experimental/model_templates/classvar_allowed }} +{{> python-experimental/model_templates/classvars }} attribute_map = { -{{#allVars}} - '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} # noqa: E501 -{{/allVars}} +{{#requiredVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': '{{baseName}}', # noqa: E501 +{{/optionalVars}} } -{{#discriminator}} - discriminator_value_class_map = { - {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': {{{classname}}}{{^-last}}, - {{/-last}}{{/children}} - } -{{/discriminator}} - -{{> python-experimental/model_templates/classvar_openapi_validations }} - -{{> python-experimental/model_templates/methods_init_properties }} -{{#discriminator}} - @classmethod - def get_real_child_model(cls, data): - """Returns the real base class specified by the discriminator - We assume that data has javascript keys - """ - discriminator_key = cls.attribute_map[cls.discriminator] - discriminator_value = data[discriminator_key] - return cls.discriminator_value_class_map.get(discriminator_value) - -{{/discriminator}} - def to_dict(self): - """Returns the model properties as a dict""" - return model_to_dict(self, serialize=False) - - def to_str(self): - """Returns the string representation of the model""" - return pprint.pformat(self.to_dict()) - - def __repr__(self): - """For `print` and `pprint`""" - return self.to_str() - - def __eq__(self, other): - """Returns true if both objects are equal""" - if not isinstance(other, {{classname}}): - return False + @staticmethod + def _composed_schemas(): + return None - if not set(self._data_store.keys()) == set(other._data_store.keys()): - return False - for _var_name, this_val in six.iteritems(self._data_store): - that_val = other._data_store[_var_name] - types = set() - types.add(this_val.__class__) - types.add(that_val.__class__) - vals_equal = this_val == that_val - if (not six.PY3 and - len(types) == 2 and unicode in types): # noqa: F821 - vals_equal = ( - this_val.encode('utf-8') == that_val.encode('utf-8') - ) - if not vals_equal: - return False - return True +{{> python-experimental/model_templates/method_init_normal}}{{#discriminator}} - def __ne__(self, other): - """Returns true if both objects are not equal""" - return not self == other \ No newline at end of file +{{> python-experimental/model_templates/method_discriminator }}{{/discriminator}} \ No newline at end of file diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index b5939d926c..465918dfa5 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -1,4 +1,4 @@ -class {{classname}}(ModelSimple): +class {{unescapedDescription}}(ModelSimple): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -9,38 +9,10 @@ class {{classname}}(ModelSimple): {{> python-experimental/model_templates/docstring_openapi_validations }} """ -{{> python-experimental/model_templates/classvar_allowed }} +{{> python-experimental/model_templates/classvars }} -{{> python-experimental/model_templates/classvar_openapi_validations }} + @staticmethod + def _composed_schemas(): + return None -{{> python-experimental/model_templates/methods_init_properties }} - def to_str(self): - """Returns the string representation of the model""" - return str(self.value) - - def __repr__(self): - """For `print` and `pprint`""" - return self.to_str() - - def __eq__(self, other): - """Returns true if both objects are equal""" - if not isinstance(other, {{classname}}): - return False - - this_val = self._data_store['value'] - that_val = other._data_store['value'] - types = set() - types.add(this_val.__class__) - types.add(that_val.__class__) - vals_equal = this_val == that_val - if not six.PY3 and len(types) == 2 and unicode in types: # noqa: F821 - vals_equal = ( - this_val.encode('utf-8') == that_val.encode('utf-8') - ) - if not vals_equal: - return False - return True - - def __ne__(self, other): - """Returns true if both objects are not equal""" - return not self == other \ No newline at end of file +{{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file diff --git a/python-experimental/model_test.mustache b/python-experimental/model_test.mustache new file mode 100644 index 0000000000..4fd1263b5f --- /dev/null +++ b/python-experimental/model_test.mustache @@ -0,0 +1,33 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +{{#models}} +{{#model}} +import {{packageName}} + + +class Test{{unescapedDescription}}(unittest.TestCase): + """{{unescapedDescription}} unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def test{{unescapedDescription}}(self): + """Test {{unescapedDescription}}""" + # FIXME: construct object with mandatory attributes with example values + # model = {{packageName}}.{{unescapedDescription}}() # noqa: E501 + pass + +{{/model}} +{{/models}} + +if __name__ == '__main__': + unittest.main() diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 101b5466c3..dbd592c37e 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -2,10 +2,10 @@ {{>partial_header}} -import copy from datetime import date, datetime # noqa: F401 import inspect import os +import pprint import re import tempfile @@ -38,30 +38,52 @@ else: class OpenApiModel(object): """The base class for all OpenAPIModels""" +{{> python-experimental/model_templates/method_set_attribute }} + +{{> python-experimental/model_templates/methods_shared }} + class ModelSimple(OpenApiModel): """the parent class of models whose type != object in their swagger/openapi""" +{{> python-experimental/model_templates/methods_setattr_getattr_normal }} + +{{> python-experimental/model_templates/methods_tostr_eq_simple }} + class ModelNormal(OpenApiModel): """the parent class of models whose type == object in their swagger/openapi""" +{{> python-experimental/model_templates/methods_setattr_getattr_normal }} + +{{> python-experimental/model_templates/methods_todict_tostr_eq_shared}} + + +class ModelComposed(OpenApiModel): + """the parent class of models whose type == object in their + swagger/openapi and have oneOf/allOf/anyOf""" + +{{> python-experimental/model_templates/methods_setattr_getattr_composed }} + +{{> python-experimental/model_templates/methods_todict_tostr_eq_shared}} + COERCION_INDEX_BY_TYPE = { - ModelNormal: 0, - ModelSimple: 1, - none_type: 2, - list: 3, - dict: 4, - float: 5, - int: 6, - bool: 7, - datetime: 8, - date: 9, - str: 10, - file_type: 11, + ModelComposed: 0, + ModelNormal: 1, + ModelSimple: 2, + none_type: 3, + list: 4, + dict: 5, + float: 6, + int: 7, + bool: 8, + datetime: 9, + date: 10, + str: 11, + file_type: 12, } # these are used to limit what type conversions we try to do @@ -70,6 +92,8 @@ COERCION_INDEX_BY_TYPE = { UPCONVERSION_TYPE_PAIRS = ( (str, datetime), (str, date), + (list, ModelComposed), + (dict, ModelComposed), (list, ModelNormal), (dict, ModelNormal), (str, ModelSimple), @@ -80,6 +104,8 @@ UPCONVERSION_TYPE_PAIRS = ( COERCIBLE_TYPE_PAIRS = { False: ( # client instantiation of a model with client data + # (dict, ModelComposed), + # (list, ModelComposed), # (dict, ModelNormal), # (list, ModelNormal), # (str, ModelSimple), @@ -94,6 +120,8 @@ COERCIBLE_TYPE_PAIRS = { # (float, str), ), True: ( # server -> client data + (dict, ModelComposed), + (list, ModelComposed), (dict, ModelNormal), (list, ModelNormal), (str, ModelSimple), @@ -336,6 +364,9 @@ def order_response_types(required_types): return COERCION_INDEX_BY_TYPE[list] elif isinstance(class_or_instance, dict): return COERCION_INDEX_BY_TYPE[dict] + elif (inspect.isclass(class_or_instance) + and issubclass(class_or_instance, ModelComposed)): + return COERCION_INDEX_BY_TYPE[ModelComposed] elif (inspect.isclass(class_or_instance) and issubclass(class_or_instance, ModelNormal)): return COERCION_INDEX_BY_TYPE[ModelNormal] @@ -377,7 +408,9 @@ def remove_uncoercible(required_types_classes, current_item, from_server, # convert our models to OpenApiModel required_type_class_simplified = required_type_class if isinstance(required_type_class_simplified, type): - if issubclass(required_type_class_simplified, ModelNormal): + if issubclass(required_type_class_simplified, ModelComposed): + required_type_class_simplified = ModelComposed + elif issubclass(required_type_class_simplified, ModelNormal): required_type_class_simplified = ModelNormal elif issubclass(required_type_class_simplified, ModelSimple): required_type_class_simplified = ModelSimple @@ -514,6 +547,21 @@ def deserialize_primitive(data, klass, path_to_item): ) +def fix_model_input_data(model_data, model_class): + # this is only called on classes where the input data is a dict + fixed_model_data = change_keys_js_to_python( + model_data, + model_class + ) + if model_class._composed_schemas() is not None: + for allof_class in model_class._composed_schemas()['allOf']: + fixed_model_data = change_keys_js_to_python( + fixed_model_data, + allof_class + ) + return fixed_model_data + + def deserialize_model(model_data, model_class, path_to_item, check_type, configuration, from_server): """Deserializes model_data to model instance. @@ -536,42 +584,29 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, ApiValueError ApiKeyError """ - fixed_model_data = copy.deepcopy(model_data) - - if isinstance(fixed_model_data, dict): - fixed_model_data = change_keys_js_to_python(fixed_model_data, - model_class) kw_args = dict(_check_type=check_type, _path_to_item=path_to_item, _configuration=configuration, _from_server=from_server) - if hasattr(model_class, 'get_real_child_model'): - # discriminator case - discriminator_class = model_class.get_real_child_model(model_data) - if discriminator_class: - if isinstance(model_data, list): - instance = discriminator_class(*model_data, **kw_args) - elif isinstance(model_data, dict): - fixed_model_data = change_keys_js_to_python( - fixed_model_data, - discriminator_class - ) - kw_args.update(fixed_model_data) - instance = discriminator_class(**kw_args) - else: - # all other cases - if isinstance(model_data, list): - instance = model_class(*model_data, **kw_args) - if isinstance(model_data, dict): - fixed_model_data = change_keys_js_to_python(fixed_model_data, - model_class) - kw_args.update(fixed_model_data) - instance = model_class(**kw_args) - else: - instance = model_class(model_data, **kw_args) - + used_model_class = model_class + if model_class.discriminator() is not None: + used_model_class = model_class.get_discriminator_class( + from_server, model_data) + + if issubclass(used_model_class, ModelSimple): + instance = used_model_class(value=model_data, **kw_args) + return instance + if isinstance(model_data, list): + instance = used_model_class(*model_data, **kw_args) + if isinstance(model_data, dict): + fixed_model_data = change_keys_js_to_python( + model_data, + used_model_class + ) + kw_args.update(fixed_model_data) + instance = used_model_class(**kw_args) return instance @@ -626,7 +661,7 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, key_type (bool): if True we need to convert a key type (not supported) must_convert (bool): if True we must convert check_type (bool): if True we check the type or the returned data in - ModelNormal and ModelSimple instances + ModelComposed/ModelNormal/ModelSimple instances Returns: instance (any) the fixed item @@ -790,27 +825,31 @@ def model_to_dict(model_instance, serialize=True): """ result = {} - for attr, value in six.iteritems(model_instance._data_store): - if serialize: - # we use get here because additional property key names do not - # exist in attribute_map - attr = model_instance.attribute_map.get(attr, attr) - if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) - elif isinstance(value, dict): - result[attr] = dict(map( - lambda item: (item[0], - model_to_dict(item[1], serialize=serialize)) - if hasattr(item[1], '_data_store') else item, - value.items() - )) - elif hasattr(value, '_data_store'): - result[attr] = model_to_dict(value, serialize=serialize) - else: - result[attr] = value + model_instances = [model_instance] + if model_instance._composed_schemas() is not None: + model_instances = model_instance._composed_instances + for model_instance in model_instances: + for attr, value in six.iteritems(model_instance._data_store): + if serialize: + # we use get here because additional property key names do not + # exist in attribute_map + attr = model_instance.attribute_map.get(attr, attr) + if isinstance(value, list): + result[attr] = list(map( + lambda x: model_to_dict(x, serialize=serialize) + if hasattr(x, '_data_store') else x, value + )) + elif isinstance(value, dict): + result[attr] = dict(map( + lambda item: (item[0], + model_to_dict(item[1], serialize=serialize)) + if hasattr(item[1], '_data_store') else item, + value.items() + )) + elif hasattr(value, '_data_store'): + result[attr] = model_to_dict(value, serialize=serialize) + else: + result[attr] = value return result @@ -866,3 +905,235 @@ def get_py3_class_name(input_class): elif input_class == int: return 'int' return input_class.__name__ + + +def get_allof_instances(self, model_args, constant_args): + """ + Args: + self: the class we are handling + model_args (dict): var_name to var_value + used to make instances + constant_args (dict): var_name to var_value + used to make instances + + Returns + composed_instances (list) + """ + composed_instances = [] + for allof_class in self._composed_schemas()['allOf']: + + # transform js keys to python keys in fixed_model_args + fixed_model_args = change_keys_js_to_python( + model_args, allof_class) + + # extract a dict of only required keys from fixed_model_args + kwargs = {} + var_names = set(allof_class.openapi_types.keys()) + for var_name in var_names: + if var_name in fixed_model_args: + kwargs[var_name] = fixed_model_args[var_name] + + # and use it to make the instance + kwargs.update(constant_args) + allof_instance = allof_class(**kwargs) + composed_instances.append(allof_instance) + return composed_instances + + +def get_oneof_instance(self, model_args, constant_args): + """ + Args: + self: the class we are handling + model_args (dict): var_name to var_value + used to make instances + constant_args (dict): var_name to var_value + used to make instances + + Returns + oneof_instance (instance) + """ + oneof_instance = None + if len(self._composed_schemas()['oneOf']) == 0: + return oneof_instance + + for oneof_class in self._composed_schemas()['oneOf']: + # transform js keys to python keys in fixed_model_args + fixed_model_args = change_keys_js_to_python( + model_args, oneof_class) + + # extract a dict of only required keys from fixed_model_args + kwargs = {} + var_names = set(oneof_class.openapi_types.keys()) + for var_name in var_names: + if var_name in fixed_model_args: + kwargs[var_name] = fixed_model_args[var_name] + + # and use it to make the instance + kwargs.update(constant_args) + try: + oneof_instance = oneof_class(**kwargs) + break + except Exception: + pass + if oneof_instance is None: + raise ApiValueError( + "Invalid inputs given to generate an instance of %s. Unable to " + "make any instances of the classes in oneOf definition." % + self.__class__.__name__ + ) + return oneof_instance + + +def get_anyof_instances(self, model_args, constant_args): + """ + Args: + self: the class we are handling + model_args (dict): var_name to var_value + used to make instances + constant_args (dict): var_name to var_value + used to make instances + + Returns + anyof_instances (list) + """ + anyof_instances = [] + if len(self._composed_schemas()['anyOf']) == 0: + return anyof_instances + + for anyof_class in self._composed_schemas()['anyOf']: + # transform js keys to python keys in fixed_model_args + fixed_model_args = change_keys_js_to_python(model_args, anyof_class) + + # extract a dict of only required keys from these_model_vars + kwargs = {} + var_names = set(anyof_class.openapi_types.keys()) + for var_name in var_names: + if var_name in fixed_model_args: + kwargs[var_name] = fixed_model_args[var_name] + + # and use it to make the instance + kwargs.update(constant_args) + try: + anyof_instance = anyof_class(**kwargs) + anyof_instances.append(anyof_instance) + except Exception: + pass + if len(anyof_instances) == 0: + raise ApiValueError( + "Invalid inputs given to generate an instance of %s. Unable to " + "make any instances of the classes in anyOf definition." % + self.__class__.__name__ + ) + return anyof_instances + + +def get_additional_properties_model_instances( + composed_instances, self): + additional_properties_model_instances = [] + all_instances = [self] + all_instances.extend(composed_instances) + for instance in all_instances: + if instance.additional_properties_type is not None: + additional_properties_model_instances.append(instance) + return additional_properties_model_instances + + +def get_var_name_to_model_instances(self, composed_instances): + var_name_to_model_instances = {} + all_instances = [self] + all_instances.extend(composed_instances) + for instance in all_instances: + for var_name in instance.openapi_types: + if var_name not in var_name_to_model_instances: + var_name_to_model_instances[var_name] = [instance] + else: + var_name_to_model_instances[var_name].append(instance) + return var_name_to_model_instances + + +def get_unused_args(self, composed_instances, model_args): + unused_args = dict(model_args) + # arguments apssed to self were already converted to python names + # before __init__ was called + for var_name_py in self.attribute_map: + if var_name_py in unused_args: + del unused_args[var_name_py] + for instance in composed_instances: + if instance.__class__ in self._composed_schemas()['allOf']: + for var_name_py in instance.attribute_map: + if var_name_py in unused_args: + del unused_args[var_name_py] + else: + for var_name_js in instance.attribute_map.values(): + if var_name_js in unused_args: + del unused_args[var_name_js] + return unused_args + + +def validate_get_composed_info(constant_args, model_args, self): + """ + For composed schemas/classes, validates the classes to make sure that + they do not share any of the same parameters. If there is no collision + then composed model instances are created and returned tot the calling + self model + + Args: + constant_args (dict): these are the args that every model requires + model_args (dict): these are the required and optional spec args that + were passed in to make this model + self (class): the class that we are instantiating + This class contains self._composed_schemas() + + Returns: + composed_info (list): length three + composed_instances (list): the composed instances which are not + self + var_name_to_model_instances (dict): a dict going from var_name + to the model_instance which holds that var_name + the model_instance may be self or an instance of one of the + classes in self.composed_instances() + additional_properties_model_instances (list): a list of the + model instances which have the property + additional_properties_type. This list can include self + """ + # create composed_instances + composed_instances = [] + allof_instances = get_allof_instances(self, model_args, constant_args) + composed_instances.extend(allof_instances) + oneof_instance = get_oneof_instance(self, model_args, constant_args) + if oneof_instance is not None: + composed_instances.append(oneof_instance) + anyof_instances = get_anyof_instances(self, model_args, constant_args) + composed_instances.extend(anyof_instances) + + # map variable names to composed_instances + var_name_to_model_instances = get_var_name_to_model_instances( + self, composed_instances) + + # set additional_properties_model_instances + additional_properties_model_instances = ( + get_additional_properties_model_instances(composed_instances, self) + ) + + # set any remaining values + unused_args = get_unused_args(self, composed_instances, model_args) + if len(unused_args) > 0: + if len(additional_properties_model_instances) == 0: + raise ApiValueError( + "Invalid input arguments input when making an instance of " + "class %s. Not all inputs were used. The unused input data " + "is %s" % (self.__class__.__name__, unused_args) + ) + for var_name, var_value in six.iteritems(unused_args): + for instance in additional_properties_model_instances: + setattr(instance, var_name, var_value) + # no need to add additional_properties to var_name_to_model_instances here + # because additional_properties_model_instances will direct us to that + # instance when we use getattr or setattr + # and we update var_name_to_model_instances in setattr + + return [ + composed_instances, + var_name_to_model_instances, + additional_properties_model_instances + ] From a8b8ddb1e2f03f7f3629b1e1ccbed7bcd268ecdb Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Tue, 17 Dec 2019 03:39:54 +0100 Subject: [PATCH 071/180] [Python] Remove mutable default argument (#4665) --- configuration.mustache | 46 +++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 6e02b238da..b6a89d495d 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -349,41 +349,37 @@ class Configuration(object): {{/servers}} ] - def get_host_from_settings(self, index, variables={}): + def get_host_from_settings(self, index, variables=None): """Gets host URL based on the index and variables :param index: array index of the host settings :param variables: hash of variable and the corresponding value :return: URL based on host settings """ - + variables = {} if variables is None else variables servers = self.get_host_settings() - # check array index out of bound - if index < 0 or index >= len(servers): + try: + server = servers[index] + except IndexError: raise ValueError( - "Invalid index {} when selecting the host settings. Must be less than {}" # noqa: E501 - .format(index, len(servers))) + "Invalid index {0} when selecting the host settings. " + "Must be less than {1}".format(index, len(servers))) - server = servers[index] url = server['url'] - # go through variable and assign a value - for variable_name in server['variables']: - if variable_name in variables: - if variables[variable_name] in server['variables'][ - variable_name]['enum_values']: - url = url.replace("{" + variable_name + "}", - variables[variable_name]) - else: - raise ValueError( - "The variable `{}` in the host URL has invalid value {}. Must be {}." # noqa: E501 - .format( - variable_name, variables[variable_name], - server['variables'][variable_name]['enum_values'])) - else: - # use default value - url = url.replace( - "{" + variable_name + "}", - server['variables'][variable_name]['default_value']) + # go through variables and replace placeholders + for variable_name, variable in server['variables'].items(): + used_value = variables.get( + variable_name, variable['default_value']) + + if 'enum_values' in variable \ + and used_value not in variable['enum_values']: + raise ValueError( + "The variable `{0}` in the host URL has invalid value " + "{1}. Must be {2}.".format( + variable_name, variables[variable_name], + variable['enum_values'])) + + url = url.replace("{" + variable_name + "}", used_value) return url From 779e70b026a1a6edacc10507143cc981a6f51561 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 22 Dec 2019 00:14:04 -0600 Subject: [PATCH 072/180] [Python] Updates python test framework to pytest (#4765) * Switches python generators to use pytest, useNose CLI option added if to allow nose to be used instead * Adds ensure-up-to-date changes * Adds setup.cfg to python clients so we can configure nose when useNose=true * Adds fix for python-aiohttp testing, adds files missing from ensure-up-to-date --- gitignore.mustache | 2 ++ python-experimental/test-requirements.mustache | 16 ++++++++-------- setup_cfg.mustache | 13 +++++++++++++ test-requirements.mustache | 13 +++++++------ tox.mustache | 8 +------- 5 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 setup_cfg.mustache diff --git a/gitignore.mustache b/gitignore.mustache index a655050c26..43995bd42f 100644 --- a/gitignore.mustache +++ b/gitignore.mustache @@ -45,7 +45,9 @@ coverage.xml *,cover .hypothesis/ venv/ +.venv/ .python-version +.pytest_cache # Translations *.mo diff --git a/python-experimental/test-requirements.mustache b/python-experimental/test-requirements.mustache index 023ff96078..338b229bae 100644 --- a/python-experimental/test-requirements.mustache +++ b/python-experimental/test-requirements.mustache @@ -1,13 +1,13 @@ -{{^asyncio}} +{{#useNose}} coverage>=4.0.3 nose>=1.3.7 -{{/asyncio}} -{{#asyncio}} -pytest>=3.6.0 -pytest-cov>=2.6.1 -{{/asyncio}} pluggy>=0.3.1 py>=1.4.31 randomize>=0.13 -mock; python_version<="2.7" - +{{/useNose}} +{{^useNose}} +pytest~=4.6.7 # needed for python 2.7+3.4 +pytest-cov>=2.8.1 +pytest-randomly==1.2.3 # needed for python 2.7+3.4 +{{/useNose}} +mock; python_version<="2.7" \ No newline at end of file diff --git a/setup_cfg.mustache b/setup_cfg.mustache new file mode 100644 index 0000000000..d89aa72ee4 --- /dev/null +++ b/setup_cfg.mustache @@ -0,0 +1,13 @@ +{{#useNose}} +[nosetests] +logging-clear-handlers=true +verbosity=2 +randomize=true +exe=true +with-coverage=true +cover-package=petstore_api +cover-erase=true + +{{/useNose}} +[flake8] +max-line-length=99 diff --git a/test-requirements.mustache b/test-requirements.mustache index d9e3f20b53..12021b47a1 100644 --- a/test-requirements.mustache +++ b/test-requirements.mustache @@ -1,11 +1,12 @@ -{{^asyncio}} +{{#useNose}} coverage>=4.0.3 nose>=1.3.7 -{{/asyncio}} -{{#asyncio}} -pytest>=3.6.0 -pytest-cov>=2.6.1 -{{/asyncio}} pluggy>=0.3.1 py>=1.4.31 randomize>=0.13 +{{/useNose}} +{{^useNose}} +pytest~=4.6.7 # needed for python 2.7+3.4 +pytest-cov>=2.8.1 +pytest-randomly==1.2.3 # needed for python 2.7+3.4 +{{/useNose}} \ No newline at end of file diff --git a/tox.mustache b/tox.mustache index 585feb3c68..fe989faf93 100644 --- a/tox.mustache +++ b/tox.mustache @@ -11,10 +11,4 @@ deps=-r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands= -{{^asyncio}} - nosetests \ - [] -{{/asyncio}} -{{#asyncio}} - pytest -v --cov {{{packageName}}} -{{/asyncio}} + {{^useNose}}pytest --cov={{{packageName}}}{{/useNose}}{{#useNose}}nosetests{{/useNose}} From 5dd55cc14f0427f2db0a19228394ca4906b3102c Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 3 Jan 2020 22:54:52 +0800 Subject: [PATCH 073/180] replace petstore_api with packageName (#4921) --- setup_cfg.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup_cfg.mustache b/setup_cfg.mustache index d89aa72ee4..931f02c5d1 100644 --- a/setup_cfg.mustache +++ b/setup_cfg.mustache @@ -5,7 +5,7 @@ verbosity=2 randomize=true exe=true with-coverage=true -cover-package=petstore_api +cover-package={{{packageName}}} cover-erase=true {{/useNose}} From e6a668e03597b49826afbaa697a01106247a3150 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 10 Jan 2020 01:43:35 -0800 Subject: [PATCH 074/180] [Python] Allow models to have properties of type self (#4888) * Refactors openapi_types into a staticmethod * Adds a Player model with a self type rpoperty, adds a test to ensure that it is working right --- .../model_templates/classvars.mustache | 28 +++++++++++++------ .../docstring_openapi_validations.mustache | 2 -- .../method_set_attribute.mustache | 5 ++-- python-experimental/model_utils.mustache | 8 +++--- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index fcd8a71fd1..60fff484ef 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -29,15 +29,6 @@ {{/optionalVars}} } - openapi_types = { -{{#requiredVars}} - '{{name}}': ({{{dataType}}},), # noqa: E501 -{{/requiredVars}} -{{#optionalVars}} - '{{name}}': ({{{dataType}}},), # noqa: E501 -{{/optionalVars}} - } - validations = { {{#requiredVars}} {{#hasValidation}} @@ -103,6 +94,25 @@ additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} + @staticmethod + def openapi_types(): + """ + This must be a class method so a model may have properties that are + of type self, this ensures that we don't create a cyclic import + + Returns + openapi_types (dict): The key is attribute name + and the value is attribute type. + """ + return { +{{#requiredVars}} + '{{name}}': ({{{dataType}}},), # noqa: E501 +{{/requiredVars}} +{{#optionalVars}} + '{{name}}': ({{{dataType}}},), # noqa: E501 +{{/optionalVars}} + } + @staticmethod def discriminator(): return {{^discriminator}}None{{/discriminator}}{{#discriminator}}{ diff --git a/python-experimental/model_templates/docstring_openapi_validations.mustache b/python-experimental/model_templates/docstring_openapi_validations.mustache index 03eec953f3..f933b86c5b 100644 --- a/python-experimental/model_templates/docstring_openapi_validations.mustache +++ b/python-experimental/model_templates/docstring_openapi_validations.mustache @@ -1,5 +1,3 @@ - openapi_types (dict): The key is attribute name - and the value is attribute type. validations (dict): The key is the tuple path to the attribute and the for var_name this is (var_name,). The value is a dict that stores validations for max_length, min_length, max_items, diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache index f4a36e42f2..bcafb71368 100644 --- a/python-experimental/model_templates/method_set_attribute.mustache +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -6,8 +6,9 @@ path_to_item.extend(self._path_to_item) path_to_item.append(name) - if name in self.openapi_types: - required_types_mixed = self.openapi_types[name] + openapi_types = self.openapi_types() + if name in openapi_types: + required_types_mixed = openapi_types[name] elif self.additional_properties_type is None: raise ApiKeyError( "{0} has no key '{1}'".format(type(self).__name__, name), diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index dbd592c37e..c3d9e7d536 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -928,7 +928,7 @@ def get_allof_instances(self, model_args, constant_args): # extract a dict of only required keys from fixed_model_args kwargs = {} - var_names = set(allof_class.openapi_types.keys()) + var_names = set(allof_class.openapi_types().keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] @@ -963,7 +963,7 @@ def get_oneof_instance(self, model_args, constant_args): # extract a dict of only required keys from fixed_model_args kwargs = {} - var_names = set(oneof_class.openapi_types.keys()) + var_names = set(oneof_class.openapi_types().keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] @@ -1006,7 +1006,7 @@ def get_anyof_instances(self, model_args, constant_args): # extract a dict of only required keys from these_model_vars kwargs = {} - var_names = set(anyof_class.openapi_types.keys()) + var_names = set(anyof_class.openapi_types().keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] @@ -1043,7 +1043,7 @@ def get_var_name_to_model_instances(self, composed_instances): all_instances = [self] all_instances.extend(composed_instances) for instance in all_instances: - for var_name in instance.openapi_types: + for var_name in instance.openapi_types(): if var_name not in var_name_to_model_instances: var_name_to_model_instances[var_name] = [instance] else: From 0f0aa0c1ed1d5e41e9d672a9fe3b352119efd8db Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 16 Jan 2020 01:42:23 -0800 Subject: [PATCH 075/180] [Python] Conditionally set auth attributes (#4988) * Enhance python API keys * Run python scripts under ./bin/openapi3 * fix unit test issue * Fix unit tests * Fix unit tests * Invoke bin scripts --- api_client.mustache | 4 +- configuration.mustache | 101 +++++++++++++++--------- python-experimental/api_client.mustache | 4 +- 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 3bf085e190..8297ad5798 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -520,9 +520,7 @@ class ApiClient(object): for auth in auth_settings: auth_setting = self.configuration.auth_settings().get(auth) if auth_setting: - if not auth_setting['value']: - continue - elif auth_setting['in'] == 'cookie': + if auth_setting['in'] == 'cookie': headers['Cookie'] = auth_setting['value'] elif auth_setting['in'] == 'header': headers[auth_setting['key']] = auth_setting['value'] diff --git a/configuration.mustache b/configuration.mustache index b6a89d495d..f53b6f4197 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -22,15 +22,38 @@ class Configuration(object): Do not edit the class manually. :param host: Base url - :param api_key: Dict to store API key(s) + :param api_key: Dict to store API key(s). + Each entry in the dict specifies an API key. + The dict key is the name of the security scheme in the OAS specification. + The dict value is the API key secret. :param api_key_prefix: Dict to store API prefix (e.g. Bearer) + The dict key is the name of the security scheme in the OAS specification. + The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication + + :Example: + + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + cookieAuth: # name for the security scheme + type: apiKey + in: cookie + name: JSESSIONID # cookie name + + You can programmatically set the cookie: + conf = {{{packageName}}}.Configuration( + api_key={'cookieAuth': 'abc123'} + api_key_prefix={'cookieAuth': 'JSESSIONID'} + ) + The following cookie will be added to the HTTP request: + Cookie: JSESSIONID abc123 """ def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, - username="", password=""): + username=None, password=None): """Constructor """ self.host = host @@ -247,8 +270,14 @@ class Configuration(object): :return: The token for basic HTTP authentication. """ + username = "" + if self.username is not None: + username = self.username + password = "" + if self.password is not None: + password = self.password return urllib3.util.make_headers( - basic_auth=self.username + ':' + self.password + basic_auth=username + ':' + password ).get('authorization') def auth_settings(self): @@ -256,51 +285,51 @@ class Configuration(object): :return: The Auth Settings information dict. """ - return { + auth = {} {{#authMethods}} {{#isApiKey}} - '{{name}}': - { - 'type': 'api_key', - 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, - 'key': '{{keyParamName}}', - 'value': self.get_api_key_with_prefix('{{keyParamName}}') - }, + if '{{keyParamName}}' in self.api_key: + auth['{{name}}'] = { + 'type': 'api_key', + 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': self.get_api_key_with_prefix('{{keyParamName}}') + } {{/isApiKey}} {{#isBasic}} {{^isBasicBearer}} - '{{name}}': - { - 'type': 'basic', - 'in': 'header', - 'key': 'Authorization', - 'value': self.get_basic_auth_token() - }, + if self.username is not None and self.password is not None: + auth['{{name}}'] = { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': self.get_basic_auth_token() + } {{/isBasicBearer}} {{#isBasicBearer}} - '{{name}}': - { - 'type': 'bearer', - 'in': 'header', - {{#bearerFormat}} - 'format': '{{{.}}}', - {{/bearerFormat}} - 'key': 'Authorization', - 'value': 'Bearer ' + self.access_token - }, + if self.access_token is not None: + auth['{{name}}'] = { + 'type': 'bearer', + 'in': 'header', + {{#bearerFormat}} + 'format': '{{{.}}}', + {{/bearerFormat}} + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } {{/isBasicBearer}} {{/isBasic}} {{#isOAuth}} - '{{name}}': - { - 'type': 'oauth2', - 'in': 'header', - 'key': 'Authorization', - 'value': 'Bearer ' + self.access_token - }, + if self.access_token is not None: + auth['{{name}}'] = { + 'type': 'oauth2', + 'in': 'header', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } {{/isOAuth}} {{/authMethods}} - } + return auth def to_debug_report(self): """Gets the essential information for debugging. diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 25ca4b5043..c9d7eac63e 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -530,9 +530,7 @@ class ApiClient(object): for auth in auth_settings: auth_setting = self.configuration.auth_settings().get(auth) if auth_setting: - if not auth_setting['value']: - continue - elif auth_setting['in'] == 'cookie': + if auth_setting['in'] == 'cookie': headers['Cookie'] = auth_setting['value'] elif auth_setting['in'] == 'header': headers[auth_setting['key']] = auth_setting['value'] From f22c81787e4aae9e6819357bcb3f7f2abbb1e5a2 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 21 Jan 2020 07:19:07 -0800 Subject: [PATCH 076/180] Add python-experimental-openapiv3-sample (#4992) Add python-experimental-openapiv3-sample Add missing files for the Python samples Add python-experimental-petstore.bat for openapi v3 Add python-experimental samples openapi v3 Add python-experimental samples openapi v3 Add python-experimental samples openapi v3. Address review comments add missing files for test purpose fix python formatting issues fix python formatting issues fix python formatting issues Fix unit tests fix python formatting issues fix python formatting issues fix python formatting issues fix 'line too long' pep8 error address PR comments for pep8 'line too long' problem regenerate samples execute samples scripts dummy commit to retrigger circleci Revert dummy commit, it didn't help. --- python-experimental/api.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 734c490cab..2182d7362d 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -108,7 +108,8 @@ class {{classname}}(object): ) kwargs['_host_index'] = kwargs.get('_host_index', 0) {{#requiredParams}} - kwargs['{{paramName}}'] = {{paramName}} + kwargs['{{paramName}}'] = \ + {{paramName}} {{/requiredParams}} return self.call_with_http_info(**kwargs) @@ -216,7 +217,8 @@ class {{classname}}(object): }, 'openapi_types': { {{#allParams}} - '{{paramName}}': ({{{dataType}}},), + '{{paramName}}': + ({{{dataType}}},), {{/allParams}} }, 'attribute_map': { From 11fedab25445f136a5cbe23751a8a5cdd6b95617 Mon Sep 17 00:00:00 2001 From: Michele Albano Date: Wed, 22 Jan 2020 15:08:53 +0100 Subject: [PATCH 077/180] Rebased to current upstream/master. (#4514) Tests for python client, comprising support for additional_properties and arrays. There are ugly workarounds for when there are discriminators, since the python client generator does not fully handle them. Cool indentation of test files. --- model_test.mustache | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/model_test.mustache b/model_test.mustache index 765e4f9c2c..b69f13f744 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -5,6 +5,7 @@ from __future__ import absolute_import import unittest +import datetime {{#models}} {{#model}} @@ -12,7 +13,6 @@ import {{packageName}} from {{modelPackage}}.{{classFilename}} import {{classname}} # noqa: E501 from {{packageName}}.rest import ApiException - class Test{{classname}}(unittest.TestCase): """{{classname}} unit test stubs""" @@ -22,11 +22,31 @@ class Test{{classname}}(unittest.TestCase): def tearDown(self): pass + def make_instance(self, include_optional): + """Test {{classname}} + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501 + if include_optional : + return {{classname}}( +{{#vars}} + {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}{{#hasMore}}, {{/hasMore}} +{{/vars}} + ) + else : + return {{classname}}( +{{#vars}} +{{#required}} + {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}, +{{/required}} +{{/vars}} + ) + def test{{classname}}(self): """Test {{classname}}""" - # FIXME: construct object with mandatory attributes with example values - # model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501 - pass + inst_req_only = self.make_instance(include_optional=False) + inst_req_and_optional = self.make_instance(include_optional=True) {{/model}} {{/models}} From 0cccbfba2affac4e4ab30f41dcda01bc4b481201 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 23 Jan 2020 18:35:56 -0800 Subject: [PATCH 078/180] [HttpBasicAuth] Use positive isBasicBasic tag instead of negative isBasicBearer (#5095) * use positive isBasicBasic tag instead of negative isBasicBearer * use positive isBasicBasic tag instead of negative isBasicBearer --- api_doc.mustache | 4 ++-- common_README.mustache | 4 ++-- configuration.mustache | 4 ++-- python-experimental/README_common.mustache | 4 ++-- python-experimental/api_doc.mustache | 4 ++-- python_doc_auth_partial.mustache | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/api_doc.mustache b/api_doc.mustache index 1df5389c5c..fb537ad30b 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -22,9 +22,9 @@ Method | HTTP request | Description {{#hasAuthMethods}} {{#authMethods}} {{#isBasic}} -{{^isBasicBearer}} +{{#isBasicBasic}} * Basic Authentication ({{name}}): -{{/isBasicBearer}} +{{/isBasicBasic}} {{#isBasicBearer}} * Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}): {{/isBasicBearer}} diff --git a/common_README.mustache b/common_README.mustache index 7238703c4b..7de8c9ef09 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -51,9 +51,9 @@ Class | Method | HTTP request | Description - **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} {{/isApiKey}} {{#isBasic}} -{{^isBasicBearer}} +{{#isBasicBasic}} - **Type**: HTTP basic authentication -{{/isBasicBearer}} +{{/isBasicBasic}} {{#isBasicBearer}} - **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} {{/isBasicBearer}} diff --git a/configuration.mustache b/configuration.mustache index f53b6f4197..1aed945621 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -297,7 +297,7 @@ class Configuration(object): } {{/isApiKey}} {{#isBasic}} - {{^isBasicBearer}} + {{#isBasicBasic}} if self.username is not None and self.password is not None: auth['{{name}}'] = { 'type': 'basic', @@ -305,7 +305,7 @@ class Configuration(object): 'key': 'Authorization', 'value': self.get_basic_auth_token() } - {{/isBasicBearer}} + {{/isBasicBasic}} {{#isBasicBearer}} if self.access_token is not None: auth['{{name}}'] = { diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index a8b66b0bed..d8185eea5a 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -50,9 +50,9 @@ Class | Method | HTTP request | Description - **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} {{/isApiKey}} {{#isBasic}} -{{^isBasicBearer}} +{{#isBasicBasic}} - **Type**: HTTP basic authentication -{{/isBasicBearer}} +{{/isBasicBasic}} {{#isBasicBearer}} - **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} {{/isBasicBearer}} diff --git a/python-experimental/api_doc.mustache b/python-experimental/api_doc.mustache index 4feb612f1c..10317b4b48 100644 --- a/python-experimental/api_doc.mustache +++ b/python-experimental/api_doc.mustache @@ -22,9 +22,9 @@ Method | HTTP request | Description {{#hasAuthMethods}} {{#authMethods}} {{#isBasic}} -{{^isBasicBearer}} +{{#isBasicBasic}} * Basic Authentication ({{name}}): -{{/isBasicBearer}} +{{/isBasicBasic}} {{#isBasicBearer}} * Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}): {{/isBasicBearer}} diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 899e4b58b9..2e74426103 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -2,11 +2,11 @@ {{#authMethods}} configuration = {{{packageName}}}.Configuration() {{#isBasic}} -{{^isBasicBearer}} +{{#isBasicBasic}} # Configure HTTP basic authorization: {{{name}}} configuration.username = 'YOUR_USERNAME' configuration.password = 'YOUR_PASSWORD' -{{/isBasicBearer}} +{{/isBasicBasic}} {{#isBasicBearer}} # Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}} configuration.access_token = 'YOUR_BEARER_TOKEN' From c0924d16ea14332d4490cbd6ce067a28e330a0e1 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 26 Jan 2020 18:17:26 -0800 Subject: [PATCH 079/180] [Python] Support for HTTP signature (#4958) * start implementation of HTTP signature * add api key parameters for http message signature * HTTP signature authentication * start implementation of HTTP signature * add api key parameters for http message signature * HTTP signature authentication * HTTP signature authentication * start implementation of HTTP signature * fix merge issues * Address formatting issues * Address formatting issues * move python-experimental-openapiv3-sample to a separate PR * Add support for HTTP signature * Add code comments * Add code comments * Fix formatting issues * Fix formatting issues * Fix formatting issues * add code comments * add code comments * fix python formatting issues * Make PKCS1v15 string constant consistent between Python and Golang * fix python formatting issues * Add code comments in generated Python. Start adding unit tests for HTTP signature * compliance with HTTP signature draft 12 * compliance with HTTP signature draft 12 * working on review comments * working on review comments * working on review comments * working on review comments * working on review comments * working on review comments * working on review comments * working on review comments * working on review comments * fix python formatting issues * fix trailing white space * address PR comments * address PR comments * address PR comments * Add suppport for '(expires)' signature parameter * address PR comments * address PR comments * Fix python formatting issues * Fix python formatting issues * Starting to move code to dedicated file for HTTP signatures * Continue to refactor code to dedicated file for HTTP signatures * Continue to refactor code to dedicated file for HTTP signatures * Continue to refactor code to dedicated file for HTTP signatures * Continue to refactor code to dedicated file for HTTP signatures * move method to ProcessUtils * conditionally build signing.py * move method to ProcessUtils * Code reformatting * externalize http signature configuration * address PR review comments * address PR review comments * run samples scripts * Address PR review comments * Move 'private_key' field to signing module * Move 'private_key' field to signing module * code cleanup * remove use of strftime('%s'), which is non portable * code cleanup * code cleanup * code cleanup * run sample scripts * Address PR review comments. * Add http-signature security scheme * Run sample scripts for go * Fix issue uncovered in integration branch * Fix issue uncovered in integration branch * Fix issue uncovered in integration branch * Fix issue uncovered in integration branch * Run samples scripts * move http signature tests to separate file * move http signature tests to separate file * unit tests for HTTP signature * continue implementation of unit tests * add http_signature_test to security scheme * add unit tests for http signature * address review comments * remove http signature from petapi * Add separate OAS file with support for HTTP signature * Add support for private key passphrase. Add more unit tests * Add unit test to validate the signature against the public key * remove http signature from petstore-with-fake-endpoints-models-for-testing.yaml * fix unit test issues * run scripts in bin directory * Refact unit test with better variable names * do not throw exception if security scheme is unrecognized * change URL of apache license to use https * sync from master * fix usage of escape character in python regex. Fix generated python documentation * write HTTP signed headers in user-specified order. Fix PEP8 formatting issues * write HTTP signed headers in user-specified order. Fix PEP8 formatting issues * http signature unit tests * Fix PEP8 format issue * spread out each requirement to a separate line * run samples scripts * run sample scripts * remove encoding of '+' character --- configuration.mustache | 57 ++- python-experimental/README_common.mustache | 3 + python-experimental/api.mustache | 2 +- python-experimental/api_client.mustache | 26 +- python-experimental/setup.mustache | 15 +- python-experimental/signing.mustache | 368 ++++++++++++++++++ .../test-requirements.mustache | 3 + python_doc_auth_partial.mustache | 22 ++ 8 files changed, 486 insertions(+), 10 deletions(-) create mode 100644 python-experimental/signing.mustache diff --git a/configuration.mustache b/configuration.mustache index 1aed945621..3e0a156765 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -31,6 +31,8 @@ class Configuration(object): The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication + :param signing_info: Configuration parameters for HTTP signature. + Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration :Example: @@ -49,11 +51,50 @@ class Configuration(object): ) The following cookie will be added to the HTTP request: Cookie: JSESSIONID abc123 + + Configure API client with HTTP basic authentication: + conf = {{{packageName}}}.Configuration( + username='the-user', + password='the-password', + ) + + Configure API client with HTTP signature authentication. Use the 'hs2019' signature scheme, + sign the HTTP requests with the RSA-SSA-PSS signature algorithm, and set the expiration time + of the signature to 5 minutes after the signature has been created. + Note you can use the constants defined in the {{{packageName}}}.signing module, and you can + also specify arbitrary HTTP headers to be included in the HTTP signature, except for the + 'Authorization' header, which is used to carry the signature. + + One may be tempted to sign all headers by default, but in practice it rarely works. + This is beccause explicit proxies, transparent proxies, TLS termination endpoints or + load balancers may add/modify/remove headers. Include the HTTP headers that you know + are not going to be modified in transit. + + conf = {{{packageName}}}.Configuration( + signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( + key_id = 'my-key-id', + private_key_path = 'rsa.pem', + signing_scheme = signing.SCHEME_HS2019, + signing_algorithm = signing.ALGORITHM_RSASSA_PSS, + signed_headers = [signing.HEADER_REQUEST_TARGET, + signing.HEADER_CREATED, + signing.HEADER_EXPIRES, + signing.HEADER_HOST, + signing.HEADER_DATE, + signing.HEADER_DIGEST, + 'Content-Type', + 'Content-Length', + 'User-Agent' + ], + signature_max_validity = datetime.timedelta(minutes=5) + ) + ) """ def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, - username=None, password=None): + username=None, password=None, + signing_info=None): """Constructor """ self.host = host @@ -82,6 +123,11 @@ class Configuration(object): self.password = password """Password for HTTP basic authentication """ + if signing_info is not None: + signing_info.host = host + self.signing_info = signing_info + """The HTTP signing configuration + """ {{#hasOAuthMethods}} self.access_token = "" """access token for OAuth/Bearer @@ -318,6 +364,15 @@ class Configuration(object): 'value': 'Bearer ' + self.access_token } {{/isBasicBearer}} + {{#isHttpSignature}} + if self.signing_info is not None: + auth['{{name}}'] = { + 'type': 'http-signature', + 'in': 'header', + 'key': 'Authorization', + 'value': None # Signature headers are calculated for every HTTP request + } + {{/isHttpSignature}} {{/isBasic}} {{#isOAuth}} if self.access_token is not None: diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index d8185eea5a..5fffdc74fc 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -56,6 +56,9 @@ Class | Method | HTTP request | Description {{#isBasicBearer}} - **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} {{/isBasicBearer}} +{{#isHttpSignature}} +- **Type**: HTTP signature authentication +{{/isHttpSignature}} {{/isBasic}} {{#isOAuth}} - **Type**: OAuth diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 2182d7362d..8390a848d2 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -120,7 +120,7 @@ class {{classname}}(object): {{#-first}} 'auth': [ {{/-first}} - '{{name}}'{{#hasMore}}, {{/hasMore}} + '{{name}}'{{#hasMore}},{{/hasMore}} {{#-last}} ], {{/-last}} diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index c9d7eac63e..9520896120 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -150,13 +150,14 @@ class ApiClient(object): collection_formats) post_params.extend(self.files_parameters(files)) - # auth setting - self.update_params_for_auth(header_params, query_params, auth_settings) - # body if body: body = self.sanitize_for_serialization(body) + # auth setting + self.update_params_for_auth(header_params, query_params, + auth_settings, resource_path, method, body) + # request url if _host is None: url = self.configuration.host + resource_path @@ -517,12 +518,17 @@ class ApiClient(object): else: return content_types[0] - def update_params_for_auth(self, headers, querys, auth_settings): + def update_params_for_auth(self, headers, querys, auth_settings, + resource_path, method, body): """Updates header and query params based on authentication setting. :param headers: Header parameters dict to be updated. :param querys: Query parameters tuple list to be updated. :param auth_settings: Authentication setting identifiers list. + :resource_path: A string representation of the HTTP request resource path. + :method: A string representation of the HTTP request method. + :body: A object representing the body of the HTTP request. + The object type is the return value of sanitize_for_serialization(). """ if not auth_settings: return @@ -533,7 +539,17 @@ class ApiClient(object): if auth_setting['in'] == 'cookie': headers['Cookie'] = auth_setting['value'] elif auth_setting['in'] == 'header': - headers[auth_setting['key']] = auth_setting['value'] + if auth_setting['type'] != 'http-signature': + headers[auth_setting['key']] = auth_setting['value'] +{{#hasHttpSignatureMethods}} + else: + # The HTTP signature scheme requires multiple HTTP headers + # that are calculated dynamically. + signing_info = self.configuration.signing_info + auth_headers = signing_info.get_http_signature_headers( + resource_path, method, headers, body, querys) + headers.update(auth_headers) +{{/hasHttpSignatureMethods}} elif auth_setting['in'] == 'query': querys.append((auth_setting['key'], auth_setting['value'])) else: diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index bf9ffe07d0..2fe84efcee 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -16,13 +16,22 @@ VERSION = "{{packageVersion}}" # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] +REQUIRES = [ + "urllib3 >= 1.15", + "six >= 1.10", + "certifi", + "python-dateutil", {{#asyncio}} -REQUIRES.append("aiohttp >= 3.0.0") + "aiohttp >= 3.0.0", {{/asyncio}} {{#tornado}} -REQUIRES.append("tornado>=4.2,<5") + "tornado>=4.2,<5", {{/tornado}} +{{#hasHttpSignatureMethods}} + "pem>=19.3.0", + "pycryptodome>=3.9.0", +{{/hasHttpSignatureMethods}} +] EXTRAS = {':python_version <= "2.7"': ['future']} setup( diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache new file mode 100644 index 0000000000..d191bbf485 --- /dev/null +++ b/python-experimental/signing.mustache @@ -0,0 +1,368 @@ +# coding: utf-8 +{{>partial_header}} +from __future__ import absolute_import + +from base64 import b64encode +from Crypto.IO import PEM, PKCS8 +from Crypto.Hash import SHA256, SHA512 +from Crypto.PublicKey import RSA, ECC +from Crypto.Signature import PKCS1_v1_5, pss, DSS +from datetime import datetime +from email.utils import formatdate +import json +import os +import re +from six.moves.urllib.parse import urlencode, urlparse +from time import mktime + +HEADER_REQUEST_TARGET = '(request-target)' +HEADER_CREATED = '(created)' +HEADER_EXPIRES = '(expires)' +HEADER_HOST = 'Host' +HEADER_DATE = 'Date' +HEADER_DIGEST = 'Digest' # RFC 3230, include digest of the HTTP request body. +HEADER_AUTHORIZATION = 'Authorization' + +SCHEME_HS2019 = 'hs2019' +SCHEME_RSA_SHA256 = 'rsa-sha256' +SCHEME_RSA_SHA512 = 'rsa-sha512' + +ALGORITHM_RSASSA_PSS = 'RSASSA-PSS' +ALGORITHM_RSASSA_PKCS1v15 = 'RSASSA-PKCS1-v1_5' + +ALGORITHM_ECDSA_MODE_FIPS_186_3 = 'fips-186-3' +ALGORITHM_ECDSA_MODE_DETERMINISTIC_RFC6979 = 'deterministic-rfc6979' +ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS = { + ALGORITHM_ECDSA_MODE_FIPS_186_3, + ALGORITHM_ECDSA_MODE_DETERMINISTIC_RFC6979 +} + + +class HttpSigningConfiguration(object): + """The configuration parameters for the HTTP signature security scheme. + The HTTP signature security scheme is used to sign HTTP requests with a private key + which is in possession of the API client. + An 'Authorization' header is calculated by creating a hash of select headers, + and optionally the body of the HTTP request, then signing the hash value using + a private key. The 'Authorization' header is added to outbound HTTP requests. + + NOTE: This class is auto generated by OpenAPI Generator + + Ref: https://openapi-generator.tech + Do not edit the class manually. + + :param key_id: A string value specifying the identifier of the cryptographic key, + when signing HTTP requests. + :param signing_scheme: A string value specifying the signature scheme, when + signing HTTP requests. + Supported value are hs2019, rsa-sha256, rsa-sha512. + Avoid using rsa-sha256, rsa-sha512 as they are deprecated. These values are + available for server-side applications that only support the older + HTTP signature algorithms. + :param private_key_path: A string value specifying the path of the file containing + a private key. The private key is used to sign HTTP requests. + :param private_key_passphrase: A string value specifying the passphrase to decrypt + the private key. + :param signed_headers: A list of strings. Each value is the name of a HTTP header + that must be included in the HTTP signature calculation. + The two special signature headers '(request-target)' and '(created)' SHOULD be + included in SignedHeaders. + The '(created)' header expresses when the signature was created. + The '(request-target)' header is a concatenation of the lowercased :method, an + ASCII space, and the :path pseudo-headers. + When signed_headers is not specified, the client defaults to a single value, + '(created)', in the list of HTTP headers. + When SignedHeaders contains the 'Digest' value, the client performs the + following operations: + 1. Calculate a digest of request body, as specified in RFC3230, section 4.3.2. + 2. Set the 'Digest' header in the request body. + 3. Include the 'Digest' header and value in the HTTP signature. + :param signing_algorithm: A string value specifying the signature algorithm, when + signing HTTP requests. + Supported values are: + 1. For RSA keys: RSASSA-PSS, RSASSA-PKCS1-v1_5. + 2. For ECDSA keys: fips-186-3, deterministic-rfc6979. + The default value is inferred from the private key. + The default value for RSA keys is RSASSA-PSS. + The default value for ECDSA keys is fips-186-3. + :param signature_max_validity: The signature max validity, expressed as + a datetime.timedelta value. It must be a positive value. + """ + def __init__(self, key_id, signing_scheme, private_key_path, + private_key_passphrase=None, + signed_headers=None, + signing_algorithm=None, + signature_max_validity=None): + self.key_id = key_id + if signing_scheme not in {SCHEME_HS2019, SCHEME_RSA_SHA256, SCHEME_RSA_SHA512}: + raise Exception("Unsupported security scheme: {0}".format(signing_scheme)) + self.signing_scheme = signing_scheme + if not os.path.exists(private_key_path): + raise Exception("Private key file does not exist") + self.private_key_path = private_key_path + self.private_key_passphrase = private_key_passphrase + self.signing_algorithm = signing_algorithm + if signature_max_validity is not None and signature_max_validity.total_seconds() < 0: + raise Exception("The signature max validity must be a positive value") + self.signature_max_validity = signature_max_validity + # If the user has not provided any signed_headers, the default must be set to '(created)', + # as specified in the 'HTTP signature' standard. + if signed_headers is None or len(signed_headers) == 0: + signed_headers = [HEADER_CREATED] + if self.signature_max_validity is None and HEADER_EXPIRES in signed_headers: + raise Exception( + "Signature max validity must be set when " + "'(expires)' signature parameter is specified") + if len(signed_headers) != len(set(signed_headers)): + raise Exception("Cannot have duplicates in the signed_headers parameter") + if HEADER_AUTHORIZATION in signed_headers: + raise Exception("'Authorization' header cannot be included in signed headers") + self.signed_headers = signed_headers + self.private_key = None + """The private key used to sign HTTP requests. + Initialized when the PEM-encoded private key is loaded from a file. + """ + self.host = None + """The host name, optionally followed by a colon and TCP port number. + """ + self._load_private_key() + + def get_http_signature_headers(self, resource_path, method, headers, body, query_params): + """Create a cryptographic message signature for the HTTP request and add the signed headers. + + :param resource_path : A string representation of the HTTP request resource path. + :param method: A string representation of the HTTP request method, e.g. GET, POST. + :param headers: A dict containing the HTTP request headers. + :param body: The object representing the HTTP request body. + :param query_params: A string representing the HTTP request query parameters. + :return: A dict of HTTP headers that must be added to the outbound HTTP request. + """ + if method is None: + raise Exception("HTTP method must be set") + if resource_path is None: + raise Exception("Resource path must be set") + + signed_headers_list, request_headers_dict = self._get_signed_header_info( + resource_path, method, headers, body, query_params) + + header_items = [ + "{0}: {1}".format(key.lower(), value) for key, value in signed_headers_list] + string_to_sign = "\n".join(header_items) + + digest, digest_prefix = self._get_message_digest(string_to_sign.encode()) + b64_signed_msg = self._sign_digest(digest) + + request_headers_dict[HEADER_AUTHORIZATION] = self._get_authorization_header( + signed_headers_list, b64_signed_msg) + + return request_headers_dict + + def get_public_key(self): + """Returns the public key object associated with the private key. + """ + pubkey = None + if isinstance(self.private_key, RSA.RsaKey): + pubkey = self.private_key.publickey() + elif isinstance(self.private_key, ECC.EccKey): + pubkey = self.private_key.public_key() + return pubkey + + def _load_private_key(self): + """Load the private key used to sign HTTP requests. + The private key is used to sign HTTP requests as defined in + https://datatracker.ietf.org/doc/draft-cavage-http-signatures/. + """ + if self.private_key is not None: + return + with open(self.private_key_path, 'r') as f: + pem_data = f.read() + # Verify PEM Pre-Encapsulation Boundary + r = re.compile(r"\s*-----BEGIN (.*)-----\s+") + m = r.match(pem_data) + if not m: + raise ValueError("Not a valid PEM pre boundary") + pem_header = m.group(1) + if pem_header == 'RSA PRIVATE KEY': + self.private_key = RSA.importKey(pem_data, self.private_key_passphrase) + elif pem_header == 'EC PRIVATE KEY': + self.private_key = ECC.import_key(pem_data, self.private_key_passphrase) + elif pem_header in {'PRIVATE KEY', 'ENCRYPTED PRIVATE KEY'}: + # Key is in PKCS8 format, which is capable of holding many different + # types of private keys, not just EC keys. + (key_binary, pem_header, is_encrypted) = \ + PEM.decode(pem_data, self.private_key_passphrase) + (oid, privkey, params) = \ + PKCS8.unwrap(key_binary, passphrase=self.private_key_passphrase) + if oid == '1.2.840.10045.2.1': + self.private_key = ECC.import_key(pem_data, self.private_key_passphrase) + else: + raise Exception("Unsupported key: {0}. OID: {1}".format(pem_header, oid)) + else: + raise Exception("Unsupported key: {0}".format(pem_header)) + # Validate the specified signature algorithm is compatible with the private key. + if self.signing_algorithm is not None: + supported_algs = None + if isinstance(self.private_key, RSA.RsaKey): + supported_algs = {ALGORITHM_RSASSA_PSS, ALGORITHM_RSASSA_PKCS1v15} + elif isinstance(self.private_key, ECC.EccKey): + supported_algs = ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS + if supported_algs is not None and self.signing_algorithm not in supported_algs: + raise Exception( + "Signing algorithm {0} is not compatible with private key".format( + self.signing_algorithm)) + + def _get_unix_time(self, ts): + """Converts and returns a datetime object to UNIX time, the number of seconds + elapsed since January 1, 1970 UTC. + """ + return (ts - datetime(1970, 1, 1)).total_seconds() + + def _get_signed_header_info(self, resource_path, method, headers, body, query_params): + """Build the HTTP headers (name, value) that need to be included in + the HTTP signature scheme. + + :param resource_path : A string representation of the HTTP request resource path. + :param method: A string representation of the HTTP request method, e.g. GET, POST. + :param headers: A dict containing the HTTP request headers. + :param body: The object (e.g. a dict) representing the HTTP request body. + :param query_params: A string representing the HTTP request query parameters. + :return: A tuple containing two dict objects: + The first dict contains the HTTP headers that are used to calculate + the HTTP signature. + The second dict contains the HTTP headers that must be added to + the outbound HTTP request. + """ + + if body is None: + body = '' + else: + body = json.dumps(body) + + # Build the '(request-target)' HTTP signature parameter. + target_host = urlparse(self.host).netloc + target_path = urlparse(self.host).path + request_target = method.lower() + " " + target_path + resource_path + if query_params: + request_target += "?" + urlencode(query_params) + + # Get current time and generate RFC 1123 (HTTP/1.1) date/time string. + now = datetime.now() + stamp = mktime(now.timetuple()) + cdate = formatdate(timeval=stamp, localtime=False, usegmt=True) + # The '(created)' value MUST be a Unix timestamp integer value. + # Subsecond precision is not supported. + created = int(self._get_unix_time(now)) + if self.signature_max_validity is not None: + expires = self._get_unix_time(now + self.signature_max_validity) + + signed_headers_list = [] + request_headers_dict = {} + for hdr_key in self.signed_headers: + hdr_key = hdr_key.lower() + if hdr_key == HEADER_REQUEST_TARGET: + value = request_target + elif hdr_key == HEADER_CREATED: + value = '{0}'.format(created) + elif hdr_key == HEADER_EXPIRES: + value = '{0}'.format(expires) + elif hdr_key == HEADER_DATE.lower(): + value = cdate + request_headers_dict[HEADER_DATE] = '{0}'.format(cdate) + elif hdr_key == HEADER_DIGEST.lower(): + request_body = body.encode() + body_digest, digest_prefix = self._get_message_digest(request_body) + b64_body_digest = b64encode(body_digest.digest()) + value = digest_prefix + b64_body_digest.decode('ascii') + request_headers_dict[HEADER_DIGEST] = '{0}{1}'.format( + digest_prefix, b64_body_digest.decode('ascii')) + elif hdr_key == HEADER_HOST.lower(): + value = target_host + request_headers_dict[HEADER_HOST] = '{0}'.format(target_host) + else: + value = next((v for k, v in headers.items() if k.lower() == hdr_key), None) + if value is None: + raise Exception( + "Cannot sign HTTP request. " + "Request does not contain the '{0}' header".format(hdr_key)) + signed_headers_list.append((hdr_key, value)) + + return signed_headers_list, request_headers_dict + + def _get_message_digest(self, data): + """Calculates and returns a cryptographic digest of a specified HTTP request. + + :param data: The string representation of the date to be hashed with a cryptographic hash. + :return: A tuple of (digest, prefix). + The digest is a hashing object that contains the cryptographic digest of + the HTTP request. + The prefix is a string that identifies the cryptographc hash. It is used + to generate the 'Digest' header as specified in RFC 3230. + """ + if self.signing_scheme in {SCHEME_RSA_SHA512, SCHEME_HS2019}: + digest = SHA512.new() + prefix = 'SHA-512=' + elif self.signing_scheme == SCHEME_RSA_SHA256: + digest = SHA256.new() + prefix = 'SHA-256=' + else: + raise Exception("Unsupported signing algorithm: {0}".format(self.signing_scheme)) + digest.update(data) + return digest, prefix + + def _sign_digest(self, digest): + """Signs a message digest with a private key specified in the signing_info. + + :param digest: A hashing object that contains the cryptographic digest of the HTTP request. + :return: A base-64 string representing the cryptographic signature of the input digest. + """ + sig_alg = self.signing_algorithm + if isinstance(self.private_key, RSA.RsaKey): + if sig_alg is None or sig_alg == ALGORITHM_RSASSA_PSS: + # RSASSA-PSS in Section 8.1 of RFC8017. + signature = pss.new(self.private_key).sign(digest) + elif sig_alg == ALGORITHM_RSASSA_PKCS1v15: + # RSASSA-PKCS1-v1_5 in Section 8.2 of RFC8017. + signature = PKCS1_v1_5.new(self.private_key).sign(digest) + else: + raise Exception("Unsupported signature algorithm: {0}".format(sig_alg)) + elif isinstance(self.private_key, ECC.EccKey): + if sig_alg is None: + sig_alg = ALGORITHM_ECDSA_MODE_FIPS_186_3 + if sig_alg in ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS: + signature = DSS.new(self.private_key, sig_alg).sign(digest) + else: + raise Exception("Unsupported signature algorithm: {0}".format(sig_alg)) + else: + raise Exception("Unsupported private key: {0}".format(type(self.private_key))) + return b64encode(signature) + + def _get_authorization_header(self, signed_headers, signed_msg): + """Calculates and returns the value of the 'Authorization' header when signing HTTP requests. + + :param signed_headers : A list of tuples. Each value is the name of a HTTP header that + must be included in the HTTP signature calculation. + :param signed_msg: A base-64 encoded string representation of the signature. + :return: The string value of the 'Authorization' header, representing the signature + of the HTTP request. + """ + created_ts = None + expires_ts = None + for k, v in signed_headers: + if k == HEADER_CREATED: + created_ts = v + elif k == HEADER_EXPIRES: + expires_ts = v + lower_keys = [k.lower() for k, v in signed_headers] + headers_value = " ".join(lower_keys) + + auth_str = "Signature keyId=\"{0}\",algorithm=\"{1}\",".format( + self.key_id, self.signing_scheme) + if created_ts is not None: + auth_str = auth_str + "created={0},".format(created_ts) + if expires_ts is not None: + auth_str = auth_str + "expires={0},".format(expires_ts) + auth_str = auth_str + "headers=\"{0}\",signature=\"{1}\"".format( + headers_value, signed_msg.decode('ascii')) + + print("AUTH: {0}".format(auth_str)) + return auth_str diff --git a/python-experimental/test-requirements.mustache b/python-experimental/test-requirements.mustache index 338b229bae..ebdee3392e 100644 --- a/python-experimental/test-requirements.mustache +++ b/python-experimental/test-requirements.mustache @@ -10,4 +10,7 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 pytest-randomly==1.2.3 # needed for python 2.7+3.4 {{/useNose}} +{{#hasHttpSignatureMethods}} +pycryptodome>=3.9.0 +{{/hasHttpSignatureMethods}} mock; python_version<="2.7" \ No newline at end of file diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 2e74426103..9f5b49f821 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -11,6 +11,28 @@ configuration.password = 'YOUR_PASSWORD' # Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}} configuration.access_token = 'YOUR_BEARER_TOKEN' {{/isBasicBearer}} +{{#isHttpSignature}} +# Configure HTTP signature authorization: {{{name}}} +# You can specify the signing key-id, private key path, signing scheme, signing algorithm, +# list of signed headers and signature max validity. +configuration.signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( + key_id = 'my-key-id', + private_key_path = 'rsa.pem', + signing_scheme = signing.SCHEME_HS2019, + signing_algorithm = signing.ALGORITHM_RSASSA_PSS, + signed_headers = [signing.HEADER_REQUEST_TARGET, + signing.HEADER_CREATED, + signing.HEADER_EXPIRES, + signing.HEADER_HOST, + signing.HEADER_DATE, + signing.HEADER_DIGEST, + 'Content-Type', + 'Content-Length', + 'User-Agent' + ], + signature_max_validity = datetime.timedelta(minutes=5) +) +{{/isHttpSignature}} {{/isBasic}} {{#isApiKey}} # Configure API key authorization: {{{name}}} From 73b434916e889df56b9a81ab1107f3c1e38638f4 Mon Sep 17 00:00:00 2001 From: Fabian von Feilitzsch Date: Tue, 28 Jan 2020 21:58:11 -0800 Subject: [PATCH 080/180] [python] Cleanup ThreadPool with atexit rather than __del__ (#5094) * [python] Cleanup ThreadPool with atexit rather than __del__ This removes the `__del__` function from the generated Python client, and replaces it with a `cleanup` function. When a ThreadPool is created, the cleanup function is registered with the `atexit` module. This fixes #5093, where the API client could hang indefinitely at garbage collection. * Update petstore examples * Test to ensure threadpool is cleaned up * Docs now encourage using the context manager * Regenerate docs * Update samples --- api_client.mustache | 12 ++- api_doc_example.mustache | 32 ++++---- common_README.mustache | 24 +++--- python-experimental/README_common.mustache | 24 +++--- python-experimental/api_client.mustache | 12 ++- python-experimental/api_doc_example.mustache | 86 ++++++++++---------- 6 files changed, 111 insertions(+), 79 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 8297ad5798..08de3bab85 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -2,6 +2,7 @@ {{>partial_header}} from __future__ import absolute_import +import atexit import datetime from dateutil.parser import parse import json @@ -75,11 +76,19 @@ class ApiClient(object): self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' self.client_side_validation = configuration.client_side_validation - def __del__(self): + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def close(self): if self._pool: self._pool.close() self._pool.join() self._pool = None + if hasattr(atexit, 'unregister'): + atexit.unregister(self.close) @property def pool(self): @@ -87,6 +96,7 @@ class ApiClient(object): avoids instantiating unused threadpool for blocking clients. """ if self._pool is None: + atexit.register(self.close) self._pool = ThreadPool(self.pool_threads) return self._pool diff --git a/api_doc_example.mustache b/api_doc_example.mustache index f2d6117a7c..e86c5d6011 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -8,22 +8,26 @@ from pprint import pprint {{#hasAuthMethods}} # Defining host is optional and default to {{{basePath}}} configuration.host = "{{{basePath}}}" -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) + {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}() -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient() as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) + {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/allParams}} {{/hasAuthMethods}} -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} + except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) ``` diff --git a/common_README.mustache b/common_README.mustache index 7de8c9ef09..991002aa17 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -8,18 +8,20 @@ from pprint import pprint {{> python_doc_auth_partial}} # Defining host is optional and default to {{{basePath}}} configuration.host = "{{{basePath}}}" -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) + {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/allParams}} -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} + except ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + {{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} ``` ## Documentation for API Endpoints diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index 5fffdc74fc..b474eb264a 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -7,18 +7,20 @@ from pprint import pprint {{> python_doc_auth_partial}} # Defining host is optional and default to {{{basePath}}} configuration.host = "{{{basePath}}}" -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) -{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} -{{/allParams}} +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) + {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/allParams}} -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + pprint(api_response){{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + {{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} ``` ## Documentation for API Endpoints diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 9520896120..78f502b00d 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -3,6 +3,7 @@ from __future__ import absolute_import import json +import atexit import mimetypes from multiprocessing.pool import ThreadPool import os @@ -74,11 +75,19 @@ class ApiClient(object): # Set default User-Agent. self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' - def __del__(self): + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + self.close() + + def close(self): if self._pool: self._pool.close() self._pool.join() self._pool = None + if hasattr(atexit, 'unregister'): + atexit.unregister(self.close) @property def pool(self): @@ -86,6 +95,7 @@ class ApiClient(object): avoids instantiating unused threadpool for blocking clients. """ if self._pool is None: + atexit.register(self.close) self._pool = ThreadPool(self.pool_threads) return self._pool diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index 8a6beabd2d..565d00a3b9 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -7,51 +7,55 @@ from pprint import pprint {{#hasAuthMethods}} # Defining host is optional and default to {{{basePath}}} configuration.host = "{{{basePath}}}" -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration)) +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{/hasAuthMethods}} {{^hasAuthMethods}} -# Create an instance of the API class -api_instance = {{{packageName}}}.{{{classname}}}() +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{/hasAuthMethods}} -{{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} -{{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} -{{/optionalParams}} -{{#requiredParams}} -{{^hasMore}} + {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} + {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} + {{/optionalParams}} + {{#requiredParams}} + {{^hasMore}} -# example passing only required values which don't have defaults set -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/hasMore}} -{{/requiredParams}} -{{#optionalParams}} -{{^hasMore}} + # example passing only required values which don't have defaults set + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}){{#returnType}} + pprint(api_response){{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + {{/hasMore}} + {{/requiredParams}} + {{#optionalParams}} + {{^hasMore}} -# example passing only required values which don't have defaults set -# and optional values -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}){{#returnType}} - pprint(api_response){{/returnType}} -except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/hasMore}} -{{/optionalParams}} -{{^requiredParams}} -{{^optionalParams}} + # example passing only required values which don't have defaults set + # and optional values + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}){{#returnType}} + pprint(api_response){{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + {{/hasMore}} + {{/optionalParams}} + {{^requiredParams}} + {{^optionalParams}} -# example, this endpoint has no required or optional parameters -try: -{{#summary}} # {{{.}}} -{{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}(){{#returnType}} - pprint(api_response){{/returnType}} -except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/optionalParams}} -{{/requiredParams}} + # example, this endpoint has no required or optional parameters + try: + {{#summary}} # {{{.}}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}(){{#returnType}} + pprint(api_response){{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) + {{/optionalParams}} + {{/requiredParams}} ``` From f538592ff5894788002a0a7e2e4b9bfc7b37d52d Mon Sep 17 00:00:00 2001 From: LoveIsGrief Date: Wed, 29 Jan 2020 10:18:57 +0100 Subject: [PATCH 081/180] Switch to predominant use of appDescriptionWithNewLines in README.mustache (#5109) Descriptions tend to get lengthy and can include multiple lines. New lines are important to markdown formatting/syntax and can't just be ignored. Resolves https://github.com/OpenAPITools/openapi-generator/issues/3704 --- README.mustache | 6 +++--- python-experimental/README.mustache | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.mustache b/README.mustache index 94d72af33d..9d854a4f1b 100644 --- a/README.mustache +++ b/README.mustache @@ -1,7 +1,7 @@ # {{{projectName}}} -{{#appDescription}} -{{{appDescription}}} -{{/appDescription}} +{{#appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} +{{/appDescriptionWithNewLines}} This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: diff --git a/python-experimental/README.mustache b/python-experimental/README.mustache index f26408cf66..72c7f3de3f 100644 --- a/python-experimental/README.mustache +++ b/python-experimental/README.mustache @@ -1,7 +1,7 @@ # {{{projectName}}} -{{#appDescription}} -{{{appDescription}}} -{{/appDescription}} +{{#appDescriptionWithNewLines}} +{{{appDescriptionWithNewLines}}} +{{/appDescriptionWithNewLines}} This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: From 0df7216b683a6d15baa8e0cb0cadd2007042fd9d Mon Sep 17 00:00:00 2001 From: Justin Black Date: Wed, 29 Jan 2020 10:10:41 -0800 Subject: [PATCH 082/180] [Python] Fix #5126 operations with req enums of length one (#5129) * Updates ap.mustache for python-experimental, adds test test_test_endpoint_enums_length_one * Removes sortParamsByRequiredFlag from python-experimental * Removes duplicate params from docstring --- python-experimental/api.mustache | 90 ++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 33 deletions(-) diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 8390a848d2..4cf1d423e8 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -45,7 +45,20 @@ class {{classname}}(object): self.api_client = api_client {{#operation}} - def __{{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 + def __{{operationId}}( + self, +{{#requiredParams}} +{{^defaultValue}} + {{paramName}}, +{{/defaultValue}} +{{/requiredParams}} +{{#requiredParams}} +{{#defaultValue}} + {{paramName}}={{{defaultValue}}}, +{{/defaultValue}} +{{/requiredParams}} + **kwargs + ): """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 {{#notes}} @@ -53,40 +66,51 @@ class {{classname}}(object): {{/notes}} This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True -{{#sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} -{{^sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} + >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) >>> result = thread.get() - :param async_req bool: execute request asynchronously - Default is False. -{{#allParams}} - :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} -{{/allParams}} - :param _return_http_data_only: response data without head status - code and headers. Default is True. - :param _preload_content: if False, the urllib3.HTTPResponse object - will be returned without reading/decoding response data. - Default is True. - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request timeout. It can also - be a pair (tuple) of (connection, read) timeouts. - Default is None. - :param _check_input_type: boolean specifying if type checking - should be done one the data sent to the server. - Default is True. - :param _check_return_type: boolean specifying if type checking - should be done one the data received from the server. - Default is True. - :param _host_index: integer specifying the index of the server - that we want to use. - Default is 0. - :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} - If the method is called asynchronously, returns the request - thread. +{{#requiredParams}} +{{^hasMore}} + Args: +{{/hasMore}} +{{/requiredParams}} +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}} +{{/defaultValue}} +{{/requiredParams}} +{{#requiredParams}} +{{#defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] +{{/defaultValue}} +{{/requiredParams}} + + Keyword Args:{{#optionalParams}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (float/tuple): timeout setting for this request. If one + number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int): specifies the index of the server + that we want to use. + Default is 0. + async_req (bool): execute request asynchronously + + Returns: + {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, returns the request + thread. """ kwargs['async_req'] = kwargs.get( 'async_req', False From d296a2d73f80a442881a47c331f815c1ddb4e3ec Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Mon, 3 Feb 2020 09:39:17 -0800 Subject: [PATCH 083/180] [Python] Python HTTP signature update (#5154) * improve python documentation and add import to __init__package.mustache * improve python documentation and add import to __init__package.mustache * add signing_info parameter conditionally * add code comments and remove 'Content-Length' header from example * Remove debug log statement * set access_token to None by default * set access_token to None by default * fix unit tests for Python experimental * fix trailing space --- configuration.mustache | 41 +++++++++++++++++--- python-experimental/__init__package.mustache | 3 ++ python-experimental/signing.mustache | 20 +++++++++- 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 3e0a156765..0645bc4675 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -31,11 +31,16 @@ class Configuration(object): The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication - :param signing_info: Configuration parameters for HTTP signature. +{{#hasHttpSignatureMethods}} + :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration +{{/hasHttpSignatureMethods}} +{{#hasAuthMethods}} :Example: +{{#hasApiKeyMethods}} + API Key Authentication Example. Given the following security scheme in the OpenAPI specification: components: securitySchemes: @@ -51,12 +56,32 @@ class Configuration(object): ) The following cookie will be added to the HTTP request: Cookie: JSESSIONID abc123 +{{/hasApiKeyMethods}} +{{#hasHttpBasicMethods}} + + HTTP Basic Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + http_basic_auth: + type: http + scheme: basic Configure API client with HTTP basic authentication: conf = {{{packageName}}}.Configuration( username='the-user', password='the-password', ) +{{/hasHttpBasicMethods}} +{{#hasHttpSignatureMethods}} + + HTTP Signature Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + http_basic_auth: + type: http + scheme: signature Configure API client with HTTP signature authentication. Use the 'hs2019' signature scheme, sign the HTTP requests with the RSA-SSA-PSS signature algorithm, and set the expiration time @@ -83,18 +108,22 @@ class Configuration(object): signing.HEADER_DATE, signing.HEADER_DIGEST, 'Content-Type', - 'Content-Length', 'User-Agent' ], signature_max_validity = datetime.timedelta(minutes=5) ) ) +{{/hasHttpSignatureMethods}} +{{/hasAuthMethods}} """ def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, username=None, password=None, - signing_info=None): +{{#hasHttpSignatureMethods}} + signing_info=None, +{{/hasHttpSignatureMethods}} + ): """Constructor """ self.host = host @@ -123,19 +152,21 @@ class Configuration(object): self.password = password """Password for HTTP basic authentication """ +{{#hasHttpSignatureMethods}} if signing_info is not None: signing_info.host = host self.signing_info = signing_info """The HTTP signing configuration """ +{{/hasHttpSignatureMethods}} {{#hasOAuthMethods}} - self.access_token = "" + self.access_token = None """access token for OAuth/Bearer """ {{/hasOAuthMethods}} {{^hasOAuthMethods}} {{#hasBearerMethods}} - self.access_token = "" + self.access_token = None """access token for OAuth/Bearer """ {{/hasBearerMethods}} diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache index b5224a5821..1d74d016ab 100644 --- a/python-experimental/__init__package.mustache +++ b/python-experimental/__init__package.mustache @@ -20,6 +20,9 @@ from {{packageName}}.api_client import ApiClient # import Configuration from {{packageName}}.configuration import Configuration +{{#hasHttpSignatureMethods}} +from {{packageName}}.signing import HttpSigningConfiguration +{{/hasHttpSignatureMethods}} # import exceptions from {{packageName}}.exceptions import OpenApiException diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index d191bbf485..300efa007b 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -15,18 +15,35 @@ import re from six.moves.urllib.parse import urlencode, urlparse from time import mktime +# The constants below define a subset of HTTP headers that can be included in the +# HTTP signature scheme. Additional headers may be included in the signature. + +# The '(request-target)' header is a calculated field that includes the HTTP verb, +# the URL path and the URL query. HEADER_REQUEST_TARGET = '(request-target)' +# The time when the HTTP signature was generated. HEADER_CREATED = '(created)' +# The time when the HTTP signature expires. The API server should reject HTTP requests +# that have expired. HEADER_EXPIRES = '(expires)' +# The 'Host' header. HEADER_HOST = 'Host' +# The 'Date' header. HEADER_DATE = 'Date' -HEADER_DIGEST = 'Digest' # RFC 3230, include digest of the HTTP request body. +# When the 'Digest' header is included in the HTTP signature, the client automatically +# computes the digest of the HTTP request body, per RFC 3230. +HEADER_DIGEST = 'Digest' +# The 'Authorization' header is automatically generated by the client. It includes +# the list of signed headers and a base64-encoded signature. HEADER_AUTHORIZATION = 'Authorization' +# The constants below define the cryptographic schemes for the HTTP signature scheme. SCHEME_HS2019 = 'hs2019' SCHEME_RSA_SHA256 = 'rsa-sha256' SCHEME_RSA_SHA512 = 'rsa-sha512' +# The constants below define the signature algorithms that can be used for the HTTP +# signature scheme. ALGORITHM_RSASSA_PSS = 'RSASSA-PSS' ALGORITHM_RSASSA_PKCS1v15 = 'RSASSA-PKCS1-v1_5' @@ -364,5 +381,4 @@ class HttpSigningConfiguration(object): auth_str = auth_str + "headers=\"{0}\",signature=\"{1}\"".format( headers_value, signed_msg.decode('ascii')) - print("AUTH: {0}".format(auth_str)) return auth_str From f82715a3ac59b492c6cf50076dbe5bcadcefbe9e Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 6 Feb 2020 09:48:23 -0800 Subject: [PATCH 084/180] [python] use datetime aware object (#5209) * python use aware datetime object * python use aware datetime object * python use aware datetime object * python use aware datetime object * python use aware datetime object * python use aware datetime object --- python-experimental/signing.mustache | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index 300efa007b..f52feb8f12 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -7,13 +7,12 @@ from Crypto.IO import PEM, PKCS8 from Crypto.Hash import SHA256, SHA512 from Crypto.PublicKey import RSA, ECC from Crypto.Signature import PKCS1_v1_5, pss, DSS -from datetime import datetime from email.utils import formatdate import json import os import re from six.moves.urllib.parse import urlencode, urlparse -from time import mktime +from time import time # The constants below define a subset of HTTP headers that can be included in the # HTTP signature scheme. Additional headers may be included in the signature. @@ -228,12 +227,6 @@ class HttpSigningConfiguration(object): "Signing algorithm {0} is not compatible with private key".format( self.signing_algorithm)) - def _get_unix_time(self, ts): - """Converts and returns a datetime object to UNIX time, the number of seconds - elapsed since January 1, 1970 UTC. - """ - return (ts - datetime(1970, 1, 1)).total_seconds() - def _get_signed_header_info(self, resource_path, method, headers, body, query_params): """Build the HTTP headers (name, value) that need to be included in the HTTP signature scheme. @@ -262,15 +255,16 @@ class HttpSigningConfiguration(object): if query_params: request_target += "?" + urlencode(query_params) - # Get current time and generate RFC 1123 (HTTP/1.1) date/time string. - now = datetime.now() - stamp = mktime(now.timetuple()) - cdate = formatdate(timeval=stamp, localtime=False, usegmt=True) + # Get UNIX time, e.g. seconds since epoch, not including leap seconds. + now = time() + # Format date per RFC 7231 section-7.1.1.2. An example is: + # Date: Wed, 21 Oct 2015 07:28:00 GMT + cdate = formatdate(timeval=now, localtime=False, usegmt=True) # The '(created)' value MUST be a Unix timestamp integer value. # Subsecond precision is not supported. - created = int(self._get_unix_time(now)) + created = int(now) if self.signature_max_validity is not None: - expires = self._get_unix_time(now + self.signature_max_validity) + expires = now + self.signature_max_validity.total_seconds() signed_headers_list = [] request_headers_dict = {} From 9977d22bf758b7c9c7ceec66973bcb2829ce0333 Mon Sep 17 00:00:00 2001 From: Fabian von Feilitzsch Date: Thu, 6 Feb 2020 13:58:17 -0800 Subject: [PATCH 085/180] [Python] 5094 followup - Reduce redundancy in docs (#5161) * Reduce redundancy in python docs This is a followup to PR #5094, which had a few unresolved comments at merge time. This reduces the amount of redundant lines in the api example doc templates, and ensures that referenced Configuration objects are actually instantiated. * Regenerate samples --- api_doc_example.mustache | 11 ++--------- python-experimental/api_doc_example.mustache | 11 +++-------- python_doc_auth_partial.mustache | 3 +++ 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/api_doc_example.mustache b/api_doc_example.mustache index e86c5d6011..dadb8f6a96 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -5,24 +5,17 @@ import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint {{> python_doc_auth_partial}} -{{#hasAuthMethods}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" # Enter a context with an instance of the API client +{{#hasAuthMethods}} with {{{packageName}}}.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) - {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} - {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} -# Enter a context with an instance of the API client with {{{packageName}}}.ApiClient() as api_client: +{{/hasAuthMethods}} # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} -{{/hasAuthMethods}} try: {{#summary}} # {{{.}}} diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index 565d00a3b9..ae7b8a6979 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -4,20 +4,15 @@ import time import {{{packageName}}} from pprint import pprint {{> python_doc_auth_partial}} -{{#hasAuthMethods}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" # Enter a context with an instance of the API client +{{#hasAuthMethods}} with {{{packageName}}}.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{/hasAuthMethods}} {{^hasAuthMethods}} -# Enter a context with an instance of the API client -with {{{packageName}}}.ApiClient(configuration) as api_client: +with {{{packageName}}}.ApiClient() as api_client: +{{/hasAuthMethods}} # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) -{{/hasAuthMethods}} {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 9f5b49f821..d8cfc4ad11 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -45,4 +45,7 @@ configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' configuration.access_token = 'YOUR_ACCESS_TOKEN' {{/isOAuth}} {{/authMethods}} + +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" {{/hasAuthMethods}} From fd4cd68d958e65cf1a9e29d872ec8550babf7c82 Mon Sep 17 00:00:00 2001 From: LoveIsGrief Date: Mon, 17 Feb 2020 15:36:21 +0100 Subject: [PATCH 086/180] python: Add gitlab-ci.mustache (#5342) * python: Add gitlab-ci.mustache It does the same stuff as in the .travis.yml but just for Gitlab CI #5340 - Python .gitlab-ci.yml * python: Run all scripts in bin find bin/ -type f -name 'python*.sh' -exec {} \; Had to update all samples --- gitlab-ci.mustache | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 gitlab-ci.mustache diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache new file mode 100644 index 0000000000..28046fefa0 --- /dev/null +++ b/gitlab-ci.mustache @@ -0,0 +1,33 @@ +# ref: https://docs.gitlab.com/ee/ci/README.html + +stages: + - test + +.nosetest: + stage: test + script: + - pip install -r requirements.txt + - pip install nose + - nosetests + +nosetest-2.7: + extends: .nosetest + image: python:2.7-alpine +nosetest-3.3: + extends: .nosetest + image: python:3.3-alpine +nosetest-3.4: + extends: .nosetest + image: python:3.4-alpine +nosetest-3.5: + extends: .nosetest + image: python:3.5-alpine +nosetest-3.6: + extends: .nosetest + image: python:3.6-alpine +nosetest-3.7: + extends: .nosetest + image: python:3.7-alpine +nosetest-3.8: + extends: .nosetest + image: python:3.8-alpine From 57f7c721dfca35ed02a64d4785703e3fbca94d4d Mon Sep 17 00:00:00 2001 From: LoveIsGrief Date: Thu, 20 Feb 2020 14:47:13 +0100 Subject: [PATCH 087/180] Respect usenose for Python CI (#5376) * python: Respect useNose option in generated CI templates Travis and Gitlab CI now use nosetests or pytests depending on the "useNose" option that is passed. * python: Update CI samples They now respect the "useNose" option --- gitlab-ci.mustache | 7 ++++++- travis.mustache | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache index 28046fefa0..2cabff63c7 100644 --- a/gitlab-ci.mustache +++ b/gitlab-ci.mustache @@ -7,8 +7,13 @@ stages: stage: test script: - pip install -r requirements.txt - - pip install nose + - pip install -r test-requirements.txt + {{#useNose}} - nosetests + {{/useNose}} + {{^useNose}} + - pytest --cov={{{packageName}}} + {{/useNose}} nosetest-2.7: extends: .nosetest diff --git a/travis.mustache b/travis.mustache index 388de83128..195488737d 100644 --- a/travis.mustache +++ b/travis.mustache @@ -10,6 +10,13 @@ python: - "3.7" - "3.8" # command to install dependencies -install: "pip install -r requirements.txt" +install: + - "pip install -r requirements.txt" + - "pip install -r test-requirements.txt" # command to run tests +{{#useNose}} script: nosetests +{{/useNose}} +{{^useNose}} +script: pytest --cov={{{packageName}}} +{{/useNose}} From 686c3f76529f05d4b97ffe49851e9200e021eed4 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 21 Feb 2020 14:51:24 -0800 Subject: [PATCH 088/180] [Python] add discard_unknown_keys parameter (#5362) * add discard_unknown_key parameter * add discard_unknown_key parameter * add discard_unknown_key parameter * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * discard unknown keys in composed schema if configuration.discard_unknown_keys is set * run sample scripts for python * code reformatting * execute script in bin directory * improve unit tests for discarding properties --- configuration.mustache | 13 +++++++++ .../method_init_composed.mustache | 13 +++++---- .../method_init_normal.mustache | 12 ++++---- .../method_init_shared.mustache | 8 +++++- python-experimental/model_utils.mustache | 28 ++++++++++--------- 5 files changed, 48 insertions(+), 26 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 0645bc4675..8228fff6a8 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -31,6 +31,17 @@ class Configuration(object): The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication + :param discard_unknown_keys: Boolean value indicating whether to discard + unknown properties. A server may send a response that includes additional + properties that are not known by the client in the following scenarios: + 1. The OpenAPI document is incomplete, i.e. it does not match the server + implementation. + 2. The client was generated using an older version of the OpenAPI document + and the server has been upgraded since then. + If a schema in the OpenAPI document defines the additionalProperties attribute, + then all undeclared properties received by the server are injected into the + additional properties map. In that case, there are undeclared properties, and + nothing to discard. {{#hasHttpSignatureMethods}} :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration @@ -120,6 +131,7 @@ class Configuration(object): def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, username=None, password=None, + discard_unknown_keys=False, {{#hasHttpSignatureMethods}} signing_info=None, {{/hasHttpSignatureMethods}} @@ -152,6 +164,7 @@ class Configuration(object): self.password = password """Password for HTTP basic authentication """ + self.discard_unknown_keys = discard_unknown_keys {{#hasHttpSignatureMethods}} if signing_info is not None: signing_info.host = host diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index 5ed5993fe9..5a1ece1f92 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -11,12 +11,6 @@ {{> python-experimental/model_templates/method_init_shared }} - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration - constant_args = { '_check_type': _check_type, '_path_to_item': _path_to_item, @@ -34,9 +28,16 @@ self._composed_instances = composed_info[0] self._var_name_to_model_instances = composed_info[1] self._additional_properties_model_instances = composed_info[2] + unused_args = composed_info[3] {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} for var_name, var_value in six.iteritems(kwargs): + if var_name in unused_args and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + not self._additional_properties_model_instances: + # discard variable. + continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index b053427a79..d26506c56c 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -8,14 +8,14 @@ {{> python-experimental/model_templates/method_init_shared }} - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration - {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} for var_name, var_value in six.iteritems(kwargs): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 2f3b70ea69..318d693e15 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -20,4 +20,10 @@ If passed, type conversion is attempted If omitted no type conversion is done.{{#optionalVars}} {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} - """ \ No newline at end of file + """ + + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index c3d9e7d536..8193d8a3b2 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -677,8 +677,9 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, if not valid_classes_coercible or key_type: # we do not handle keytype errors, json will take care # of this for us - raise get_type_error(input_value, path_to_item, valid_classes, - key_type=key_type) + if configuration is None or not configuration.discard_unknown_keys: + raise get_type_error(input_value, path_to_item, valid_classes, + key_type=key_type) for valid_class in valid_classes_coercible: try: if issubclass(valid_class, OpenApiModel): @@ -1117,16 +1118,16 @@ def validate_get_composed_info(constant_args, model_args, self): # set any remaining values unused_args = get_unused_args(self, composed_instances, model_args) - if len(unused_args) > 0: - if len(additional_properties_model_instances) == 0: - raise ApiValueError( - "Invalid input arguments input when making an instance of " - "class %s. Not all inputs were used. The unused input data " - "is %s" % (self.__class__.__name__, unused_args) - ) - for var_name, var_value in six.iteritems(unused_args): - for instance in additional_properties_model_instances: - setattr(instance, var_name, var_value) + if len(unused_args) > 0 and \ + len(additional_properties_model_instances) == 0 and \ + (self._configuration is None or + not self._configuration.discard_unknown_keys): + raise ApiValueError( + "Invalid input arguments input when making an instance of " + "class %s. Not all inputs were used. The unused input data " + "is %s" % (self.__class__.__name__, unused_args) + ) + # no need to add additional_properties to var_name_to_model_instances here # because additional_properties_model_instances will direct us to that # instance when we use getattr or setattr @@ -1135,5 +1136,6 @@ def validate_get_composed_info(constant_args, model_args, self): return [ composed_instances, var_name_to_model_instances, - additional_properties_model_instances + additional_properties_model_instances, + unused_args ] From f20a3a39d6131179d3426632e46839201e9b48ad Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Sun, 23 Feb 2020 21:10:44 +0100 Subject: [PATCH 089/180] [python] add method to set/get default configuration (#5315) * [python] add method to set/get default configuration * [python] change method name and fix handling api_key * python: using modified deepcopy to set/get default configuration * python: update samples * python: update samples --- api_client.mustache | 2 +- configuration.mustache | 42 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index 08de3bab85..52b2ec2f3d 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -63,7 +63,7 @@ class ApiClient(object): def __init__(self, configuration=None, header_name=None, header_value=None, cookie=None, pool_threads=1): if configuration is None: - configuration = Configuration() + configuration = Configuration.get_default_copy() self.configuration = configuration self.pool_threads = pool_threads diff --git a/configuration.mustache b/configuration.mustache index 8228fff6a8..6581e603ad 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -4,6 +4,7 @@ from __future__ import absolute_import +import copy import logging {{^asyncio}} import multiprocessing @@ -128,6 +129,8 @@ class Configuration(object): {{/hasAuthMethods}} """ + _default = None + def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, username=None, password=None, @@ -254,6 +257,45 @@ class Configuration(object): # Disable client side validation self.client_side_validation = True + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k not in ('logger', 'logger_file_handler'): + setattr(result, k, copy.deepcopy(v, memo)) + # shallow copy of loggers + result.logger = copy.copy(self.logger) + # use setters to configure loggers + result.logger_file = self.logger_file + result.debug = self.debug + return result + + @classmethod + def set_default(cls, default): + """Set default instance of configuration. + + It stores default configuration, which can be + returned by get_default_copy method. + + :param default: object of Configuration + """ + cls._default = copy.deepcopy(default) + + @classmethod + def get_default_copy(cls): + """Return new instance of configuration. + + This method returns newly created, based on default constructor, + object of Configuration class or returns a copy of default + configuration passed by the set_default method. + + :return: The configuration object. + """ + if cls._default is not None: + return copy.deepcopy(cls._default) + return Configuration() + @property def logger_file(self): """The logger file. From c3ed779ac85b5c7eb44a3c9099a9cbde9bc11f82 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 28 Feb 2020 14:21:08 -0800 Subject: [PATCH 090/180] [python] Adds python oneOf/anyOf models + tests (#5341) * Adds oneOf + anyOf schemas, models and tests to python-experimental * Adds setUpClass and tearDownClass * Removes newline in method_init_shared.mustache * Regenerated v3 spec sample for python-experimental * Fxes test for discard_unknown_keys * Moves new models into existing spec, regen python-exp and go-exp * Also fix python-exp windows file --- python-experimental/model.mustache | 1 + .../method_init_composed.mustache | 14 +++++++--- .../method_init_shared.mustache | 28 ++++++++++++++----- .../methods_setattr_getattr_composed.mustache | 20 +++++++------ python-experimental/model_utils.mustache | 28 ++++++++++++++----- python-experimental/requirements.mustache | 1 + python-experimental/setup.mustache | 1 + 7 files changed, 66 insertions(+), 27 deletions(-) diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 0ca198ddf9..ef7da57282 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -7,6 +7,7 @@ import re # noqa: F401 import sys # noqa: F401 import six # noqa: F401 +import nulltype # noqa: F401 from {{packageName}}.model_utils import ( # noqa: F401 ModelComposed, diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index 5a1ece1f92..e00bf129b2 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -17,11 +17,18 @@ '_from_server': _from_server, '_configuration': _configuration, } - model_args = { + required_args = { {{#requiredVars}} '{{name}}': {{name}}, {{/requiredVars}} } + # remove args whose value is Null because they are unset + required_arg_names = list(required_args.keys()) + for required_arg_name in required_arg_names: + if required_args[required_arg_name] is nulltype.Null: + del required_args[required_arg_name] + model_args = {} + model_args.update(required_args) model_args.update(kwargs) composed_info = validate_get_composed_info( constant_args, model_args, self) @@ -30,9 +37,8 @@ self._additional_properties_model_instances = composed_info[2] unused_args = composed_info[3] -{{#requiredVars}} - self.{{name}} = {{name}} -{{/requiredVars}} + for var_name, var_value in required_args.items(): + setattr(self, var_name, var_value) for var_name, var_value in six.iteritems(kwargs): if var_name in unused_args and \ self._configuration is not None and \ diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 318d693e15..9dd5bc2b6f 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,11 +1,23 @@ def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI -{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} -{{/hasMore}}{{/requiredVars}} - Keyword Args:{{#requiredVars}}{{#defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} +{{#requiredVars}} +{{#-first}} + Args: +{{/-first}} +{{^defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}} +{{/defaultValue}} +{{#-last}} + +{{/-last}} +{{/requiredVars}} + Keyword Args: +{{#requiredVars}} +{{#defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 +{{/defaultValue}} +{{/requiredVars}} _check_type (bool): if True, values for parameters in openapi_types will be type checked and a TypeError will be raised if the wrong type is input. @@ -18,8 +30,10 @@ _configuration (Configuration): the instance to use when deserializing a file_type parameter. If passed, type conversion is attempted - If omitted no type conversion is done.{{#optionalVars}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} + If omitted no type conversion is done. +{{#optionalVars}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 +{{/optionalVars}} """ self._data_store = {} diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index e5eee88a96..9adb2a08a1 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -41,21 +41,23 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) + values = set() if model_instances: - values = set() for model_instance in model_instances: if name in model_instance._data_store: values.add(model_instance._data_store[name]) - if len(values) == 1: - return list(values)[0] + len_values = len(values) + if len_values == 0: + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) + elif len_values == 1: + return list(values)[0] + elif len_values > 1: raise ApiValueError( "Values stored for property {0} in {1} difffer when looking " "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), path_to_item - ) - - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), - path_to_item - ) \ No newline at end of file + ) \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 8193d8a3b2..7f05f2dbe8 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -828,7 +828,7 @@ def model_to_dict(model_instance, serialize=True): model_instances = [model_instance] if model_instance._composed_schemas() is not None: - model_instances = model_instance._composed_instances + model_instances.extend(model_instance._composed_instances) for model_instance in model_instances: for attr, value in six.iteritems(model_instance._data_store): if serialize: @@ -951,12 +951,12 @@ def get_oneof_instance(self, model_args, constant_args): used to make instances Returns - oneof_instance (instance) + oneof_instance (instance/None) """ - oneof_instance = None if len(self._composed_schemas()['oneOf']) == 0: - return oneof_instance + return None + oneof_instances = [] for oneof_class in self._composed_schemas()['oneOf']: # transform js keys to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( @@ -969,20 +969,30 @@ def get_oneof_instance(self, model_args, constant_args): if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] + # do not try to make a model with no input args + if len(kwargs) == 0: + continue + # and use it to make the instance kwargs.update(constant_args) try: oneof_instance = oneof_class(**kwargs) - break + oneof_instances.append(oneof_instance) except Exception: pass - if oneof_instance is None: + if len(oneof_instances) == 0: raise ApiValueError( "Invalid inputs given to generate an instance of %s. Unable to " "make any instances of the classes in oneOf definition." % self.__class__.__name__ ) - return oneof_instance + elif len(oneof_instances) > 1: + raise ApiValueError( + "Invalid inputs given to generate an instance of %s. Multiple " + "oneOf instances were generated when a max of one is allowed." % + self.__class__.__name__ + ) + return oneof_instances[0] def get_anyof_instances(self, model_args, constant_args): @@ -1012,6 +1022,10 @@ def get_anyof_instances(self, model_args, constant_args): if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] + # do not try to make a model with no input args + if len(kwargs) == 0: + continue + # and use it to make the instance kwargs.update(constant_args) try: diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache index eb358efd5b..a56bedffbf 100644 --- a/python-experimental/requirements.mustache +++ b/python-experimental/requirements.mustache @@ -1,3 +1,4 @@ +nulltype certifi >= 14.05.14 future; python_version<="2.7" six >= 1.10 diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 2fe84efcee..796475c456 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -21,6 +21,7 @@ REQUIRES = [ "six >= 1.10", "certifi", "python-dateutil", + "nulltype", {{#asyncio}} "aiohttp >= 3.0.0", {{/asyncio}} From f6e96443584a81e14a62bd969ee766a598651137 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 6 Mar 2020 17:25:45 -0800 Subject: [PATCH 091/180] Add serialization of ModelComposed (#5551) --- python-experimental/api_client.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 78f502b00d..774dae89c6 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -21,6 +21,7 @@ from {{packageName}}.exceptions import ApiValueError from {{packageName}}.model_utils import ( ModelNormal, ModelSimple, + ModelComposed, date, datetime, deserialize_file, @@ -240,7 +241,7 @@ class ApiClient(object): if isinstance(obj, dict): obj_dict = obj - elif isinstance(obj, ModelNormal): + elif isinstance(obj, ModelNormal) or isinstance(obj, ModelComposed): # Convert model obj to dict # Convert attribute name to json key in # model definition for request From 446507eeeb3ef5e641182fb6feac15492d94a3ea Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 6 Mar 2020 20:22:19 -0800 Subject: [PATCH 092/180] Fixes kwargs typos, removes E501s (#5552) --- api.mustache | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/api.mustache b/api.mustache index f1a110bd47..f2c5541835 100644 --- a/api.mustache +++ b/api.mustache @@ -10,7 +10,7 @@ import re # noqa: F401 import six from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( +from {{packageName}}.exceptions import ( # noqa: F401 ApiTypeError, ApiValueError ) @@ -99,20 +99,36 @@ class {{classname}}(object): """ {{#servers.0}} - local_var_hosts = [{{#servers}}'{{{url}}}'{{^-last}}, {{/-last}}{{/servers}}] # noqa: E501 + local_var_hosts = [ +{{#servers}} + '{{{url}}}'{{^-last}},{{/-last}} +{{/servers}} + ] local_var_host = local_var_hosts[0] if kwargs.get('_host_index'): - if int(kwags.get('_host_index')) < 0 or int(kawgs.get('_host_index')) >= len(local_var_hosts): - raise ApiValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) - local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] + _host_index = int(kwargs.get('_host_index')) + if _host_index < 0 or _host_index >= len(local_var_hosts): + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" + % len(local_var_host) + ) + local_var_host = local_var_hosts[_host_index] {{/servers.0}} local_var_params = locals() - all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 - all_params.append('async_req') - all_params.append('_return_http_data_only') - all_params.append('_preload_content') - all_params.append('_request_timeout') + all_params = [ +{{#allParams}} + '{{paramName}}'{{#hasMore}},{{/hasMore}} +{{/allParams}} + ] + all_params.extend( + [ + 'async_req', + '_return_http_data_only', + '_preload_content', + '_request_timeout' + ] + ) for key, val in six.iteritems(local_var_params['kwargs']): if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: From 185cd3e88627d23dbcf24ed14f5d1b4c4ae203b7 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Wed, 25 Mar 2020 15:59:27 +0100 Subject: [PATCH 093/180] [python/asyncio] explicitly close client session via async context manager (#5621) --- api_client.mustache | 14 +++++++++++++- asyncio/rest.mustache | 5 ++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index 52b2ec2f3d..c69e7d5945 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -76,13 +76,25 @@ class ApiClient(object): self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' self.client_side_validation = configuration.client_side_validation + {{#asyncio}} + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.close() + {{/asyncio}} + {{^asyncio}} def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() + {{/asyncio}} - def close(self): + {{#asyncio}}async {{/asyncio}}def close(self): + {{#asyncio}} + await self.rest_client.close() + {{/asyncio}} if self._pool: self._pool.close() self._pool.join() diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 4585f1c6ad..e797d0ae7a 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -10,7 +10,6 @@ import ssl import aiohttp import certifi -import asyncio # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode @@ -77,8 +76,8 @@ class RESTClientObject(object): connector=connector ) - def __del__(self): - asyncio.ensure_future(self.pool_manager.close()) + async def close(self): + await self.pool_manager.close() async def request(self, method, url, query_params=None, headers=None, body=None, post_params=None, _preload_content=True, From c2dadaef904be181ab773e6968ded9a30a8bcb12 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 3 Apr 2020 20:49:23 -0700 Subject: [PATCH 094/180] [Python-experimental] Documentation enhancement for oneOf schema and minor err msg improvement (#5791) * Add documentation to generated code * Improve error message * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Run sample scripts * Address review comments * Address review comments * Fix problem in python error message --- python-experimental/model_utils.mustache | 69 ++++++++++++++++++------ 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 7f05f2dbe8..8b60618c1d 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -464,7 +464,11 @@ def get_required_type_classes(required_types_mixed): def change_keys_js_to_python(input_dict, model_class): """ Converts from javascript_key keys in the input_dict to python_keys in - the output dict using the mapping in model_class + the output dict using the mapping in model_class. + If the input_dict contains a key which does not declared in the model_class, + the key is added to the output dict as is. The assumption is the model_class + may have undeclared properties (additionalProperties attribute in the OAS + document). """ output_dict = {} @@ -936,19 +940,39 @@ def get_allof_instances(self, model_args, constant_args): # and use it to make the instance kwargs.update(constant_args) - allof_instance = allof_class(**kwargs) - composed_instances.append(allof_instance) + try: + allof_instance = allof_class(**kwargs) + composed_instances.append(allof_instance) + except Exception as ex: + raise ApiValueError( + "Invalid inputs given to generate an instance of '%s'. The " + "input data was invalid for the allOf schema '%s' in the composed " + "schema '%s'. Error=%s" % ( + allof_class.__class__.__name__, + allof_class.__class__.__name__, + self.__class__.__name__, + str(ex) + ) + ) return composed_instances def get_oneof_instance(self, model_args, constant_args): """ + Find the oneOf schema that matches the input data (e.g. payload). + If exactly one schema matches the input data, an instance of that schema + is returned. + If zero or more than one schema match the input data, an exception is raised. + In OAS 3.x, the payload MUST, by validation, match exactly one of the + schemas described by oneOf. Args: self: the class we are handling model_args (dict): var_name to var_value - used to make instances + The input data, e.g. the payload that must match a oneOf schema + in the OpenAPI document. constant_args (dict): var_name to var_value - used to make instances + args that every model requires, including configuration, server + and path to item. Returns oneof_instance (instance/None) @@ -957,12 +981,17 @@ def get_oneof_instance(self, model_args, constant_args): return None oneof_instances = [] + # Iterate over each oneOf schema and determine if the input data + # matches the oneOf schemas. for oneof_class in self._composed_schemas()['oneOf']: - # transform js keys to python keys in fixed_model_args + # transform js keys from input data to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( model_args, oneof_class) - # extract a dict of only required keys from fixed_model_args + # Extract a dict with the properties that are declared in the oneOf schema. + # Undeclared properties (e.g. properties that are allowed because of the + # additionalProperties attribute in the OAS document) are not added to + # the dict. kwargs = {} var_names = set(oneof_class.openapi_types().keys()) for var_name in var_names: @@ -982,14 +1011,14 @@ def get_oneof_instance(self, model_args, constant_args): pass if len(oneof_instances) == 0: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. Unable to " - "make any instances of the classes in oneOf definition." % + "Invalid inputs given to generate an instance of %s. None " + "of the oneOf schemas matched the input data." % self.__class__.__name__ ) elif len(oneof_instances) > 1: raise ApiValueError( "Invalid inputs given to generate an instance of %s. Multiple " - "oneOf instances were generated when a max of one is allowed." % + "oneOf schemas matched the inputs, but a max of one is allowed." % self.__class__.__name__ ) return oneof_instances[0] @@ -1035,8 +1064,8 @@ def get_anyof_instances(self, model_args, constant_args): pass if len(anyof_instances) == 0: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. Unable to " - "make any instances of the classes in anyOf definition." % + "Invalid inputs given to generate an instance of %s. None of the " + "anyOf schemas matched the inputs." % self.__class__.__name__ ) return anyof_instances @@ -1087,10 +1116,18 @@ def get_unused_args(self, composed_instances, model_args): def validate_get_composed_info(constant_args, model_args, self): """ - For composed schemas/classes, validates the classes to make sure that - they do not share any of the same parameters. If there is no collision - then composed model instances are created and returned tot the calling - self model + For composed schemas, generate schema instances for + all schemas in the oneOf/anyOf/allOf definition. If additional + properties are allowed, also assign those properties on + all matched schemas that contain additionalProperties. + Openapi schemas are python classes. + + Exceptions are raised if: + - no oneOf schema matches the model_args input data + - > 1 oneOf schema matches the model_args input data + - > 1 oneOf schema matches the model_args input data + - no anyOf schema matches the model_args input data + - any of the allOf schemas do not match the model_args input data Args: constant_args (dict): these are the args that every model requires From 9f5ea5601b7e05050d441195c415a24884df2b53 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Wed, 15 Apr 2020 10:43:33 -0700 Subject: [PATCH 095/180] [Python-experimental] Use DER encoding for ECDSA signatures, add parameter to configure hash algorithm (#5924) * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * fix python unit tests for http message signature * Fix error message * format python code * format python code --- python-experimental/signing.mustache | 46 +++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 7 deletions(-) diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index f52feb8f12..0be0e1c467 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -53,6 +53,10 @@ ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS = { ALGORITHM_ECDSA_MODE_DETERMINISTIC_RFC6979 } +# The cryptographic hash algorithm for the message signature. +HASH_SHA256 = 'sha256' +HASH_SHA512 = 'sha512' + class HttpSigningConfiguration(object): """The configuration parameters for the HTTP signature security scheme. @@ -98,9 +102,15 @@ class HttpSigningConfiguration(object): Supported values are: 1. For RSA keys: RSASSA-PSS, RSASSA-PKCS1-v1_5. 2. For ECDSA keys: fips-186-3, deterministic-rfc6979. - The default value is inferred from the private key. - The default value for RSA keys is RSASSA-PSS. - The default value for ECDSA keys is fips-186-3. + If None, the signing algorithm is inferred from the private key. + The default signing algorithm for RSA keys is RSASSA-PSS. + The default signing algorithm for ECDSA keys is fips-186-3. + :param hash_algorithm: The hash algorithm for the signature. Supported values are + sha256 and sha512. + If the signing_scheme is rsa-sha256, the hash algorithm must be set + to None or sha256. + If the signing_scheme is rsa-sha512, the hash algorithm must be set + to None or sha512. :param signature_max_validity: The signature max validity, expressed as a datetime.timedelta value. It must be a positive value. """ @@ -108,6 +118,7 @@ class HttpSigningConfiguration(object): private_key_passphrase=None, signed_headers=None, signing_algorithm=None, + hash_algorithm=None, signature_max_validity=None): self.key_id = key_id if signing_scheme not in {SCHEME_HS2019, SCHEME_RSA_SHA256, SCHEME_RSA_SHA512}: @@ -118,6 +129,24 @@ class HttpSigningConfiguration(object): self.private_key_path = private_key_path self.private_key_passphrase = private_key_passphrase self.signing_algorithm = signing_algorithm + self.hash_algorithm = hash_algorithm + if signing_scheme == SCHEME_RSA_SHA256: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA256 + elif self.hash_algorithm != HASH_SHA256: + raise Exception("Hash algorithm must be sha256 when security scheme is %s" % + SCHEME_RSA_SHA256) + elif signing_scheme == SCHEME_RSA_SHA512: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA512 + elif self.hash_algorithm != HASH_SHA512: + raise Exception("Hash algorithm must be sha512 when security scheme is %s" % + SCHEME_RSA_SHA512) + elif signing_scheme == SCHEME_HS2019: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA256 + elif self.hash_algorithm not in {HASH_SHA256, HASH_SHA512}: + raise Exception("Invalid hash algorithm") if signature_max_validity is not None and signature_max_validity.total_seconds() < 0: raise Exception("The signature max validity must be a positive value") self.signature_max_validity = signature_max_validity @@ -309,14 +338,14 @@ class HttpSigningConfiguration(object): The prefix is a string that identifies the cryptographc hash. It is used to generate the 'Digest' header as specified in RFC 3230. """ - if self.signing_scheme in {SCHEME_RSA_SHA512, SCHEME_HS2019}: + if self.hash_algorithm == HASH_SHA512: digest = SHA512.new() prefix = 'SHA-512=' - elif self.signing_scheme == SCHEME_RSA_SHA256: + elif self.hash_algorithm == HASH_SHA256: digest = SHA256.new() prefix = 'SHA-256=' else: - raise Exception("Unsupported signing algorithm: {0}".format(self.signing_scheme)) + raise Exception("Unsupported hash algorithm: {0}".format(self.hash_algorithm)) digest.update(data) return digest, prefix @@ -340,7 +369,10 @@ class HttpSigningConfiguration(object): if sig_alg is None: sig_alg = ALGORITHM_ECDSA_MODE_FIPS_186_3 if sig_alg in ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS: - signature = DSS.new(self.private_key, sig_alg).sign(digest) + # draft-ietf-httpbis-message-signatures-00 does not specify the ECDSA encoding. + # Issue: https://github.com/w3c-ccg/http-signatures/issues/107 + signature = DSS.new(key=self.private_key, mode=sig_alg, + encoding='der').sign(digest) else: raise Exception("Unsupported signature algorithm: {0}".format(sig_alg)) else: From f91931de3b4069499655f0b12501d5631bbbff58 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Wed, 15 Apr 2020 17:02:56 -0700 Subject: [PATCH 096/180] [Python-experimental] Fix TypeError: unhashable type: 'list' (#5810) * handle scenario when value is a list, fix TypeError: unhashable type: 'list' * Add __hash__ function * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set --- .../methods_setattr_getattr_composed.mustache | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index 9adb2a08a1..9420fe1582 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -41,11 +41,17 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) - values = set() + values = [] + # A composed model stores child (oneof/anyOf/allOf) models under + # self._var_name_to_model_instances. A named property can exist in + # multiple child models. If the property is present in more than one + # child model, the value must be the same across all the child models. if model_instances: for model_instance in model_instances: if name in model_instance._data_store: - values.add(model_instance._data_store[name]) + v = model_instance._data_store[name] + if v not in values: + values.append(v) len_values = len(values) if len_values == 0: raise ApiKeyError( @@ -53,10 +59,10 @@ path_to_item ) elif len_values == 1: - return list(values)[0] + return values[0] elif len_values > 1: raise ApiValueError( - "Values stored for property {0} in {1} difffer when looking " + "Values stored for property {0} in {1} differ when looking " "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), path_to_item From 1fbc64d84b36d5ab5e831689ed61cfdae8043f17 Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Thu, 16 Apr 2020 03:16:08 +0200 Subject: [PATCH 097/180] [python/asyncio] fix passing proxy parameters to aiohttp (#5943) --- asyncio/rest.mustache | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index e797d0ae7a..f2099c7531 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -65,16 +65,13 @@ class RESTClientObject(object): ssl=ssl_context ) + self.proxy = configuration.proxy + self.proxy_headers = configuration.proxy_headers + # https pool manager - if configuration.proxy: - self.pool_manager = aiohttp.ClientSession( - connector=connector, - proxy=configuration.proxy - ) - else: - self.pool_manager = aiohttp.ClientSession( - connector=connector - ) + self.pool_manager = aiohttp.ClientSession( + connector=connector + ) async def close(self): await self.pool_manager.close() @@ -122,6 +119,11 @@ class RESTClientObject(object): "headers": headers } + if self.proxy: + args["proxy"] = self.proxy + if self.proxy_headers: + args["proxy_headers"] = self.proxy_headers + if query_params: args["url"] += '?' + urlencode(query_params) From abd9642e2fb2333ece9a0029cdea352c073e89c2 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 22 Apr 2020 11:47:08 +0800 Subject: [PATCH 098/180] Sync master to 5.0.x (#5968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Change the Model template (#5222) * Add a link to Xero blog post (#5426) * Removal of Encoding in the Query-Params in order to prevent double Encoding. (#5255) This way letting WebClient do its Job in encoding the URL. * update java webclient sample * [kotlin][client] Add Jackson as serialization library (#5236) * [kotlin][client] Add Jackson as serialization library * [kotlin][client] Add kotlin-client-jackson.sh to kotlin-client-all.sh * update kotlin client samples * update doc Co-authored-by: William Cheng * include kotlin jackson in CI tests (#5438) * [Ruby] Add error output (#5428) * Add error output to the log so that we can make sure why the error occurred * Fix forbidden method invocation using default charsets * Update usage.md (#5443) * fix NPE for enum (#5445) * [Java][WebClient] better code format (#5433) * better code format for java webclient * prefix local varaible with localVar * fix issue with online service (#5461) * Support for additionalProperties in the C generator "Client: C" solves #5395 (#5440) * Support for additionalProperties in the C generator. * Support for additionalProperties in the C generator. * [docs] Enable Algolia search (#5472) * Fix #5420 add headers from configuration object (#5422) * Fix #5420 add headers from configuration object * Add baseOptions undefined checking #5420 * Update the samples and replace array to object #5420 * Update sample * [typescript] Clean up modelPropertyNaming across generators (#5427) * [typescript] Clean up modelPropertyNaming across generators Fixes https://github.com/OpenAPITools/openapi-generator/issues/2976 Generators without runtime models conversion use "original" property naming by default. It's still possible to change it via cli options Generators with runtime conversion keep using "camelCase" * Refactoring: use enum instead of string for modelPropertyNaming * Restore the original camelCase for var names, decouple it from property names * Swap toParamName and toVarName logic (looks like I've mistaken them) * Regenerate docs * Remove a no longer used private method * Added support for msvc builds in cpp-qt5-client generator (#5468) * Added support for msvc builds Moved GCC-specific compile flags to non msvc builds, and added equivalent flags for msvc. * CMakeLists condition cleanup * [all] Move feature set setter (#5460) When I originally implemented the feature set code, I added the getter/setter on DefaultCodegen and CodegenConfig as well as on GeneratorMetadata. GeneratorMetadata also includes the library variation features. When I went to add library-specific features, I realized the discrepancy. This removes the public setter from DefaultCodegen/CodegenConfig, and adds a protected modifyFeatureSet which accepts a lambda and hides the builder logic away in the method. This will be a breaking change for anyone who's created a custom generator in 4.2.3, so the impact is very limited. * [Swift5] small improvements to Objc compatibility (#5410) * [swift] make some small improvements * [swift][client] revert model to use allVars * PostProcessModelProperty with allVars * PostProcessModelProperty with vars * [swift] improve objc interoperability * [swift] fix swift4 for CI to pass * [swift] improve objc interoperability * [swift] improve objc interoperability * Swift - try to fix build * [swift] remove pods from git * [scala] [template] scala sttp client (#5429) * scala-sttp-client template * invoker for sttp fixed and tests added * clean up pet api test from redunant comments * docs updated * fix artefact name, model comments and redunant generic * code optimization * cross scala versions 2.11 2.12 2.13 * date serializers extracted and joda enabled as default * basic and bearer authorization added, apikey in query supported * [Ruby] Fix obsolete configuration of Rubocop and Rubocop's warns (#5417) (#5474) * fix obsolute configuration in generated .rubocop.yml * fix style of `expect` with block in generated ruby client's test code * update sample of ruby client * [scala] strip model class name for all scala generators (#5439) * stripped parameter enabled for all scala based generators * scala samples updated * docs generators updated * fix scalatra. regenerated by openapi3 script. manually removed enum default value from scalatra example due bug in schema extraction * [Scala][sttp] various improvements (#5475) * various improvements to scala sttp * update ScalaSttpClientCodegen.java * add windows batch file * test scala sttp in jdk8 * fix tempalte directory * Use the dataType if the baseType is not set (#5372) * Use the dataType if the baseType is not set * add tests for passing enum as parameter * updated requirements file in samples * Update spec to explicitly name objects and prevent `inline_object` * use the correct scripts to generate samples (`bin/openapi3/python-flask*`) * [python] Adds python oneOf/anyOf models + tests (#5341) * Adds oneOf + anyOf schemas, models and tests to python-experimental * Adds setUpClass and tearDownClass * Removes newline in method_init_shared.mustache * Regenerated v3 spec sample for python-experimental * Fxes test for discard_unknown_keys * Moves new models into existing spec, regen python-exp and go-exp * Also fix python-exp windows file * fix CVE-2020-8130 (#5483) * [go] Add Ptr method to const enum values (#5257) * fix rubocop warns in Ruby client's custom spec (#5488) * [C-libcurl] The name in API parameter should not be escaped even though it includes a C key word. (#5487) * [go-experimental] Support aliasing of API keys (#4940) * [go-experimental] Support aliasing of API keys * Use {{.}} inside condition * Use name instead of keyParamName for lookup * x-lookup to x-auth-id-alias * [java] Support aliasing of API keys (#4966) * [java] Support aliasing of API keys * Rebuild Java Jersey2 sample client * x-lookup to x-auth-id-alias * Regenerated * [cli][gradle] Validate now uses parseOptions w/setResolve (#5471) * [cli] Validate now uses parseOptions w/setResolve The validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [gradle] Validate now uses parseOptions w/setResolve The Graldle validate command now uses ParseOptions#setResolve(true) to match how we parse in CodegenConfigurator and online's Generate. Without this option, the OpenAPI 3 parser skips the "resolve" block, which made lead to validations in the command not matching validations during generation. * [kotlin]Fix ktor doesn't generate nullable types (#5258) * If not required, need `? = null` * run ./bin/kotlin-server-petstore.sh * Added `?` when value is `required` and `isNullable` * Rerun ./bin/kotlin-server-petstore.sh. But No differences * [C++] Add an option to allow having lowercase variables in models, Pistache: allow using reservedWords in models (#5434) * [C++][Pistache] Use reserved words to replace incorrect names discard old decision to truncate reservedWords * [C++][Pistache] Update struct model to use name instead of baseName * [C++][Pistache] Update Petstore sample * [C++] Add option to have lowercase variables * [C++] Update generated docs * [BUG] [JAVA | Spring] Cookie in parameter is not correctly generated (#5393) * Cookie in parameter is not correctly generated * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Update test file * gh-5386: Fix cookie parameter in * gh-5386: Fix cookie parameter in * gh-5386: Regenerate samples * gh-5386: Fix test * Added Spring CookieValue tests Co-authored-by: Gonzalo * Add missing `@Generated` annotation. (#5384) The annotation is present on other generated files when using jaxrs-spec, but it missing on model classes. * [scala] [template] scala model property style (#5486) * Model property naming style generic for scala * scala templates based on abstractScala regererated * docs generators updated * property format tests * add Agoda as the user (#5494) * Hide timestamp in Scala Play server samples (#5495) * hide timestamp in scala play server output * add chameleon82 to scala tech committee * Add a link to tech blog tech.medpeer.co.jp (#5498) * Add links to blog posts about OpenAPI Generator (#5508) * Typescript array alias array (#4981) * Add failing tests for typescript type declaration * Refactor array and map child type string fallback * Add unaliasSchema to typescript getTypeDeclaration * TypeScriptRxjs: Use Blob as file type declaration This was inadvertantly changed in https://github.com/OpenAPITools/openapi-generator/pull/5266 * [core] Sanitize/underscore/camelize cache expiry (#5484) The helper methods for sanitize/underscore/camelize were recently updated to cache values in static maps. This would lead to a memory leak in hosted environments as the maps had no cleanup/expiry. This moves those cached entries to Caffeine caches with expiry based on last access to allow the edge-case performance improvement gains on very large documents, without the memory leak in hosted or embedded environments. * Update README.md * Add a link to the conference paper (#5510) * Add a link to the conference paper * fix author list * [Slim4] Add Data Mocker middleware (#4978) * [Slim4] Store response schemas * [Slim4] Add Data Mocker middleware * [Slim4] Enhance Slim router * [Slim4] Enhance config * [Slim4] Fix data format key in object mocking * [Slim4] Add tests for Data Mocker middleware * [Slim4] Add Mock feature documentation * [Slim4] Refresh samples * [Java][Spring][Spring-Cloud] Fix #5144 - Use conditional package declaration to avoid unnecessary dependencies (#5145) * FIX: Use conditional package declaration to avoid unnecessary dependencies * DEV: Adjusted sample ClientConfiguration.java for async spring-cloud * fix(php): no need to serialize collections, Guzzle does that, fix #2292 (#3984) * fix(php): only serialize collections if !explode, Guzzle handles the rest, fix #2292 * fix(php): update petstore samples Co-authored-by: Mahdi Dibaiee * [php] replace $collectionFormat with $style (#5517) * php - remove $collectionFormat * update php openapi3 petstore sample * [BUG][scala][template] scala generate java.math.BigDecimal instead of scala type (#5514) * [BUG] scala generate java.math.BigDecimal instead of scala type * update docs/generators * [PHP] complete support for form style (#5519) * [BUG][PHP] Parameter property style not fully implemented (related to comment on PR #3984) * [AUTOGENERATED][PHP] Sample Files * update jackson dependency to newer version (#5527) * Fix Swift4 CI tests (#5540) * comment out swift 4 order tests * comment out store tests * Test Dart petstore client in CircleCI (#5544) * test dart2 in circle ci (jdk7) * fix tests * update package * fix dart installation * Add serialization of ModelComposed (#5551) * Fixes kwargs typos, removes E501s (#5552) * Update generic model to support nullable properties (#5568) * [DOC] Add link to integration test wiki in CONTRIBUTING.md (#5570) * Add link to integration test wiki * Add link to integration test wiki * [Kotlin][client] fix file upload (#5548) * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin] fix file upload * [kotlin][client] fix jackson integration * [kotlin] fix file upload * [kotlin] fix file upload * update doc * [Java] Fix exception when OAuth2 token URL is a relative URL (#5535) * Add support for case when OAuth2 token URL is a relative URL * Add support for case when OAuth2 token URL is a relative URL * run scripts under bin * [Java] fix runtime exception when there are multiple auth methods (#5530) * fix runtime exception when there are multiple auth methods * Refactor a bit so that it does not cause conflict with relative url token branch * [markdown] Fix broken links when generating markdown (#5569) * [markdown] Fix broken links when generating markdown The `api.mustache` file generates links to the markdown model files. These links were previously brokeen. Additionally, the defaultPackage for markdown is "/Models", so this looked pretty in the heading for model files. So this prefix has been stripped from the header in `model.mustache`. * Re-generate Petstore samples for markdown * typescript-angular: fix zone-js version for angular 8 (#5585) * Add a link to the slide (#5590) * [Swift] fix URLSession file upload (#5546) * [swift5] - fix URLSession file upload * [swift5] - fix URLSession file upload * [swift5] fix file upload * [swift5] - fix URLSession file upload * [swift] add unit tests for file upload * [swift] update samples copyright * [swift] add option for API prefix (#5567) * [swift] add option for API prefix * [swift] update docs * [haskell-http-client] update stack; exclude problem time versions (#5589) * [go-experimental] Do not generate HTTP signature unit test for every generated SDK (#5588) * Do not generate HTTP signature unit test for every generated SDK * Add golang 1.14 to CI environment * fix unit test issues * remove script commands that were commented out * add support for ed25519 private keys * PR to solve 2 open issues on enums: #5091 and #4293 (#5477) * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * PR to solve 2 open issues on enums: Issue 5091 needs to generate enums also when the enum is directly in a param to a API call, instead than in a model. I did that by copying and adapting enum code from *model* to *api* Issue 4293 needs to decorate enums, for when enum names or enum values are repeated over the yaml definition. * Enums decorated: with {{projectName}}_{{classVarName}}_{{enumName}}_ in the models, with {{projectName}}_{{classVarName}}_{{enumName}}_ in the operations. * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Changes to the c client: - Removed white space. - Removed ToJSON and FromJSON function for the enums, since they are not used - Sanitized project name in the .java file. For example, this solves a problem with the issue #2338, where the yaml file had title: "Skycoin REST API." * Adds parseFlattenSpec (#5526) * Adds parseFlattenSpec, updates tests and helper functions * Adds parseSPec invocation inside parseFlattenSpec * Scala-Akka: Add missing body to PATCH requests (#5605) * NodeJS - Adds missing keyword (#5606) * [jaxrs-cxf-cdi] Support PATCH httpMethod (#5574) Update the required CXF version to 3.1.2 since PATCH support appeared with this version. Add the cxf PATCH annotation to the imports so that the generated code when defining a PATCH api compiles. * fix default value for abstract scala and scalatra server impl (#5578) * [Java] Generated API class has wrong dataType and does not compile Issue (#5331) * add unit test assertion * add check for composed schema * add support for x-allOf-name * change x-allOf-name to x-all-of-name * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * Add more troubleshooting information * [swift5] stop hiding network error (#5603) * [swift5] stop hiding network error * [swift5] stop hiding network error * [scala][templates] java 8 dates support (#5291) * [scala][akka-http-client] java8 dates support * scala-akka readme doc updated * DateSerializers renamed * rename serializers * move date-library option to abstractScala * generators docs updated * enum defined for date libraries * Backport to scala-http-client * fix scala-akka-client date serializers * fix typo in docs * switch scala templates to java8 (jsr-310) date library by default * update scala samples with java8 date library * update scala generators docs with java8 default date library * fix scala-play-server generator cli options as only java8 dateLibrary supported * fix scalaz DateTimeCodecs template to support java8 * scalaz ci test againt java7 removed as it generate scala 2.11.8 client which is java8 based * update doc * Adding Response Interceptor (#5500) * added Response interceptor for native clients * added Response interceptor for native clients * [k6] Add blog post about using the k6 generator (#5608) * [Kotlin] Remove kotlin-reflect dependency when not needed (#5502) * Remove kotlin-reflect dependency when using CodeGen * Update Kotlin tests * Regenerated unit test samples * Remove newline in generated build.gradle files * [typescript-fetch] add interfaces, withInterfaces (#5612) * typescript-fetch: interfaces, first draft * fix name in description * [scala] Regenerate akka sample (#5622) * scala-version 2.11.12 (#5618) * micheleISEP->michelealbano (#5625) * [Powershell] refactor the client generator (#5629) * add api client * add local variables * add configuration * add header/query/form parameter support * add partial header * add auth, fix parameters type * fix accept, content type * url query string * fix path, header * remove dep on C# client * fix method naming with package name * fix object * convert result from json * better response handling * remove tostring method * fix model doc * fix default module * generate api test files * better api, model tests * fix add pet * add appveyor * fix accept, content type * add petstore tests * fix form parameters * test delete * better file handling (upload) * better code sample * add package version, better doc * delete unused files * fix header parameters * clean up api client * update samples * support query parameter * better method and parameter naming * minor formatting change * better doc, fix cookie parameter * better doc * add api prefix support * better api nam prefix option * fix configuration * throw errors for required parameter * fix authentication * add try catch block to sample code * rename model * use debug, clean up comment * revise code * move bin script * update doc * add new file * better map support * [PowerShell] minor improvements and bug fixes (#5635) * add output type, minor format fix * minor test improvement * Port client updates to server (#5634) * Revert "scala-version 2.11.12 (#5618)" This reverts commit 6b984a926a0f99120a4ad80cef73bee19f8614cd. * update release date * Handle negative response from the server (#5649) * Fix integration tests (Travis, CircleCI) (#5672) * fix php tests * fix scala tests * update ts angular v6 rest * fix user create test * fix spring cloud test * comment out user delete * fix angular v7 tests * fix user test * fix tests * fix go exp tests * commented out delete user tests * comment out delete user tests in go openapi 3 * fix clojure tests * [PowerShell] Fixes typo (#5648) * Solving issue #5623 and supporting bools for C client label:"Client: C" (#5624) * Removed stray "printf"s in modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/CLibcurlClientCodegen.java * Support for booleans in C client * Update README.md * Change to C API mustache files to solve issue #5623 * Debugging of C's modle-body.mustache, as suggested by ityuhui * Final changes suggested by ityuhui * [PowerShell] Fix map type (#5638) * fix map type * remove output type, fix appveyor * test macos * comment out failing scala test * fix typo: configuration * Revert "comment out failing scala test" This reverts commit 1dcf84ffcbb7ab520938ae7c75d60a8329f71478. * [powershell-experimental] Protects against stackoverflow when OAS spec has circular references (#5646) * protects against stackoverflow when OAS spec has circular references * protects against stackoverflow when OAS spec has circular references * Adds configuration option to skip certificate check. Fixes a typo. Fixes an issue which was restricting from cookie to get consumed (#5657) * [k6] bugfixes to improve the output script (#5614) * [k6] Skip appDescription escaping * [k6] Fix variable identifier in output * [k6] Fix bug with reserved words handling * [C][Client] Check the pointer before deleting operation to avoid core dump label:"Client C" (#5626) * [C-libcurl] Check the pointer before deleting operation to avoid core dump * [C-libcurl] Check the pointer before deleting operation, update sample * [kotlin][client] Add Jackson to interface properties and remove extra line feed (#5459) * [kotlin][client] Ensure Jackson annotations are consistent with interface vars * [kotlin][client] Rebuild samples * [kotlin][client] Some kotlin client enhancements - Don't use JsonFormat for Date objects, this should be controlled via a custom serializer/deserializer or a turning on and off serialization features of Jackson. I've updated the jacksonObjectMapper config to write the dates as strings, which I think was intended in the original commit. https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/SerializationFeature.html#WRITE_DATES_AS_TIMESTAMPS https://fasterxml.github.io/jackson-databind/javadoc/2.6/com/fasterxml/jackson/databind/cfg/MapperConfig.html#getDateFormat-- - Dont' use @JsonFormat(shape = JsonFormat.Shape.OBJECT) for enums. This causes Enums to be formatted as objects with an internal "value" field. In reality, OpenAPI enums are just strings without properties and should be treated as a string. https://www.baeldung.com/jackson-serialize-enums#2-enum-as-json-object - Add's Kotlin use site annotation @get: to JsonProperty for parent interface properties. Otherwise Kotlin will warn: "This annotation is not applicable to target 'member property without backing field or delegate'" - Add's JsonTypeInfo annotations to interfaces for inheritance. This was copied verbatim from the kotlin-spring generator. https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/kotlin-spring/typeInfoAnnotation.mustache * [kotlin][client] Rebuild kotlin samples * Remove scala version in parent pom (#5647) * [asciidoc] Allow the inclusion of additional documentation to t… (#5260) * [asccidoc] Allow the inclusion of additional documentation to the asccidoc generated Resolves #5228 * [jaxrs-reasteasy-eap] Fix invalid Bean Validation annotations for Longs (#5659) * fix issue #5658 * update samples * [PowerShell] Test powershell petstore client in Appveyor (#5674) * remove scala version in parent pom * test ps petstore in appveyor * fix command * build and import * fix import module * fix import * skip module import * run multiple commands * move to test script * test ps exit * fix exit * check last status code * clean tests * exit last code * add import * change dir * skip build failure * fix check * trigger build failure * fail fast * restore c# test * new line comment * add powershell exp to ensure up to date script * [PowerShell][Experimental] Better docstring (#5688) * add docstring to powershell module * add doc string * Nodejs express js packages update (#5675) * Updated to new nodejs packages, depending heavily on express-openapi-validator. Requires quite a change in code. Updated the business-logic in the controllers/Controller.js file. Logger now records also timestamp of events. Files are uploaded according to definition in config.js file * Removed commented-out code; Changed openApi document extensions to suit new express-openapi-validator definition; multipart and file uploading is supported now; Automatic response returns the values the were sent in the request * fixed README documentation, fixed a mistage in package.json/mustache * added generated files that were created when running the ./bin/test file * [go-experimental] Fix nullable support (#5414) * Fix nullable support in go-experimental client * Fix support for models with parents and container fields * Make sure that oneOf interfaces serialize properly even if they're required (non-pointers) on other models * Spaces => tabs * Regenerate samples * Make some methods of nullables pointer-receivers, add tests * Improve the Get/Set logic to make usage more convenient * Address review * [kotlin][client] make base path globally configurable (#5450) * [kotlin][client] make base path configurable * [kotlin][client] update pet project * [kotlin][client] set default base path * [kotlin][client] set default base path * [kotlin][client] set default base path * Add michelealbano to C technical committee (#5692) * [Go][Experimental] Rename extensions from x-basetype to x-go-base-type (#5691) * rename go vendor extension * update go exp petstore samples oas3 * comment out powershell petstore in uptodate script * remove processing of http_signature_test.mustache (#5696) * Fix generation of oneOf interfaces for oneOf usage in properties (#5400) * Fix generation of oneOf interfaces for oneOf usage in properties * Only generate oneOf interface models when oneOf is defined * use basic parsing (#5702) * [python/asyncio] explicitly close client session via async context manager (#5621) * [gradle] Include engine option for handlebars generation (#5686) * [codegen][Go] Fix compilation error of generated go code when schema is free form object (#5391) * Fix code generation for free-form objects in go-experimental * Execute scripts in bin directory * Add more use cases for open-ended types * Add more use cases for open-ended types * Add more use cases for open-ended types * add code comments * Better name for test properties * handle scenario when type is arbitrary * handle interface{} scenario * handle interface{} scenario * add helper function isAnyType * isAnyType function * implementation of isAnyType function * fix javadoc issue * handle interface{} scenario * use equals comparison instead of == * merge from master * Add code documentation * add code comments, remove unused min/max attribute, fix equals method * Handle 'anytype' use case * add code comments * override postProcessModelProperty to set vendor extension * Use vendorExtensions.x-golang-is-container * fix compilation error of generated code * fix compilation error of generated code * fix compilation error of generated code * [Java] Update version of maven-surefire-plugin (#5509) * use more recent version of maven-surefire-plugin * use more recent version of maven-surefire-plugin * higher debug level for troubleshooting ci issue * temporarily increase debug log to help troubleshoot * Use local instance of pet store service for unit test purpose * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * Add more logging to troubleshoot unit test failures * use random ID for Java unit test instead of fixed id * add code comments and specify URL for java unit test * reenable quiet argument * fix java unit test issues * fix java unit test issues * Revert "fix java unit test issues" This reverts commit e8508416ff0f2aeb568e3f916b013dc967390f74. * fix java unit test issues * Generator for JavaScript/Apollo Client (#5645) Co-authored-by: William Cheng * Add yutaka0m to Kotlin Technical Committee (#5716) * Add Scala client scripts to ensure-uptodate process (#5712) * add scala client to ensure-upto-date * new scala-akka petstore oas3 folder * regenerate scala akka oas2 petstore * remove script * Minor improvments to JS apollo generator (#5714) * minor improvments to js apollo generator * comment out apollo * [Rust Server] Handle text/xml correctly (#5660) * [Rust Server] Handle text/xml correctly Treat application/xml the same as text/xml as per RFC 7303 * [Rust Server] Add test for text/xml * Update samples * 4.3.0 release (#5721) * update samples (#5722) * 5211 - Use allVars instead of vars for Kotlin client (#5396) * [C++] [Qt5] fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout... (#5651) * - fixed cpp-client-qt5 HttpRequestWorker requests crashing on timeout when they have actually NOT timed out (were calling back into a deleted struct). * #minor fixes after review * Regenerate changed files Co-authored-by: valentin Bisson Co-authored-by: etherealjoy * Fix SSL setting in checkout script (#5725) * fix ssl setting in checkout script * add check for sbt-openapi-generator * [C] fix decode funtion (#5642) * fix function names and add parameter to return decoded bytes length from base64decode function * format base64decode function to avoid unnecessary malloc and fix wrong length assigning * update the pointer assigning for some reason var++ / *var++ cannot be done on int *var, hence making a local variable which is incremented and at the end it is assigned to the pointer. * Update bump.sh to go SNAPSHOT to version (#5727) * Fix CI failures (#5734) * update ci to use petstore 1.0.4 * comment out test * comment out test * comment out update user test * comment out more tests * use latest petstore * comment out updatePetWithForm * comment out update pet test * fix file path in release_version_update_docs (#5724) * better appveyor test (#5739) * better readme, type mapping, new option (#5740) * Remove warning for unused camel case vendor extension for Qt5 client and server (#5731) * [PS][Experimental] Add multiple server support (#5741) * code comment * add get host setting * add multiple server support * add default headers support (#5746) * [C][Client] Support SSL client authentication for the c client (#5719) * [C][Client] Support SSL client authentication * [C][Client] Support SSL client authentication, update sample * [kotlin] Fix #5247 incorrect enum parameter type for arrays (#5435) * [Erlang-Server] security definition context changes don't propagate to handler (#5751) * Map Merge Context & Params handler requires context and params to be merged before returned to user defined request_handler. * post build & shell script * Delete VERSION * [PS][PowerShell] fix passthru, use switch instead of bool (#5768) * fix passthru, use switch * remove line * comment out kotlin vertx server test (#5767) * add support for common verbs (#5771) * fix request.on_complete message when tempfile is nil (#5745) * fix request.on_complete message when tempfile is nil * update faraday client sample * add openapi3 client samples * use prepare instead of new (#5773) * use Initialize instead of prepare (#5777) * add map example (#5778) * [PS][Experimental] Better common verb handling (#5783) * better common verb handling * better debugging * add option to customize common verb * [cli][docker] Better expose version/sha information of builds (#5736) * [cli] Some CLI improvements… * Introduce --version * Introduce --help * Add --sha to version command for short SHA display * Output Version and SHA details * In new --version output, display repo and doc site Additional cleanup to suppress warnings and code quality. * [docker] Adds labels for metadata This adds image labels to store metadata on the online and cli docker images, using standard labels: * org.opencontainers.image.created * org.opencontainers.image.revision * org.opencontainers.image.title * org.opencontainers.image.version These can be inspected via 'docker inspect IMAGE_NAME' and may be useful in tooling/automation or bug reports submitted by users. For more details on these labels, see: https://github.com/opencontainers/image-spec/blob/master/annotations.md * Include version --full for equiv to --version * [cli] Add --global-property for -D replacement (#5687) -D option has been deprecated as it was previously used to: * Pass "system properties" * Pass additional properties This was confusing because we already have --additional-properties and because Java System Properties are passed as -D before program arguments. Confusion around the -D option had existed for some time, but when we introduced the thread-safe GlobalSettings to avoid overwriting Java System Properties, we created a hard break from Java System Properties in the generator. This also disconnected the previous "system properties" from accepting additional properties. Once these newly deprecated methods are removed, we will have a clear separation of concerns between: * Java System Properties * Global generator properties (used as workflow context) * Additional properties (used as generator options) This commit marks multiple places for cleanup in 5.0. These will be breaking changes, and lower effort to break in 5.0 with deprecation warnings now rather than adding sibling properties throughout the code and potentially introducing logic errors. * [dart-dio] Fixes --model-name-suffix having no effect (#5669) Fixes #5409 * [go-experimental][go][client] Remove unreachable code in go client API methods (#5611) * [go-experimental][go][client] Remove unreachable code in go client API methods * Properly regenerate all samples * please add openVALIDATION Project to readme (#5534) * added openVALIDATION Project to readme * Update README.md Co-Authored-By: Akihito Nakano Co-authored-by: Akihito Nakano * [Csharp-client] Complex form parameters are not serialized as application/json (#5787) * [csharp-client] Complex form parameters are now correctly serialized as json. Reference: http://spec.openapis.org/oas/v3.0.3#special-considerations-for-multipart-content * Updated bin/windows csharp sample generation scripts to point to the correct directories * Updated csharp samples Co-authored-by: Olivier Leonard * fix scala-akka java8 serializers (#5742) * fix scala-akka java8 serializers * regenerate samples for akka-http * [typescript-axios][client] Unnecessary imports occurs when using withSeparateModelsAndApi (#5797) * add ts-ignore * add petstore sample * use write verbose in auth, better api doc (#5804) * [PS][Experimental] add withHttpInfo support, fix "null" return (#5811) * add with http support * use full name in tests * using full name in test * skip type check * [PS][Experimental] Add tests for array of object in response (#5814) * debugging array response * fix find pet tests * better tests to ignore order * [codegen] Use once(LOGGER) to reduce amount of identical warning messages (#5808) * Warn once instead of many times when the log statement does not have contextual information * Warn once instead of many times when the log statement does not have contextual information * make name cache configurabl (#5775) * [codegen] Cachesize config seconds (#5816) * make name cache configurable * Address review comments * [Python-experimental] Documentation enhancement for oneOf schema and minor err msg improvement (#5791) * Add documentation to generated code * Improve error message * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Improve documentation * Run sample scripts * Address review comments * Address review comments * Fix problem in python error message * rename hostsetting, validate base url (#5821) * fix array return (#5822) * Scala akka-http server (#5758) * Scala akka-http server base implementation * [scala-akka-http-server] petStore samples * Improved the formatting of generated files * Updated scala-akka-http server samples * [scala-akka-http-server] the groupId, artifactId and artifactVersion default value are used as intended. * Fixed the default operation not being correctly generated on parameterless operations * Added build.sbt.mustache supporting file * Updated scala-akka-http server samples * ScalaAkkaHttpServer: Fixed a String.format call to use Locale.ROOT for locale * [scala-akka-http-server] Fixed defaultValue being escaped during generation * Added scala-akka-http.md * Replaced all "⇒" character with "=>" to retain compatibility with scala 2.13 * [scala-akka-http] Added a config option akkaHttpVersion It's set in the generated build.sbt. * Updated scala-akka-http server samples * [scala-akka-http] More accurate akkaHttpVersion parsing * Updated scala-akka-http.md * [scala-akka-http] Changed the akka-http version check to fix the generation of StringDirectives * Updated scala-akka-http samples * updated scala-akka-http.md Co-authored-by: Olivier Leonard * Minor improvements to scala akka server (#5823) * minor improvements to scala akka server * add samples * update doc * Update swagger parser to 2.0.19 (#5413) * update swagger parser to 2.0.18 * fix online server exception * Revert "fix online server exception" This reverts commit fe3cb5221f362c00b176fa81411eaf368f0e446d. * update parser to 2.0.19 * [jaxrs-cxf-cdi] fix allOf equals and hashCode (#5756) When generating model that use allOf, the equals and hashCode methods must take the parent class into account. * [BUG] [KOTLIN] Fix default value generation for Kotlin Strings (#5776) * fix default value generation for kotlin * add updated pet templates * Revert "add updated pet templates" This reverts commit 7e8168ad * regen pet store projects code * tests for models for C-libcurl generator (#5699) * First try to generate unit tests for the models of the C-libcurl client. Models into models are not supported yet. * Added unit tests for the modules of the C-libcurl client to the git repository. * Support for objects having other objects as properties, for the C-libcurl client generator * Proper formatting of generated code * use allVars to cover all properties (#5835) * support enum in parameters (#5838) * [C++] [Qt5] [Client] fixed cpp-client-qt5 HttpRequestWorker contentCompression variables initialization (#5834) When contentCompression is not enabled, the variables isRequestCompressionEnabled and isResponseCompressionEnabled in HttpRequestWorker are not being initialized. Without initialization the compress function could be called and the request content could be an empty QByteArray instead of original request body. * minor fix to http basic auth (#5839) * Scala akka http server - normalization of some vendor extensions (#5829) * [scala-akka-http-server] Normalized vendor extension "paths" to "x-paths" * [scala-akka-http-server] Normalized vendor extension "hasDefaultValue", "isDefault", "specificMarshallers", "fileParams", "nonFileParams" Co-authored-by: Olivier Leonard * Add Bouill to the Scala technical committee (#5843) * C client generator improvements to support petstore. Solves #5836 (#5837) * C client generator improvement to support: openapi-generator/modules/openapi-generator/src/test/resources/3_0/petstore.yaml * Improvements to the C client generator: - moved base64* from apiClient.c to binary.h/binary.c - changed CR/LF to LF in binary.h/binary.c * C client generator: better support for base64encode / base64decode * Add openapi.yaml file to Java clients (#5765) * Add openapi.yaml file to Java client * Move supporting template file to Java root * Update petstore clients * [codegen] Fix 'super.HashCode' for oneOf and allOf Implementations (retry) (#5830) * Added hasVars after completion of all model post-processing (#5587) * Post ensure-up-to-date * Update to check the size of vars and not assume non-null * update mysql samples * Add default case to handle response code (#5825) * add default case to handle response code * fix default response code * add test for isDefault * fix user id in scala tc * Fix for Issue #4840 [BUG][JAVA][spring-mvc] Generated Code for Map of Maps Return Type does not compile (#5240) * add parent for allOf only (#5851) * Add pythonSrcRoot option to python servers (aiohttp/flask/blueplanet) to support src/ layout projects [and reenable/fix all python server tests] (#5423) * python server: Add pythonSrcRoot option This will allow the python project to be in a subdirectory (as specified in pythonSrcRoot). That could mean following the src layout with sources under src/ or lib/. Multi-language projects might use a sub directory like python/, or whatever makes sense for the project. By default, the pythonSrcRoot is "", meaning the existing behavior is the default. * python server: update template files to support pythonSrcRoot * python server: update docs to add pythonSrcRoot option * python server: add pythonSrcRoot sample script * python server: build sample srclayout project * [Python] copy test files preserving history * [Python] Make a conflict to preserve file copy history * [Python] customize pom.xml for src layout tests * [Python] add python-aiohttp-srclayout tests * [Python] Fix server tests by updating requirements Reverts the PR that disabled python2 server tests: https://github.com/OpenAPITools/openapi-generator/pull/4949 Reverts commits that disabled python3 server tests: 9adfedbfbb45c7059e64b3d9a285710bded4fb62 17ee990baaa80585242c7a07d64e2be4888fcfd0 Issue about the python 3 tests: https://github.com/OpenAPITools/openapi-generator/issues/5235 I couldn't find an issue about the python2 tests being disabled. I'm guessing build errors like the following were the trigger: https://travis-ci.org/github/OpenAPITools/openapi-generator/builds/634238181 Let's see what breaks! * [Python] Copy setup.py to python-aiohttp * [Python] Save history while copying setup.py to python-aiohttp * [Python] Add aiohttp server setup.py * [Python] Fix python server tests with src layout * [Python] bump Flask-Testing version * [Python] Pin pyyaml for py2.7 flask server * [Python] simplify flask server requirements * consolidate server tests * [Python] rebuild python server samples * [Python] Fix python server requirements for older pythons Documented minimum python version for our aiohttp server is 3.5. Documented minimum python version for our flask server is 3.4. Connexion 2.3 is the last version to support python 3.4 and 3.5, so fix the version pinning to correctly select <=2.3 for these EOL python versions. Newer pythons should get the latest if possible as there many relevant bug fixes. Werkzeug also needs to be pinned for these old versions in the aiohttp server just like for the flask server. 3.4 and 3.5 are EOL. We really should increase the minimum supported version, but that is for another PR to do. * stop error globally (#5858) * [PS][Experimental] Add validations to model (#5842) * add validations to model * better error message * improve validation * Updates to allow the setting of the dateTime format string (#5763) * [PS] Select Content-Type in the response (#5872) * better return type handling * update tempalte * better documentation * fix greater than * various enhancement to ps exp generator (#5875) * [C#] dependency upgrade (#5870) * Updating packages version (#5313) * Add support to RestSharp version 106.10.1 Restsharp 106.10.1 needs the Content Lenght as a parameter to AddFile method * Updating RestSharp Version Updating RestSharp Version * Update netcore_project.mustache * Update netcore_testproject.mustache * Update Project.mustache * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Updating packages version Updating packages version * Execute task async obsolete Use ExecuteAsync instead * update csharp samples Co-authored-by: William Cheng * [csharp] Library upgrade fix (#5848) * On .net45 framework, Restsharp version is updated to 106.10.1 Otherwise, it stays on version 105.1.0 * Added additionalProperties for library versions and target frameworks * Removed unused properties * Added an additional property to test for a specific version of RestSharp * Updated csharp samples * Fixed nuspec.mustache to use library specific additional properties * Updated csharp samples * Updating CI/samples.ci csharp petstore test project file. * Updated csharp.md Co-authored-by: Olivier Leonard * [csharp-client] Restored tests on csharp samples (#5879) * Restored tests on csharp samples * Restored a reference to the file used to test file uploads Co-authored-by: Olivier Leonard * update samples Co-authored-by: Igor Quirino Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard * [Csharp-client] Complex form parameters are not serialized as application/json (#5849) * [csharp-client] Complex form parameters are now correctly serialized as json. * Updated csharp samples Co-authored-by: Olivier Leonard * docs: removes Nico from technical committee (#5883) * [PS] better handle special variables (#5885) * add variable * fix reserved words * update ps doc * [PS] add file post-processing to the PowerShell generator (#5864) * add post process to ps generator * add import * fix merge issue * consolidate header selection functions (#5889) * [Java-client] Add maven-compiler-plugin in pom.xml and enable linter checks by default (#5866) * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Add maven-compiler-plugin plugin in Java pom.xml and enable linter checks by default * Update enum.mustache (#5793) https://github.com/OpenAPITools/openapi-generator/issues/5792 * Update modelGeneric.mustache (#5378) * Update modelGeneric.mustache If maxlength is specified for a property type enum it there should be .ToString() appended before length check * ran the csharp petstore bar and updated the file Co-authored-by: Shweta Shukla * Fix Scala sttp generator packages (#5890) * Fix Scala sttp generator packages * Change package to parameterised * [Dart] Fix "basic" auth method and Add Bearer token support (#5743) * added auth check and lint * fixed basic auth condition * Added bearer auth * updated samples * update dart petstore samples Co-authored-by: William Cheng * Add date time format annotation on pojo for model query parameters (#5437) * Add date time format annotation on pojo for model query parameters * Regenetare samples * update spring samples Co-authored-by: William Cheng * [mysql] Add basic SQL queries (#5757) * Add basic SQL queries template * Add namedParametersEnabled option * Move model related SQLs into Model folder * Update README template * Refresh samples * [enhancement] [jaxrs-spec] Add builders to models (#4930) * Update formatting in jaxrs-spec POJOs * Add generateBuilders option * Update formatting in jaxrs-spec POJOs * Disable the builders generation by default * Ensure samples are up-to-date * Revert newline change * Run ensure-up-to-date * update doc * fix merge conflicts Co-authored-by: Artem Shubovych Co-authored-by: William Cheng * Update generated build files for REST Assured (#5873) * REST Assured 4.3.0 * Jackson 2.10.3 * Gson 2.8.6, GSON-Fire 1.8.4 * Okio 1.17.5 * Joda-Time 2.10.5 * ThreeTenBP 1.4.3 * Added missing dependencies for Bean Validation * Added missing dependencies for `@Generated` annotation * Refresh REST Assured sample project * [Java][Feign] Bug fix in @Param annotation (#5250) * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. * update samples * FIX-5249 fix @Param annotation for Feign-client code generation Use paramName instead of baseName in order to make mapping in @Headers section fit the param-value. Co-authored-by: Christoph Preißner Co-authored-by: William Cheng * [Java] Increase java compiler stack size to handle large files (#5901) * increase java compiler stack size to handle large files * increase java compiler stack size to handle large files * Added emineo to list of companies on website (#5905) * add emineo to the list * [swift5] fix warning (#5900) * update bitwise config (#5904) * [Java] Discriminator lookup should not be case insensitive by default (#5894) * Add 'discriminatorCaseSensitive' property * Discriminator value lookup should not be case insensitive * fix typo * run scripts * execute ./bin/utils/export_docs_generators.sh * fix discriminator mapping, add code comments * minor fix to users.yml * Add a link to optim blog post (#5922) * [Java] Fix inclusive max validation (#5908) Co-authored-by: erikmolin * add bearer auth support to csharp netcore (#5921) * [Python][aiohttp] create venv as rule (#5913) * create venv as rule * create venv as rule II * Fix for Result Model Name collision (#5923) * Fix for Result Model Name collision * Run Scripts Co-authored-by: Sebastian Ohm * [Dart] Remove content type from header when content type is not specified (#5752) * accept empty content type * fixed test * updated samples * additional comment out * update dependency for java client (#5926) * Update axios dependency to the new minor version 0.19.0 (#5867) * Update axios dependency to 0.19.0 Axios (version 0.18.0) used by typescript-axios generator is more than two years old (released in Feb 2018). Axios 0.19.2 released earlier this year contains a lot of fixes and functionality, I recommend updating to 0.19.2. * Ran ./bin/typescript-axios-petstore-all.sh to update package.json in ./samples Co-authored-by: Chandra Yalangi * fixed README/doc of bearer auth support for csharp-netcore (#5931) * fix duplicated semi-colon in c# model (#5934) * [Python-experimental] Use DER encoding for ECDSA signatures, add parameter to configure hash algorithm (#5924) * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * Use DER encoding for ECDSA signatures * fix python unit tests for http message signature * Fix error message * format python code * format python code * [Python-experimental] Fix TypeError: unhashable type: 'list' (#5810) * handle scenario when value is a list, fix TypeError: unhashable type: 'list' * Add __hash__ function * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * use list instead of set * [python/asyncio] fix passing proxy parameters to aiohttp (#5943) * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (#5828) * [C][Client]Fix the defect of data lost when libcurl write-data callback function (configured by CURLOPT_WRITEFUNCTION) is called multiple times. * [C][Client]Fix data lost when libcurl write-data callback function is called multiple times (Reset count) * [typescript-axios][client] Allow apiKey type Promise. (#5953) * change apiKey type * recreate sample * Add YITU Technology to the user list (#5967) * add yitu to the user list * use yitu technology * Use model as body param for generateAliasAsModel (#4569) * generateAliasAsModel: Use model name as body param * Update samples * resolve merge conflicts in the core generator files * fix merge conflicts in pom.xml * Resolve Elm merge conflicts * [Rust Server] Fix up merge conflicts * Update samples * [Rust Server] Add debug log for rust-server-petstore.sh * update samples * update more samples * fix dart openapi-generator version * remove deprecated c# files * update meta codegen * fix port in pom.xml * fix port in sample * update jaxrs cxf version Co-authored-by: sunn <33183834+etherealjoy@users.noreply.github.com> Co-authored-by: dwlabcube <46682038+dwlabcube@users.noreply.github.com> Co-authored-by: Herve DARRITCHON Co-authored-by: Akihito Nakano Co-authored-by: Johnny Peck Co-authored-by: Michele Albano Co-authored-by: Jim Schubert Co-authored-by: Nikita Co-authored-by: Alexey Makhrov Co-authored-by: val Co-authored-by: Bruno Coelho <4brunu@users.noreply.github.com> Co-authored-by: Aleksandr Nekrasov Co-authored-by: Akira Tanimura Co-authored-by: Justin Co-authored-by: Justin Black Co-authored-by: Jiri Kuncar Co-authored-by: Hui Yu Co-authored-by: Yutaka Miyamae <48900426+yutaka0m@users.noreply.github.com> Co-authored-by: Mateusz Szychowski (Muttley) Co-authored-by: Jorge Rodriguez Co-authored-by: Gonzalo Co-authored-by: ChristianCiach Co-authored-by: Bodo Graumann Co-authored-by: Yuriy Belenko Co-authored-by: Daniel Klessing Co-authored-by: copypasta-g <53397163+copypasta-g@users.noreply.github.com> Co-authored-by: Mahdi Dibaiee Co-authored-by: Sebastien Rosset Co-authored-by: siada Co-authored-by: Samuel Hoffstaetter Co-authored-by: Esteban Gehring Co-authored-by: Jon Schoning Co-authored-by: Marcin Kubala Co-authored-by: anoohya-n <51289018+anoohya-n@users.noreply.github.com> Co-authored-by: Antoine Reilles Co-authored-by: Clemens Angermann Co-authored-by: Mostafa Moradian Co-authored-by: Adam Co-authored-by: Lars Hvam Co-authored-by: sullis Co-authored-by: Vikrant Balyan Co-authored-by: Matt Traynham Co-authored-by: LEZIER-S2 <60382243+LEZIER-S2@users.noreply.github.com> Co-authored-by: Thomas Enderle Co-authored-by: YishTish Co-authored-by: Slavek Kabrda Co-authored-by: Tomasz Prus Co-authored-by: Erica Kastner Co-authored-by: Richard Whitehouse Co-authored-by: valentin Bisson Co-authored-by: etherealjoy Co-authored-by: Hemant Zope <42613258+zhemant@users.noreply.github.com> Co-authored-by: Even André Fiskvik Co-authored-by: ehansen31 Co-authored-by: Timur Platonov Co-authored-by: Josh Burton Co-authored-by: Ilja leyberman <7ilya@gmx.de> Co-authored-by: Bouillie <34162532+Bouillie@users.noreply.github.com> Co-authored-by: Olivier Leonard Co-authored-by: tanmen Co-authored-by: Alex Buchkovsky Co-authored-by: Natan Laverde Co-authored-by: Nicholas Muesch Co-authored-by: jburgess <11861789+jburgess@users.noreply.github.com> Co-authored-by: emileonhardt <40421857+emileonhardt@users.noreply.github.com> Co-authored-by: Jacob Floyd Co-authored-by: Igor Quirino Co-authored-by: Nico König Co-authored-by: https://gitlab.com/selankon Co-authored-by: Shweta Shukla <25539662+shwetashukla@users.noreply.github.com> Co-authored-by: Shweta Shukla Co-authored-by: Bartek Kowalik Co-authored-by: Shinya Sugmoto <34866626+gasugesu@users.noreply.github.com> Co-authored-by: Artem Shubovych Co-authored-by: Artem Shubovych Co-authored-by: Jochen Schalanda Co-authored-by: Chr1st0ph Co-authored-by: Christoph Preißner Co-authored-by: Erikmolin Co-authored-by: erikmolin Co-authored-by: Nicolas Homble Co-authored-by: Sebastian <63457660+sebohdev@users.noreply.github.com> Co-authored-by: Sebastian Ohm Co-authored-by: chandra-gh <63366477+chandra-gh@users.noreply.github.com> Co-authored-by: Chandra Yalangi Co-authored-by: Fabian Freund Co-authored-by: Erik Timmers --- api.mustache | 36 +++-- api_client.mustache | 16 ++- api_doc_example.mustache | 11 +- asyncio/rest.mustache | 25 ++-- configuration.mustache | 55 ++++++++ gitlab-ci.mustache | 38 ++++++ python-experimental/api_client.mustache | 3 +- python-experimental/api_doc_example.mustache | 11 +- python-experimental/model.mustache | 1 + .../method_init_composed.mustache | 27 ++-- .../method_init_normal.mustache | 12 +- .../method_init_shared.mustache | 36 +++-- .../methods_setattr_getattr_composed.mustache | 30 +++-- python-experimental/model_utils.mustache | 123 +++++++++++++----- python-experimental/requirements.mustache | 1 + python-experimental/setup.mustache | 1 + python-experimental/signing.mustache | 68 +++++++--- python_doc_auth_partial.mustache | 3 + travis.mustache | 9 +- 19 files changed, 372 insertions(+), 134 deletions(-) create mode 100644 gitlab-ci.mustache diff --git a/api.mustache b/api.mustache index f1a110bd47..f2c5541835 100644 --- a/api.mustache +++ b/api.mustache @@ -10,7 +10,7 @@ import re # noqa: F401 import six from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( +from {{packageName}}.exceptions import ( # noqa: F401 ApiTypeError, ApiValueError ) @@ -99,20 +99,36 @@ class {{classname}}(object): """ {{#servers.0}} - local_var_hosts = [{{#servers}}'{{{url}}}'{{^-last}}, {{/-last}}{{/servers}}] # noqa: E501 + local_var_hosts = [ +{{#servers}} + '{{{url}}}'{{^-last}},{{/-last}} +{{/servers}} + ] local_var_host = local_var_hosts[0] if kwargs.get('_host_index'): - if int(kwags.get('_host_index')) < 0 or int(kawgs.get('_host_index')) >= len(local_var_hosts): - raise ApiValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) - local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] + _host_index = int(kwargs.get('_host_index')) + if _host_index < 0 or _host_index >= len(local_var_hosts): + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" + % len(local_var_host) + ) + local_var_host = local_var_hosts[_host_index] {{/servers.0}} local_var_params = locals() - all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 - all_params.append('async_req') - all_params.append('_return_http_data_only') - all_params.append('_preload_content') - all_params.append('_request_timeout') + all_params = [ +{{#allParams}} + '{{paramName}}'{{#hasMore}},{{/hasMore}} +{{/allParams}} + ] + all_params.extend( + [ + 'async_req', + '_return_http_data_only', + '_preload_content', + '_request_timeout' + ] + ) for key, val in six.iteritems(local_var_params['kwargs']): if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: diff --git a/api_client.mustache b/api_client.mustache index 08de3bab85..c69e7d5945 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -63,7 +63,7 @@ class ApiClient(object): def __init__(self, configuration=None, header_name=None, header_value=None, cookie=None, pool_threads=1): if configuration is None: - configuration = Configuration() + configuration = Configuration.get_default_copy() self.configuration = configuration self.pool_threads = pool_threads @@ -76,13 +76,25 @@ class ApiClient(object): self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' self.client_side_validation = configuration.client_side_validation + {{#asyncio}} + async def __aenter__(self): + return self + + async def __aexit__(self, exc_type, exc_value, traceback): + await self.close() + {{/asyncio}} + {{^asyncio}} def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() + {{/asyncio}} - def close(self): + {{#asyncio}}async {{/asyncio}}def close(self): + {{#asyncio}} + await self.rest_client.close() + {{/asyncio}} if self._pool: self._pool.close() self._pool.join() diff --git a/api_doc_example.mustache b/api_doc_example.mustache index e86c5d6011..dadb8f6a96 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -5,24 +5,17 @@ import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint {{> python_doc_auth_partial}} -{{#hasAuthMethods}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" # Enter a context with an instance of the API client +{{#hasAuthMethods}} with {{{packageName}}}.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) - {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} - {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} -# Enter a context with an instance of the API client with {{{packageName}}}.ApiClient() as api_client: +{{/hasAuthMethods}} # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} -{{/hasAuthMethods}} try: {{#summary}} # {{{.}}} diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 4585f1c6ad..f2099c7531 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -10,7 +10,6 @@ import ssl import aiohttp import certifi -import asyncio # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode @@ -66,19 +65,16 @@ class RESTClientObject(object): ssl=ssl_context ) + self.proxy = configuration.proxy + self.proxy_headers = configuration.proxy_headers + # https pool manager - if configuration.proxy: - self.pool_manager = aiohttp.ClientSession( - connector=connector, - proxy=configuration.proxy - ) - else: - self.pool_manager = aiohttp.ClientSession( - connector=connector - ) + self.pool_manager = aiohttp.ClientSession( + connector=connector + ) - def __del__(self): - asyncio.ensure_future(self.pool_manager.close()) + async def close(self): + await self.pool_manager.close() async def request(self, method, url, query_params=None, headers=None, body=None, post_params=None, _preload_content=True, @@ -123,6 +119,11 @@ class RESTClientObject(object): "headers": headers } + if self.proxy: + args["proxy"] = self.proxy + if self.proxy_headers: + args["proxy_headers"] = self.proxy_headers + if query_params: args["url"] += '?' + urlencode(query_params) diff --git a/configuration.mustache b/configuration.mustache index 0645bc4675..6581e603ad 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -4,6 +4,7 @@ from __future__ import absolute_import +import copy import logging {{^asyncio}} import multiprocessing @@ -31,6 +32,17 @@ class Configuration(object): The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication + :param discard_unknown_keys: Boolean value indicating whether to discard + unknown properties. A server may send a response that includes additional + properties that are not known by the client in the following scenarios: + 1. The OpenAPI document is incomplete, i.e. it does not match the server + implementation. + 2. The client was generated using an older version of the OpenAPI document + and the server has been upgraded since then. + If a schema in the OpenAPI document defines the additionalProperties attribute, + then all undeclared properties received by the server are injected into the + additional properties map. In that case, there are undeclared properties, and + nothing to discard. {{#hasHttpSignatureMethods}} :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration @@ -117,9 +129,12 @@ class Configuration(object): {{/hasAuthMethods}} """ + _default = None + def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, username=None, password=None, + discard_unknown_keys=False, {{#hasHttpSignatureMethods}} signing_info=None, {{/hasHttpSignatureMethods}} @@ -152,6 +167,7 @@ class Configuration(object): self.password = password """Password for HTTP basic authentication """ + self.discard_unknown_keys = discard_unknown_keys {{#hasHttpSignatureMethods}} if signing_info is not None: signing_info.host = host @@ -241,6 +257,45 @@ class Configuration(object): # Disable client side validation self.client_side_validation = True + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k not in ('logger', 'logger_file_handler'): + setattr(result, k, copy.deepcopy(v, memo)) + # shallow copy of loggers + result.logger = copy.copy(self.logger) + # use setters to configure loggers + result.logger_file = self.logger_file + result.debug = self.debug + return result + + @classmethod + def set_default(cls, default): + """Set default instance of configuration. + + It stores default configuration, which can be + returned by get_default_copy method. + + :param default: object of Configuration + """ + cls._default = copy.deepcopy(default) + + @classmethod + def get_default_copy(cls): + """Return new instance of configuration. + + This method returns newly created, based on default constructor, + object of Configuration class or returns a copy of default + configuration passed by the set_default method. + + :return: The configuration object. + """ + if cls._default is not None: + return copy.deepcopy(cls._default) + return Configuration() + @property def logger_file(self): """The logger file. diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache new file mode 100644 index 0000000000..2cabff63c7 --- /dev/null +++ b/gitlab-ci.mustache @@ -0,0 +1,38 @@ +# ref: https://docs.gitlab.com/ee/ci/README.html + +stages: + - test + +.nosetest: + stage: test + script: + - pip install -r requirements.txt + - pip install -r test-requirements.txt + {{#useNose}} + - nosetests + {{/useNose}} + {{^useNose}} + - pytest --cov={{{packageName}}} + {{/useNose}} + +nosetest-2.7: + extends: .nosetest + image: python:2.7-alpine +nosetest-3.3: + extends: .nosetest + image: python:3.3-alpine +nosetest-3.4: + extends: .nosetest + image: python:3.4-alpine +nosetest-3.5: + extends: .nosetest + image: python:3.5-alpine +nosetest-3.6: + extends: .nosetest + image: python:3.6-alpine +nosetest-3.7: + extends: .nosetest + image: python:3.7-alpine +nosetest-3.8: + extends: .nosetest + image: python:3.8-alpine diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 78f502b00d..774dae89c6 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -21,6 +21,7 @@ from {{packageName}}.exceptions import ApiValueError from {{packageName}}.model_utils import ( ModelNormal, ModelSimple, + ModelComposed, date, datetime, deserialize_file, @@ -240,7 +241,7 @@ class ApiClient(object): if isinstance(obj, dict): obj_dict = obj - elif isinstance(obj, ModelNormal): + elif isinstance(obj, ModelNormal) or isinstance(obj, ModelComposed): # Convert model obj to dict # Convert attribute name to json key in # model definition for request diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index 565d00a3b9..ae7b8a6979 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -4,20 +4,15 @@ import time import {{{packageName}}} from pprint import pprint {{> python_doc_auth_partial}} -{{#hasAuthMethods}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" # Enter a context with an instance of the API client +{{#hasAuthMethods}} with {{{packageName}}}.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{/hasAuthMethods}} {{^hasAuthMethods}} -# Enter a context with an instance of the API client -with {{{packageName}}}.ApiClient(configuration) as api_client: +with {{{packageName}}}.ApiClient() as api_client: +{{/hasAuthMethods}} # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) -{{/hasAuthMethods}} {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 0ca198ddf9..ef7da57282 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -7,6 +7,7 @@ import re # noqa: F401 import sys # noqa: F401 import six # noqa: F401 +import nulltype # noqa: F401 from {{packageName}}.model_utils import ( # noqa: F401 ModelComposed, diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index 5ed5993fe9..e00bf129b2 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -11,32 +11,39 @@ {{> python-experimental/model_templates/method_init_shared }} - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration - constant_args = { '_check_type': _check_type, '_path_to_item': _path_to_item, '_from_server': _from_server, '_configuration': _configuration, } - model_args = { + required_args = { {{#requiredVars}} '{{name}}': {{name}}, {{/requiredVars}} } + # remove args whose value is Null because they are unset + required_arg_names = list(required_args.keys()) + for required_arg_name in required_arg_names: + if required_args[required_arg_name] is nulltype.Null: + del required_args[required_arg_name] + model_args = {} + model_args.update(required_args) model_args.update(kwargs) composed_info = validate_get_composed_info( constant_args, model_args, self) self._composed_instances = composed_info[0] self._var_name_to_model_instances = composed_info[1] self._additional_properties_model_instances = composed_info[2] + unused_args = composed_info[3] -{{#requiredVars}} - self.{{name}} = {{name}} -{{/requiredVars}} + for var_name, var_value in required_args.items(): + setattr(self, var_name, var_value) for var_name, var_value in six.iteritems(kwargs): + if var_name in unused_args and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + not self._additional_properties_model_instances: + # discard variable. + continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index b053427a79..d26506c56c 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -8,14 +8,14 @@ {{> python-experimental/model_templates/method_init_shared }} - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration - {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} for var_name, var_value in six.iteritems(kwargs): + if var_name not in self.attribute_map and \ + self._configuration is not None and \ + self._configuration.discard_unknown_keys and \ + self.additional_properties_type is None: + # discard variable. + continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 2f3b70ea69..9dd5bc2b6f 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,11 +1,23 @@ def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI -{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} -{{/hasMore}}{{/requiredVars}} - Keyword Args:{{#requiredVars}}{{#defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} +{{#requiredVars}} +{{#-first}} + Args: +{{/-first}} +{{^defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}} +{{/defaultValue}} +{{#-last}} + +{{/-last}} +{{/requiredVars}} + Keyword Args: +{{#requiredVars}} +{{#defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 +{{/defaultValue}} +{{/requiredVars}} _check_type (bool): if True, values for parameters in openapi_types will be type checked and a TypeError will be raised if the wrong type is input. @@ -18,6 +30,14 @@ _configuration (Configuration): the instance to use when deserializing a file_type parameter. If passed, type conversion is attempted - If omitted no type conversion is done.{{#optionalVars}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} - """ \ No newline at end of file + If omitted no type conversion is done. +{{#optionalVars}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 +{{/optionalVars}} + """ + + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration \ No newline at end of file diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index e5eee88a96..9420fe1582 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -41,21 +41,29 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) + values = [] + # A composed model stores child (oneof/anyOf/allOf) models under + # self._var_name_to_model_instances. A named property can exist in + # multiple child models. If the property is present in more than one + # child model, the value must be the same across all the child models. if model_instances: - values = set() for model_instance in model_instances: if name in model_instance._data_store: - values.add(model_instance._data_store[name]) - if len(values) == 1: - return list(values)[0] + v = model_instance._data_store[name] + if v not in values: + values.append(v) + len_values = len(values) + if len_values == 0: + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) + elif len_values == 1: + return values[0] + elif len_values > 1: raise ApiValueError( - "Values stored for property {0} in {1} difffer when looking " + "Values stored for property {0} in {1} differ when looking " "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), path_to_item - ) - - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), - path_to_item - ) \ No newline at end of file + ) \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index c3d9e7d536..8b60618c1d 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -464,7 +464,11 @@ def get_required_type_classes(required_types_mixed): def change_keys_js_to_python(input_dict, model_class): """ Converts from javascript_key keys in the input_dict to python_keys in - the output dict using the mapping in model_class + the output dict using the mapping in model_class. + If the input_dict contains a key which does not declared in the model_class, + the key is added to the output dict as is. The assumption is the model_class + may have undeclared properties (additionalProperties attribute in the OAS + document). """ output_dict = {} @@ -677,8 +681,9 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, if not valid_classes_coercible or key_type: # we do not handle keytype errors, json will take care # of this for us - raise get_type_error(input_value, path_to_item, valid_classes, - key_type=key_type) + if configuration is None or not configuration.discard_unknown_keys: + raise get_type_error(input_value, path_to_item, valid_classes, + key_type=key_type) for valid_class in valid_classes_coercible: try: if issubclass(valid_class, OpenApiModel): @@ -827,7 +832,7 @@ def model_to_dict(model_instance, serialize=True): model_instances = [model_instance] if model_instance._composed_schemas() is not None: - model_instances = model_instance._composed_instances + model_instances.extend(model_instance._composed_instances) for model_instance in model_instances: for attr, value in six.iteritems(model_instance._data_store): if serialize: @@ -935,53 +940,88 @@ def get_allof_instances(self, model_args, constant_args): # and use it to make the instance kwargs.update(constant_args) - allof_instance = allof_class(**kwargs) - composed_instances.append(allof_instance) + try: + allof_instance = allof_class(**kwargs) + composed_instances.append(allof_instance) + except Exception as ex: + raise ApiValueError( + "Invalid inputs given to generate an instance of '%s'. The " + "input data was invalid for the allOf schema '%s' in the composed " + "schema '%s'. Error=%s" % ( + allof_class.__class__.__name__, + allof_class.__class__.__name__, + self.__class__.__name__, + str(ex) + ) + ) return composed_instances def get_oneof_instance(self, model_args, constant_args): """ + Find the oneOf schema that matches the input data (e.g. payload). + If exactly one schema matches the input data, an instance of that schema + is returned. + If zero or more than one schema match the input data, an exception is raised. + In OAS 3.x, the payload MUST, by validation, match exactly one of the + schemas described by oneOf. Args: self: the class we are handling model_args (dict): var_name to var_value - used to make instances + The input data, e.g. the payload that must match a oneOf schema + in the OpenAPI document. constant_args (dict): var_name to var_value - used to make instances + args that every model requires, including configuration, server + and path to item. Returns - oneof_instance (instance) + oneof_instance (instance/None) """ - oneof_instance = None if len(self._composed_schemas()['oneOf']) == 0: - return oneof_instance + return None + oneof_instances = [] + # Iterate over each oneOf schema and determine if the input data + # matches the oneOf schemas. for oneof_class in self._composed_schemas()['oneOf']: - # transform js keys to python keys in fixed_model_args + # transform js keys from input data to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( model_args, oneof_class) - # extract a dict of only required keys from fixed_model_args + # Extract a dict with the properties that are declared in the oneOf schema. + # Undeclared properties (e.g. properties that are allowed because of the + # additionalProperties attribute in the OAS document) are not added to + # the dict. kwargs = {} var_names = set(oneof_class.openapi_types().keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] + # do not try to make a model with no input args + if len(kwargs) == 0: + continue + # and use it to make the instance kwargs.update(constant_args) try: oneof_instance = oneof_class(**kwargs) - break + oneof_instances.append(oneof_instance) except Exception: pass - if oneof_instance is None: + if len(oneof_instances) == 0: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. Unable to " - "make any instances of the classes in oneOf definition." % + "Invalid inputs given to generate an instance of %s. None " + "of the oneOf schemas matched the input data." % self.__class__.__name__ ) - return oneof_instance + elif len(oneof_instances) > 1: + raise ApiValueError( + "Invalid inputs given to generate an instance of %s. Multiple " + "oneOf schemas matched the inputs, but a max of one is allowed." % + self.__class__.__name__ + ) + return oneof_instances[0] def get_anyof_instances(self, model_args, constant_args): @@ -1011,6 +1051,10 @@ def get_anyof_instances(self, model_args, constant_args): if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] + # do not try to make a model with no input args + if len(kwargs) == 0: + continue + # and use it to make the instance kwargs.update(constant_args) try: @@ -1020,8 +1064,8 @@ def get_anyof_instances(self, model_args, constant_args): pass if len(anyof_instances) == 0: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. Unable to " - "make any instances of the classes in anyOf definition." % + "Invalid inputs given to generate an instance of %s. None of the " + "anyOf schemas matched the inputs." % self.__class__.__name__ ) return anyof_instances @@ -1072,10 +1116,18 @@ def get_unused_args(self, composed_instances, model_args): def validate_get_composed_info(constant_args, model_args, self): """ - For composed schemas/classes, validates the classes to make sure that - they do not share any of the same parameters. If there is no collision - then composed model instances are created and returned tot the calling - self model + For composed schemas, generate schema instances for + all schemas in the oneOf/anyOf/allOf definition. If additional + properties are allowed, also assign those properties on + all matched schemas that contain additionalProperties. + Openapi schemas are python classes. + + Exceptions are raised if: + - no oneOf schema matches the model_args input data + - > 1 oneOf schema matches the model_args input data + - > 1 oneOf schema matches the model_args input data + - no anyOf schema matches the model_args input data + - any of the allOf schemas do not match the model_args input data Args: constant_args (dict): these are the args that every model requires @@ -1117,16 +1169,16 @@ def validate_get_composed_info(constant_args, model_args, self): # set any remaining values unused_args = get_unused_args(self, composed_instances, model_args) - if len(unused_args) > 0: - if len(additional_properties_model_instances) == 0: - raise ApiValueError( - "Invalid input arguments input when making an instance of " - "class %s. Not all inputs were used. The unused input data " - "is %s" % (self.__class__.__name__, unused_args) - ) - for var_name, var_value in six.iteritems(unused_args): - for instance in additional_properties_model_instances: - setattr(instance, var_name, var_value) + if len(unused_args) > 0 and \ + len(additional_properties_model_instances) == 0 and \ + (self._configuration is None or + not self._configuration.discard_unknown_keys): + raise ApiValueError( + "Invalid input arguments input when making an instance of " + "class %s. Not all inputs were used. The unused input data " + "is %s" % (self.__class__.__name__, unused_args) + ) + # no need to add additional_properties to var_name_to_model_instances here # because additional_properties_model_instances will direct us to that # instance when we use getattr or setattr @@ -1135,5 +1187,6 @@ def validate_get_composed_info(constant_args, model_args, self): return [ composed_instances, var_name_to_model_instances, - additional_properties_model_instances + additional_properties_model_instances, + unused_args ] diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache index eb358efd5b..a56bedffbf 100644 --- a/python-experimental/requirements.mustache +++ b/python-experimental/requirements.mustache @@ -1,3 +1,4 @@ +nulltype certifi >= 14.05.14 future; python_version<="2.7" six >= 1.10 diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 2fe84efcee..796475c456 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -21,6 +21,7 @@ REQUIRES = [ "six >= 1.10", "certifi", "python-dateutil", + "nulltype", {{#asyncio}} "aiohttp >= 3.0.0", {{/asyncio}} diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index 300efa007b..0be0e1c467 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -7,13 +7,12 @@ from Crypto.IO import PEM, PKCS8 from Crypto.Hash import SHA256, SHA512 from Crypto.PublicKey import RSA, ECC from Crypto.Signature import PKCS1_v1_5, pss, DSS -from datetime import datetime from email.utils import formatdate import json import os import re from six.moves.urllib.parse import urlencode, urlparse -from time import mktime +from time import time # The constants below define a subset of HTTP headers that can be included in the # HTTP signature scheme. Additional headers may be included in the signature. @@ -54,6 +53,10 @@ ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS = { ALGORITHM_ECDSA_MODE_DETERMINISTIC_RFC6979 } +# The cryptographic hash algorithm for the message signature. +HASH_SHA256 = 'sha256' +HASH_SHA512 = 'sha512' + class HttpSigningConfiguration(object): """The configuration parameters for the HTTP signature security scheme. @@ -99,9 +102,15 @@ class HttpSigningConfiguration(object): Supported values are: 1. For RSA keys: RSASSA-PSS, RSASSA-PKCS1-v1_5. 2. For ECDSA keys: fips-186-3, deterministic-rfc6979. - The default value is inferred from the private key. - The default value for RSA keys is RSASSA-PSS. - The default value for ECDSA keys is fips-186-3. + If None, the signing algorithm is inferred from the private key. + The default signing algorithm for RSA keys is RSASSA-PSS. + The default signing algorithm for ECDSA keys is fips-186-3. + :param hash_algorithm: The hash algorithm for the signature. Supported values are + sha256 and sha512. + If the signing_scheme is rsa-sha256, the hash algorithm must be set + to None or sha256. + If the signing_scheme is rsa-sha512, the hash algorithm must be set + to None or sha512. :param signature_max_validity: The signature max validity, expressed as a datetime.timedelta value. It must be a positive value. """ @@ -109,6 +118,7 @@ class HttpSigningConfiguration(object): private_key_passphrase=None, signed_headers=None, signing_algorithm=None, + hash_algorithm=None, signature_max_validity=None): self.key_id = key_id if signing_scheme not in {SCHEME_HS2019, SCHEME_RSA_SHA256, SCHEME_RSA_SHA512}: @@ -119,6 +129,24 @@ class HttpSigningConfiguration(object): self.private_key_path = private_key_path self.private_key_passphrase = private_key_passphrase self.signing_algorithm = signing_algorithm + self.hash_algorithm = hash_algorithm + if signing_scheme == SCHEME_RSA_SHA256: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA256 + elif self.hash_algorithm != HASH_SHA256: + raise Exception("Hash algorithm must be sha256 when security scheme is %s" % + SCHEME_RSA_SHA256) + elif signing_scheme == SCHEME_RSA_SHA512: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA512 + elif self.hash_algorithm != HASH_SHA512: + raise Exception("Hash algorithm must be sha512 when security scheme is %s" % + SCHEME_RSA_SHA512) + elif signing_scheme == SCHEME_HS2019: + if self.hash_algorithm is None: + self.hash_algorithm = HASH_SHA256 + elif self.hash_algorithm not in {HASH_SHA256, HASH_SHA512}: + raise Exception("Invalid hash algorithm") if signature_max_validity is not None and signature_max_validity.total_seconds() < 0: raise Exception("The signature max validity must be a positive value") self.signature_max_validity = signature_max_validity @@ -228,12 +256,6 @@ class HttpSigningConfiguration(object): "Signing algorithm {0} is not compatible with private key".format( self.signing_algorithm)) - def _get_unix_time(self, ts): - """Converts and returns a datetime object to UNIX time, the number of seconds - elapsed since January 1, 1970 UTC. - """ - return (ts - datetime(1970, 1, 1)).total_seconds() - def _get_signed_header_info(self, resource_path, method, headers, body, query_params): """Build the HTTP headers (name, value) that need to be included in the HTTP signature scheme. @@ -262,15 +284,16 @@ class HttpSigningConfiguration(object): if query_params: request_target += "?" + urlencode(query_params) - # Get current time and generate RFC 1123 (HTTP/1.1) date/time string. - now = datetime.now() - stamp = mktime(now.timetuple()) - cdate = formatdate(timeval=stamp, localtime=False, usegmt=True) + # Get UNIX time, e.g. seconds since epoch, not including leap seconds. + now = time() + # Format date per RFC 7231 section-7.1.1.2. An example is: + # Date: Wed, 21 Oct 2015 07:28:00 GMT + cdate = formatdate(timeval=now, localtime=False, usegmt=True) # The '(created)' value MUST be a Unix timestamp integer value. # Subsecond precision is not supported. - created = int(self._get_unix_time(now)) + created = int(now) if self.signature_max_validity is not None: - expires = self._get_unix_time(now + self.signature_max_validity) + expires = now + self.signature_max_validity.total_seconds() signed_headers_list = [] request_headers_dict = {} @@ -315,14 +338,14 @@ class HttpSigningConfiguration(object): The prefix is a string that identifies the cryptographc hash. It is used to generate the 'Digest' header as specified in RFC 3230. """ - if self.signing_scheme in {SCHEME_RSA_SHA512, SCHEME_HS2019}: + if self.hash_algorithm == HASH_SHA512: digest = SHA512.new() prefix = 'SHA-512=' - elif self.signing_scheme == SCHEME_RSA_SHA256: + elif self.hash_algorithm == HASH_SHA256: digest = SHA256.new() prefix = 'SHA-256=' else: - raise Exception("Unsupported signing algorithm: {0}".format(self.signing_scheme)) + raise Exception("Unsupported hash algorithm: {0}".format(self.hash_algorithm)) digest.update(data) return digest, prefix @@ -346,7 +369,10 @@ class HttpSigningConfiguration(object): if sig_alg is None: sig_alg = ALGORITHM_ECDSA_MODE_FIPS_186_3 if sig_alg in ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS: - signature = DSS.new(self.private_key, sig_alg).sign(digest) + # draft-ietf-httpbis-message-signatures-00 does not specify the ECDSA encoding. + # Issue: https://github.com/w3c-ccg/http-signatures/issues/107 + signature = DSS.new(key=self.private_key, mode=sig_alg, + encoding='der').sign(digest) else: raise Exception("Unsupported signature algorithm: {0}".format(sig_alg)) else: diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 9f5b49f821..d8cfc4ad11 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -45,4 +45,7 @@ configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' configuration.access_token = 'YOUR_ACCESS_TOKEN' {{/isOAuth}} {{/authMethods}} + +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" {{/hasAuthMethods}} diff --git a/travis.mustache b/travis.mustache index 388de83128..195488737d 100644 --- a/travis.mustache +++ b/travis.mustache @@ -10,6 +10,13 @@ python: - "3.7" - "3.8" # command to install dependencies -install: "pip install -r requirements.txt" +install: + - "pip install -r requirements.txt" + - "pip install -r test-requirements.txt" # command to run tests +{{#useNose}} script: nosetests +{{/useNose}} +{{^useNose}} +script: pytest --cov={{{packageName}}} +{{/useNose}} From 50238bff045990043f962761d55eff6948e77aa5 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 22 Apr 2020 11:59:27 +0800 Subject: [PATCH 099/180] Revert "Sync master to 5.0.x (#5968)" This reverts commit 90dd7a03418ff4554ae8351b325eb86ee5794e92. --- api.mustache | 36 ++--- api_client.mustache | 16 +-- api_doc_example.mustache | 11 +- asyncio/rest.mustache | 25 ++-- configuration.mustache | 55 -------- gitlab-ci.mustache | 38 ------ python-experimental/api_client.mustache | 3 +- python-experimental/api_doc_example.mustache | 11 +- python-experimental/model.mustache | 1 - .../method_init_composed.mustache | 27 ++-- .../method_init_normal.mustache | 12 +- .../method_init_shared.mustache | 36 ++--- .../methods_setattr_getattr_composed.mustache | 30 ++--- python-experimental/model_utils.mustache | 123 +++++------------- python-experimental/requirements.mustache | 1 - python-experimental/setup.mustache | 1 - python-experimental/signing.mustache | 68 +++------- python_doc_auth_partial.mustache | 3 - travis.mustache | 9 +- 19 files changed, 134 insertions(+), 372 deletions(-) delete mode 100644 gitlab-ci.mustache diff --git a/api.mustache b/api.mustache index f2c5541835..f1a110bd47 100644 --- a/api.mustache +++ b/api.mustache @@ -10,7 +10,7 @@ import re # noqa: F401 import six from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( # noqa: F401 +from {{packageName}}.exceptions import ( ApiTypeError, ApiValueError ) @@ -99,36 +99,20 @@ class {{classname}}(object): """ {{#servers.0}} - local_var_hosts = [ -{{#servers}} - '{{{url}}}'{{^-last}},{{/-last}} -{{/servers}} - ] + local_var_hosts = [{{#servers}}'{{{url}}}'{{^-last}}, {{/-last}}{{/servers}}] # noqa: E501 local_var_host = local_var_hosts[0] if kwargs.get('_host_index'): - _host_index = int(kwargs.get('_host_index')) - if _host_index < 0 or _host_index >= len(local_var_hosts): - raise ApiValueError( - "Invalid host index. Must be 0 <= index < %s" - % len(local_var_host) - ) - local_var_host = local_var_hosts[_host_index] + if int(kwags.get('_host_index')) < 0 or int(kawgs.get('_host_index')) >= len(local_var_hosts): + raise ApiValueError("Invalid host index. Must be 0 <= index < %s" % len(local_var_host)) + local_var_host = local_var_hosts[int(kwargs.get('_host_index'))] {{/servers.0}} local_var_params = locals() - all_params = [ -{{#allParams}} - '{{paramName}}'{{#hasMore}},{{/hasMore}} -{{/allParams}} - ] - all_params.extend( - [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout' - ] - ) + all_params = [{{#allParams}}'{{paramName}}'{{#hasMore}}, {{/hasMore}}{{/allParams}}] # noqa: E501 + all_params.append('async_req') + all_params.append('_return_http_data_only') + all_params.append('_preload_content') + all_params.append('_request_timeout') for key, val in six.iteritems(local_var_params['kwargs']): if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: diff --git a/api_client.mustache b/api_client.mustache index c69e7d5945..08de3bab85 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -63,7 +63,7 @@ class ApiClient(object): def __init__(self, configuration=None, header_name=None, header_value=None, cookie=None, pool_threads=1): if configuration is None: - configuration = Configuration.get_default_copy() + configuration = Configuration() self.configuration = configuration self.pool_threads = pool_threads @@ -76,25 +76,13 @@ class ApiClient(object): self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' self.client_side_validation = configuration.client_side_validation - {{#asyncio}} - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_value, traceback): - await self.close() - {{/asyncio}} - {{^asyncio}} def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() - {{/asyncio}} - {{#asyncio}}async {{/asyncio}}def close(self): - {{#asyncio}} - await self.rest_client.close() - {{/asyncio}} + def close(self): if self._pool: self._pool.close() self._pool.join() diff --git a/api_doc_example.mustache b/api_doc_example.mustache index dadb8f6a96..e86c5d6011 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -5,17 +5,24 @@ import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint {{> python_doc_auth_partial}} -# Enter a context with an instance of the API client {{#hasAuthMethods}} +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Enter a context with an instance of the API client with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) + {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} + {{/allParams}} {{/hasAuthMethods}} {{^hasAuthMethods}} +# Enter a context with an instance of the API client with {{{packageName}}}.ApiClient() as api_client: -{{/hasAuthMethods}} # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} +{{/hasAuthMethods}} try: {{#summary}} # {{{.}}} diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index f2099c7531..4585f1c6ad 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -10,6 +10,7 @@ import ssl import aiohttp import certifi +import asyncio # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode @@ -65,16 +66,19 @@ class RESTClientObject(object): ssl=ssl_context ) - self.proxy = configuration.proxy - self.proxy_headers = configuration.proxy_headers - # https pool manager - self.pool_manager = aiohttp.ClientSession( - connector=connector - ) + if configuration.proxy: + self.pool_manager = aiohttp.ClientSession( + connector=connector, + proxy=configuration.proxy + ) + else: + self.pool_manager = aiohttp.ClientSession( + connector=connector + ) - async def close(self): - await self.pool_manager.close() + def __del__(self): + asyncio.ensure_future(self.pool_manager.close()) async def request(self, method, url, query_params=None, headers=None, body=None, post_params=None, _preload_content=True, @@ -119,11 +123,6 @@ class RESTClientObject(object): "headers": headers } - if self.proxy: - args["proxy"] = self.proxy - if self.proxy_headers: - args["proxy_headers"] = self.proxy_headers - if query_params: args["url"] += '?' + urlencode(query_params) diff --git a/configuration.mustache b/configuration.mustache index 6581e603ad..0645bc4675 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -4,7 +4,6 @@ from __future__ import absolute_import -import copy import logging {{^asyncio}} import multiprocessing @@ -32,17 +31,6 @@ class Configuration(object): The dict value is an API key prefix when generating the auth data. :param username: Username for HTTP basic authentication :param password: Password for HTTP basic authentication - :param discard_unknown_keys: Boolean value indicating whether to discard - unknown properties. A server may send a response that includes additional - properties that are not known by the client in the following scenarios: - 1. The OpenAPI document is incomplete, i.e. it does not match the server - implementation. - 2. The client was generated using an older version of the OpenAPI document - and the server has been upgraded since then. - If a schema in the OpenAPI document defines the additionalProperties attribute, - then all undeclared properties received by the server are injected into the - additional properties map. In that case, there are undeclared properties, and - nothing to discard. {{#hasHttpSignatureMethods}} :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration @@ -129,12 +117,9 @@ class Configuration(object): {{/hasAuthMethods}} """ - _default = None - def __init__(self, host="{{{basePath}}}", api_key=None, api_key_prefix=None, username=None, password=None, - discard_unknown_keys=False, {{#hasHttpSignatureMethods}} signing_info=None, {{/hasHttpSignatureMethods}} @@ -167,7 +152,6 @@ class Configuration(object): self.password = password """Password for HTTP basic authentication """ - self.discard_unknown_keys = discard_unknown_keys {{#hasHttpSignatureMethods}} if signing_info is not None: signing_info.host = host @@ -257,45 +241,6 @@ class Configuration(object): # Disable client side validation self.client_side_validation = True - def __deepcopy__(self, memo): - cls = self.__class__ - result = cls.__new__(cls) - memo[id(self)] = result - for k, v in self.__dict__.items(): - if k not in ('logger', 'logger_file_handler'): - setattr(result, k, copy.deepcopy(v, memo)) - # shallow copy of loggers - result.logger = copy.copy(self.logger) - # use setters to configure loggers - result.logger_file = self.logger_file - result.debug = self.debug - return result - - @classmethod - def set_default(cls, default): - """Set default instance of configuration. - - It stores default configuration, which can be - returned by get_default_copy method. - - :param default: object of Configuration - """ - cls._default = copy.deepcopy(default) - - @classmethod - def get_default_copy(cls): - """Return new instance of configuration. - - This method returns newly created, based on default constructor, - object of Configuration class or returns a copy of default - configuration passed by the set_default method. - - :return: The configuration object. - """ - if cls._default is not None: - return copy.deepcopy(cls._default) - return Configuration() - @property def logger_file(self): """The logger file. diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache deleted file mode 100644 index 2cabff63c7..0000000000 --- a/gitlab-ci.mustache +++ /dev/null @@ -1,38 +0,0 @@ -# ref: https://docs.gitlab.com/ee/ci/README.html - -stages: - - test - -.nosetest: - stage: test - script: - - pip install -r requirements.txt - - pip install -r test-requirements.txt - {{#useNose}} - - nosetests - {{/useNose}} - {{^useNose}} - - pytest --cov={{{packageName}}} - {{/useNose}} - -nosetest-2.7: - extends: .nosetest - image: python:2.7-alpine -nosetest-3.3: - extends: .nosetest - image: python:3.3-alpine -nosetest-3.4: - extends: .nosetest - image: python:3.4-alpine -nosetest-3.5: - extends: .nosetest - image: python:3.5-alpine -nosetest-3.6: - extends: .nosetest - image: python:3.6-alpine -nosetest-3.7: - extends: .nosetest - image: python:3.7-alpine -nosetest-3.8: - extends: .nosetest - image: python:3.8-alpine diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 774dae89c6..78f502b00d 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -21,7 +21,6 @@ from {{packageName}}.exceptions import ApiValueError from {{packageName}}.model_utils import ( ModelNormal, ModelSimple, - ModelComposed, date, datetime, deserialize_file, @@ -241,7 +240,7 @@ class ApiClient(object): if isinstance(obj, dict): obj_dict = obj - elif isinstance(obj, ModelNormal) or isinstance(obj, ModelComposed): + elif isinstance(obj, ModelNormal): # Convert model obj to dict # Convert attribute name to json key in # model definition for request diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index ae7b8a6979..565d00a3b9 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -4,15 +4,20 @@ import time import {{{packageName}}} from pprint import pprint {{> python_doc_auth_partial}} -# Enter a context with an instance of the API client {{#hasAuthMethods}} +# Defining host is optional and default to {{{basePath}}} +configuration.host = "{{{basePath}}}" +# Enter a context with an instance of the API client with {{{packageName}}}.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = {{{packageName}}}.{{{classname}}}(api_client) {{/hasAuthMethods}} {{^hasAuthMethods}} -with {{{packageName}}}.ApiClient() as api_client: -{{/hasAuthMethods}} +# Enter a context with an instance of the API client +with {{{packageName}}}.ApiClient(configuration) as api_client: # Create an instance of the API class api_instance = {{{packageName}}}.{{{classname}}}(api_client) +{{/hasAuthMethods}} {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index ef7da57282..0ca198ddf9 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -7,7 +7,6 @@ import re # noqa: F401 import sys # noqa: F401 import six # noqa: F401 -import nulltype # noqa: F401 from {{packageName}}.model_utils import ( # noqa: F401 ModelComposed, diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index e00bf129b2..5ed5993fe9 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -11,39 +11,32 @@ {{> python-experimental/model_templates/method_init_shared }} + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration + constant_args = { '_check_type': _check_type, '_path_to_item': _path_to_item, '_from_server': _from_server, '_configuration': _configuration, } - required_args = { + model_args = { {{#requiredVars}} '{{name}}': {{name}}, {{/requiredVars}} } - # remove args whose value is Null because they are unset - required_arg_names = list(required_args.keys()) - for required_arg_name in required_arg_names: - if required_args[required_arg_name] is nulltype.Null: - del required_args[required_arg_name] - model_args = {} - model_args.update(required_args) model_args.update(kwargs) composed_info = validate_get_composed_info( constant_args, model_args, self) self._composed_instances = composed_info[0] self._var_name_to_model_instances = composed_info[1] self._additional_properties_model_instances = composed_info[2] - unused_args = composed_info[3] - for var_name, var_value in required_args.items(): - setattr(self, var_name, var_value) +{{#requiredVars}} + self.{{name}} = {{name}} +{{/requiredVars}} for var_name, var_value in six.iteritems(kwargs): - if var_name in unused_args and \ - self._configuration is not None and \ - self._configuration.discard_unknown_keys and \ - not self._additional_properties_model_instances: - # discard variable. - continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index d26506c56c..b053427a79 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -8,14 +8,14 @@ {{> python-experimental/model_templates/method_init_shared }} + self._data_store = {} + self._check_type = _check_type + self._from_server = _from_server + self._path_to_item = _path_to_item + self._configuration = _configuration + {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} for var_name, var_value in six.iteritems(kwargs): - if var_name not in self.attribute_map and \ - self._configuration is not None and \ - self._configuration.discard_unknown_keys and \ - self.additional_properties_type is None: - # discard variable. - continue setattr(self, var_name, var_value) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 9dd5bc2b6f..2f3b70ea69 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,23 +1,11 @@ def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI -{{#requiredVars}} -{{#-first}} - Args: -{{/-first}} -{{^defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}} -{{/defaultValue}} -{{#-last}} - -{{/-last}} -{{/requiredVars}} - Keyword Args: -{{#requiredVars}} -{{#defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 -{{/defaultValue}} -{{/requiredVars}} +{{#requiredVars}}{{^hasMore}} Args:{{/hasMore}}{{/requiredVars}}{{#requiredVars}}{{^defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{^hasMore}} +{{/hasMore}}{{/requiredVars}} + Keyword Args:{{#requiredVars}}{{#defaultValue}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] # noqa: E501{{/defaultValue}}{{/requiredVars}} _check_type (bool): if True, values for parameters in openapi_types will be type checked and a TypeError will be raised if the wrong type is input. @@ -30,14 +18,6 @@ _configuration (Configuration): the instance to use when deserializing a file_type parameter. If passed, type conversion is attempted - If omitted no type conversion is done. -{{#optionalVars}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 -{{/optionalVars}} - """ - - self._data_store = {} - self._check_type = _check_type - self._from_server = _from_server - self._path_to_item = _path_to_item - self._configuration = _configuration \ No newline at end of file + If omitted no type conversion is done.{{#optionalVars}} + {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501{{/optionalVars}} + """ \ No newline at end of file diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index 9420fe1582..e5eee88a96 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -41,29 +41,21 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) - values = [] - # A composed model stores child (oneof/anyOf/allOf) models under - # self._var_name_to_model_instances. A named property can exist in - # multiple child models. If the property is present in more than one - # child model, the value must be the same across all the child models. if model_instances: + values = set() for model_instance in model_instances: if name in model_instance._data_store: - v = model_instance._data_store[name] - if v not in values: - values.append(v) - len_values = len(values) - if len_values == 0: - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), - path_to_item - ) - elif len_values == 1: - return values[0] - elif len_values > 1: + values.add(model_instance._data_store[name]) + if len(values) == 1: + return list(values)[0] raise ApiValueError( - "Values stored for property {0} in {1} differ when looking " + "Values stored for property {0} in {1} difffer when looking " "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), path_to_item - ) \ No newline at end of file + ) + + raise ApiKeyError( + "{0} has no key '{1}'".format(type(self).__name__, name), + path_to_item + ) \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 8b60618c1d..c3d9e7d536 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -464,11 +464,7 @@ def get_required_type_classes(required_types_mixed): def change_keys_js_to_python(input_dict, model_class): """ Converts from javascript_key keys in the input_dict to python_keys in - the output dict using the mapping in model_class. - If the input_dict contains a key which does not declared in the model_class, - the key is added to the output dict as is. The assumption is the model_class - may have undeclared properties (additionalProperties attribute in the OAS - document). + the output dict using the mapping in model_class """ output_dict = {} @@ -681,9 +677,8 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, if not valid_classes_coercible or key_type: # we do not handle keytype errors, json will take care # of this for us - if configuration is None or not configuration.discard_unknown_keys: - raise get_type_error(input_value, path_to_item, valid_classes, - key_type=key_type) + raise get_type_error(input_value, path_to_item, valid_classes, + key_type=key_type) for valid_class in valid_classes_coercible: try: if issubclass(valid_class, OpenApiModel): @@ -832,7 +827,7 @@ def model_to_dict(model_instance, serialize=True): model_instances = [model_instance] if model_instance._composed_schemas() is not None: - model_instances.extend(model_instance._composed_instances) + model_instances = model_instance._composed_instances for model_instance in model_instances: for attr, value in six.iteritems(model_instance._data_store): if serialize: @@ -940,88 +935,53 @@ def get_allof_instances(self, model_args, constant_args): # and use it to make the instance kwargs.update(constant_args) - try: - allof_instance = allof_class(**kwargs) - composed_instances.append(allof_instance) - except Exception as ex: - raise ApiValueError( - "Invalid inputs given to generate an instance of '%s'. The " - "input data was invalid for the allOf schema '%s' in the composed " - "schema '%s'. Error=%s" % ( - allof_class.__class__.__name__, - allof_class.__class__.__name__, - self.__class__.__name__, - str(ex) - ) - ) + allof_instance = allof_class(**kwargs) + composed_instances.append(allof_instance) return composed_instances def get_oneof_instance(self, model_args, constant_args): """ - Find the oneOf schema that matches the input data (e.g. payload). - If exactly one schema matches the input data, an instance of that schema - is returned. - If zero or more than one schema match the input data, an exception is raised. - In OAS 3.x, the payload MUST, by validation, match exactly one of the - schemas described by oneOf. Args: self: the class we are handling model_args (dict): var_name to var_value - The input data, e.g. the payload that must match a oneOf schema - in the OpenAPI document. + used to make instances constant_args (dict): var_name to var_value - args that every model requires, including configuration, server - and path to item. + used to make instances Returns - oneof_instance (instance/None) + oneof_instance (instance) """ + oneof_instance = None if len(self._composed_schemas()['oneOf']) == 0: - return None + return oneof_instance - oneof_instances = [] - # Iterate over each oneOf schema and determine if the input data - # matches the oneOf schemas. for oneof_class in self._composed_schemas()['oneOf']: - # transform js keys from input data to python keys in fixed_model_args + # transform js keys to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( model_args, oneof_class) - # Extract a dict with the properties that are declared in the oneOf schema. - # Undeclared properties (e.g. properties that are allowed because of the - # additionalProperties attribute in the OAS document) are not added to - # the dict. + # extract a dict of only required keys from fixed_model_args kwargs = {} var_names = set(oneof_class.openapi_types().keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] - # do not try to make a model with no input args - if len(kwargs) == 0: - continue - # and use it to make the instance kwargs.update(constant_args) try: oneof_instance = oneof_class(**kwargs) - oneof_instances.append(oneof_instance) + break except Exception: pass - if len(oneof_instances) == 0: + if oneof_instance is None: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. None " - "of the oneOf schemas matched the input data." % + "Invalid inputs given to generate an instance of %s. Unable to " + "make any instances of the classes in oneOf definition." % self.__class__.__name__ ) - elif len(oneof_instances) > 1: - raise ApiValueError( - "Invalid inputs given to generate an instance of %s. Multiple " - "oneOf schemas matched the inputs, but a max of one is allowed." % - self.__class__.__name__ - ) - return oneof_instances[0] + return oneof_instance def get_anyof_instances(self, model_args, constant_args): @@ -1051,10 +1011,6 @@ def get_anyof_instances(self, model_args, constant_args): if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] - # do not try to make a model with no input args - if len(kwargs) == 0: - continue - # and use it to make the instance kwargs.update(constant_args) try: @@ -1064,8 +1020,8 @@ def get_anyof_instances(self, model_args, constant_args): pass if len(anyof_instances) == 0: raise ApiValueError( - "Invalid inputs given to generate an instance of %s. None of the " - "anyOf schemas matched the inputs." % + "Invalid inputs given to generate an instance of %s. Unable to " + "make any instances of the classes in anyOf definition." % self.__class__.__name__ ) return anyof_instances @@ -1116,18 +1072,10 @@ def get_unused_args(self, composed_instances, model_args): def validate_get_composed_info(constant_args, model_args, self): """ - For composed schemas, generate schema instances for - all schemas in the oneOf/anyOf/allOf definition. If additional - properties are allowed, also assign those properties on - all matched schemas that contain additionalProperties. - Openapi schemas are python classes. - - Exceptions are raised if: - - no oneOf schema matches the model_args input data - - > 1 oneOf schema matches the model_args input data - - > 1 oneOf schema matches the model_args input data - - no anyOf schema matches the model_args input data - - any of the allOf schemas do not match the model_args input data + For composed schemas/classes, validates the classes to make sure that + they do not share any of the same parameters. If there is no collision + then composed model instances are created and returned tot the calling + self model Args: constant_args (dict): these are the args that every model requires @@ -1169,16 +1117,16 @@ def validate_get_composed_info(constant_args, model_args, self): # set any remaining values unused_args = get_unused_args(self, composed_instances, model_args) - if len(unused_args) > 0 and \ - len(additional_properties_model_instances) == 0 and \ - (self._configuration is None or - not self._configuration.discard_unknown_keys): - raise ApiValueError( - "Invalid input arguments input when making an instance of " - "class %s. Not all inputs were used. The unused input data " - "is %s" % (self.__class__.__name__, unused_args) - ) - + if len(unused_args) > 0: + if len(additional_properties_model_instances) == 0: + raise ApiValueError( + "Invalid input arguments input when making an instance of " + "class %s. Not all inputs were used. The unused input data " + "is %s" % (self.__class__.__name__, unused_args) + ) + for var_name, var_value in six.iteritems(unused_args): + for instance in additional_properties_model_instances: + setattr(instance, var_name, var_value) # no need to add additional_properties to var_name_to_model_instances here # because additional_properties_model_instances will direct us to that # instance when we use getattr or setattr @@ -1187,6 +1135,5 @@ def validate_get_composed_info(constant_args, model_args, self): return [ composed_instances, var_name_to_model_instances, - additional_properties_model_instances, - unused_args + additional_properties_model_instances ] diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache index a56bedffbf..eb358efd5b 100644 --- a/python-experimental/requirements.mustache +++ b/python-experimental/requirements.mustache @@ -1,4 +1,3 @@ -nulltype certifi >= 14.05.14 future; python_version<="2.7" six >= 1.10 diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 796475c456..2fe84efcee 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -21,7 +21,6 @@ REQUIRES = [ "six >= 1.10", "certifi", "python-dateutil", - "nulltype", {{#asyncio}} "aiohttp >= 3.0.0", {{/asyncio}} diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index 0be0e1c467..300efa007b 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -7,12 +7,13 @@ from Crypto.IO import PEM, PKCS8 from Crypto.Hash import SHA256, SHA512 from Crypto.PublicKey import RSA, ECC from Crypto.Signature import PKCS1_v1_5, pss, DSS +from datetime import datetime from email.utils import formatdate import json import os import re from six.moves.urllib.parse import urlencode, urlparse -from time import time +from time import mktime # The constants below define a subset of HTTP headers that can be included in the # HTTP signature scheme. Additional headers may be included in the signature. @@ -53,10 +54,6 @@ ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS = { ALGORITHM_ECDSA_MODE_DETERMINISTIC_RFC6979 } -# The cryptographic hash algorithm for the message signature. -HASH_SHA256 = 'sha256' -HASH_SHA512 = 'sha512' - class HttpSigningConfiguration(object): """The configuration parameters for the HTTP signature security scheme. @@ -102,15 +99,9 @@ class HttpSigningConfiguration(object): Supported values are: 1. For RSA keys: RSASSA-PSS, RSASSA-PKCS1-v1_5. 2. For ECDSA keys: fips-186-3, deterministic-rfc6979. - If None, the signing algorithm is inferred from the private key. - The default signing algorithm for RSA keys is RSASSA-PSS. - The default signing algorithm for ECDSA keys is fips-186-3. - :param hash_algorithm: The hash algorithm for the signature. Supported values are - sha256 and sha512. - If the signing_scheme is rsa-sha256, the hash algorithm must be set - to None or sha256. - If the signing_scheme is rsa-sha512, the hash algorithm must be set - to None or sha512. + The default value is inferred from the private key. + The default value for RSA keys is RSASSA-PSS. + The default value for ECDSA keys is fips-186-3. :param signature_max_validity: The signature max validity, expressed as a datetime.timedelta value. It must be a positive value. """ @@ -118,7 +109,6 @@ class HttpSigningConfiguration(object): private_key_passphrase=None, signed_headers=None, signing_algorithm=None, - hash_algorithm=None, signature_max_validity=None): self.key_id = key_id if signing_scheme not in {SCHEME_HS2019, SCHEME_RSA_SHA256, SCHEME_RSA_SHA512}: @@ -129,24 +119,6 @@ class HttpSigningConfiguration(object): self.private_key_path = private_key_path self.private_key_passphrase = private_key_passphrase self.signing_algorithm = signing_algorithm - self.hash_algorithm = hash_algorithm - if signing_scheme == SCHEME_RSA_SHA256: - if self.hash_algorithm is None: - self.hash_algorithm = HASH_SHA256 - elif self.hash_algorithm != HASH_SHA256: - raise Exception("Hash algorithm must be sha256 when security scheme is %s" % - SCHEME_RSA_SHA256) - elif signing_scheme == SCHEME_RSA_SHA512: - if self.hash_algorithm is None: - self.hash_algorithm = HASH_SHA512 - elif self.hash_algorithm != HASH_SHA512: - raise Exception("Hash algorithm must be sha512 when security scheme is %s" % - SCHEME_RSA_SHA512) - elif signing_scheme == SCHEME_HS2019: - if self.hash_algorithm is None: - self.hash_algorithm = HASH_SHA256 - elif self.hash_algorithm not in {HASH_SHA256, HASH_SHA512}: - raise Exception("Invalid hash algorithm") if signature_max_validity is not None and signature_max_validity.total_seconds() < 0: raise Exception("The signature max validity must be a positive value") self.signature_max_validity = signature_max_validity @@ -256,6 +228,12 @@ class HttpSigningConfiguration(object): "Signing algorithm {0} is not compatible with private key".format( self.signing_algorithm)) + def _get_unix_time(self, ts): + """Converts and returns a datetime object to UNIX time, the number of seconds + elapsed since January 1, 1970 UTC. + """ + return (ts - datetime(1970, 1, 1)).total_seconds() + def _get_signed_header_info(self, resource_path, method, headers, body, query_params): """Build the HTTP headers (name, value) that need to be included in the HTTP signature scheme. @@ -284,16 +262,15 @@ class HttpSigningConfiguration(object): if query_params: request_target += "?" + urlencode(query_params) - # Get UNIX time, e.g. seconds since epoch, not including leap seconds. - now = time() - # Format date per RFC 7231 section-7.1.1.2. An example is: - # Date: Wed, 21 Oct 2015 07:28:00 GMT - cdate = formatdate(timeval=now, localtime=False, usegmt=True) + # Get current time and generate RFC 1123 (HTTP/1.1) date/time string. + now = datetime.now() + stamp = mktime(now.timetuple()) + cdate = formatdate(timeval=stamp, localtime=False, usegmt=True) # The '(created)' value MUST be a Unix timestamp integer value. # Subsecond precision is not supported. - created = int(now) + created = int(self._get_unix_time(now)) if self.signature_max_validity is not None: - expires = now + self.signature_max_validity.total_seconds() + expires = self._get_unix_time(now + self.signature_max_validity) signed_headers_list = [] request_headers_dict = {} @@ -338,14 +315,14 @@ class HttpSigningConfiguration(object): The prefix is a string that identifies the cryptographc hash. It is used to generate the 'Digest' header as specified in RFC 3230. """ - if self.hash_algorithm == HASH_SHA512: + if self.signing_scheme in {SCHEME_RSA_SHA512, SCHEME_HS2019}: digest = SHA512.new() prefix = 'SHA-512=' - elif self.hash_algorithm == HASH_SHA256: + elif self.signing_scheme == SCHEME_RSA_SHA256: digest = SHA256.new() prefix = 'SHA-256=' else: - raise Exception("Unsupported hash algorithm: {0}".format(self.hash_algorithm)) + raise Exception("Unsupported signing algorithm: {0}".format(self.signing_scheme)) digest.update(data) return digest, prefix @@ -369,10 +346,7 @@ class HttpSigningConfiguration(object): if sig_alg is None: sig_alg = ALGORITHM_ECDSA_MODE_FIPS_186_3 if sig_alg in ALGORITHM_ECDSA_KEY_SIGNING_ALGORITHMS: - # draft-ietf-httpbis-message-signatures-00 does not specify the ECDSA encoding. - # Issue: https://github.com/w3c-ccg/http-signatures/issues/107 - signature = DSS.new(key=self.private_key, mode=sig_alg, - encoding='der').sign(digest) + signature = DSS.new(self.private_key, sig_alg).sign(digest) else: raise Exception("Unsupported signature algorithm: {0}".format(sig_alg)) else: diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index d8cfc4ad11..9f5b49f821 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -45,7 +45,4 @@ configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' configuration.access_token = 'YOUR_ACCESS_TOKEN' {{/isOAuth}} {{/authMethods}} - -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" {{/hasAuthMethods}} diff --git a/travis.mustache b/travis.mustache index 195488737d..388de83128 100644 --- a/travis.mustache +++ b/travis.mustache @@ -10,13 +10,6 @@ python: - "3.7" - "3.8" # command to install dependencies -install: - - "pip install -r requirements.txt" - - "pip install -r test-requirements.txt" +install: "pip install -r requirements.txt" # command to run tests -{{#useNose}} script: nosetests -{{/useNose}} -{{^useNose}} -script: pytest --cov={{{packageName}}} -{{/useNose}} From 1d3d5233bcbb969e6d1f28659d18a530c6289c05 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 23 Apr 2020 22:59:31 -0700 Subject: [PATCH 100/180] [python-experimental] Minor doc update, code comments and exception handling (#5945) * add support for any type, i.e. when 'type' attribute is not specified in OAS schema * fix typos, add code comments * Handle case when 'type' attribute is not present in the OAS schema * fix python formatting rule * fix python formatting rule * remove 'object' as a type --- python-experimental/model_utils.mustache | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 8b60618c1d..58da408a19 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -74,7 +74,7 @@ COERCION_INDEX_BY_TYPE = { ModelComposed: 0, ModelNormal: 1, ModelSimple: 2, - none_type: 3, + none_type: 3, # The type of 'None'. list: 4, dict: 5, float: 6, @@ -83,7 +83,7 @@ COERCION_INDEX_BY_TYPE = { datetime: 9, date: 10, str: 11, - file_type: 12, + file_type: 12, # 'file_type' is an alias for the built-in 'file' or 'io.IOBase' type. } # these are used to limit what type conversions we try to do @@ -352,11 +352,11 @@ def order_response_types(required_types): Args: required_types (list/tuple): collection of classes or instance of - list or dict with classs information inside it + list or dict with class information inside it. Returns: (list): coercion order sorted collection of classes or instance - of list or dict with classs information inside it + of list or dict with class information inside it. """ def index_getter(class_or_instance): @@ -373,7 +373,9 @@ def order_response_types(required_types): elif (inspect.isclass(class_or_instance) and issubclass(class_or_instance, ModelSimple)): return COERCION_INDEX_BY_TYPE[ModelSimple] - return COERCION_INDEX_BY_TYPE[class_or_instance] + elif class_or_instance in COERCION_INDEX_BY_TYPE: + return COERCION_INDEX_BY_TYPE[class_or_instance] + raise ApiValueError("Unsupported type: %s" % class_or_instance) sorted_types = sorted( required_types, @@ -391,7 +393,7 @@ def remove_uncoercible(required_types_classes, current_item, from_server, these should be ordered by COERCION_INDEX_BY_TYPE from_server (bool): a boolean of whether the data is from the server if false, the data is from the client - current_item (any): the current item to be converted + current_item (any): the current item (input data) to be converted Keyword Args: must_convert (bool): if True the item to convert is of the wrong From c72785752643dbd47ad235817b11e72a491c2b42 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 23 Apr 2020 23:16:31 -0700 Subject: [PATCH 101/180] [Python experimental] Add __setattr__ function to ensure signing_info.host is the same as configuration.host when the user assigns signing info (#6033) * Add __setattr__ function to ensure signing_info.host is the same as configuration.host when the user assigns signing info * Add __setattr__ function to ensure signing_info.host is the same as configuration.host when the user assigns signing info --- configuration.mustache | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index 6581e603ad..7fdcd89427 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -271,6 +271,15 @@ class Configuration(object): result.debug = self.debug return result + def __setattr__(self, name, value): + object.__setattr__(self, name, value) +{{#hasHttpSignatureMethods}} + if name == "signing_info" and value is not None: + # Ensure the host paramater from signing info is the same as + # Configuration.host. + value.host = self.host +{{/hasHttpSignatureMethods}} + @classmethod def set_default(cls, default): """Set default instance of configuration. From deecddb4a25b612e54e47941dade989759719d72 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 24 Apr 2020 09:01:02 -0700 Subject: [PATCH 102/180] [CORE] Fixes composed schema discriminator map (#4906) * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Adds updates from Sebastien Rosset * Removes newlines * Uses df.isString * Fixes tests be correctly setting df.isString * Updates discriminatorExplicitMappingVerbose description per PR feedback * Adds description of how mappedModels is populated * Adds the suggestion exception raising when a MappedModel mappingName is null * Actually resolves merge conflicts * Switches two methods to package private because they are needed for testing * Allow nulls in MappedModel.getMappingName * Updates CLI flag name to legacyDiscriminatorBehavior, default=true Co-authored-by: William Cheng --- api_client.mustache | 9 ++++++--- model.mustache | 5 +++-- .../model_templates/classvars.mustache | 16 ++++++---------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index c69e7d5945..de25b7cf97 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -643,9 +643,12 @@ class ApiClient(object): :param klass: class literal. :return: model object. """ + has_discriminator = False + if (hasattr(klass, 'get_real_child_model') + and klass.discriminator_value_class_map): + has_discriminator = True - if not klass.openapi_types and not hasattr(klass, - 'get_real_child_model'): + if not klass.openapi_types and has_discriminator is False: return data kwargs = {} @@ -659,7 +662,7 @@ class ApiClient(object): instance = klass(**kwargs) - if hasattr(instance, 'get_real_child_model'): + if has_discriminator: klass_name = instance.get_real_child_model(data) if klass_name: instance = self.__deserialize(data, klass_name) diff --git a/model.mustache b/model.mustache index 70f6e7489a..112246604d 100644 --- a/model.mustache +++ b/model.mustache @@ -52,8 +52,9 @@ class {{classname}}(object): {{#discriminator}} discriminator_value_class_map = { - {{#children}}'{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}}, - {{/-last}}{{/children}} +{{#children}} + '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} +{{/children}} } {{/discriminator}} diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 60fff484ef..8b49e58edb 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -115,15 +115,11 @@ @staticmethod def discriminator(): - return {{^discriminator}}None{{/discriminator}}{{#discriminator}}{ - '{{{discriminatorName}}}': { -{{#children}} - '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': {{{classname}}}, -{{/children}} -{{^children}} + {{^discriminator}}return None{{/discriminator}}{{#discriminator}}val = { {{#mappedModels}} - '{{mappingName}}': {{{modelName}}}, + '{{mappingName}}': {{{modelName}}}, {{/mappedModels}} -{{/children}} - }, - }{{/discriminator}} \ No newline at end of file + } + if not val: + return None + return {'{{{discriminatorName}}}': val}{{/discriminator}} \ No newline at end of file From 6f5e0b5ed9a739d56baec8ac5af25de8a0335fe7 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 24 Apr 2020 09:10:32 -0700 Subject: [PATCH 103/180] [Python experimental] Readme improvements (#6031) * Python experimental readme improvements * Python experimental readme improvements * execute scripts in bin directory --- common_README.mustache | 4 +- configuration.mustache | 56 +++++----- python-experimental/README_common.mustache | 4 +- python_doc_auth_partial.mustache | 116 ++++++++++++++++----- 4 files changed, 123 insertions(+), 57 deletions(-) diff --git a/common_README.mustache b/common_README.mustache index 991002aa17..37060d6d1f 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -1,13 +1,13 @@ ```python from __future__ import print_function +{{#apiInfo}}{{#apis}}{{^hasMore}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/hasMore}}{{/apis}}{{/apiInfo}} import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException from pprint import pprint {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} {{> python_doc_auth_partial}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" + # Enter a context with an instance of the API client with {{{packageName}}}.ApiClient(configuration) as api_client: # Create an instance of the API class diff --git a/configuration.mustache b/configuration.mustache index 7fdcd89427..dceab63e67 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -62,10 +62,12 @@ class Configuration(object): name: JSESSIONID # cookie name You can programmatically set the cookie: - conf = {{{packageName}}}.Configuration( - api_key={'cookieAuth': 'abc123'} - api_key_prefix={'cookieAuth': 'JSESSIONID'} - ) + +conf = {{{packageName}}}.Configuration( + api_key={'cookieAuth': 'abc123'} + api_key_prefix={'cookieAuth': 'JSESSIONID'} +) + The following cookie will be added to the HTTP request: Cookie: JSESSIONID abc123 {{/hasApiKeyMethods}} @@ -80,10 +82,12 @@ class Configuration(object): scheme: basic Configure API client with HTTP basic authentication: - conf = {{{packageName}}}.Configuration( - username='the-user', - password='the-password', - ) + +conf = {{{packageName}}}.Configuration( + username='the-user', + password='the-password', +) + {{/hasHttpBasicMethods}} {{#hasHttpSignatureMethods}} @@ -107,24 +111,24 @@ class Configuration(object): load balancers may add/modify/remove headers. Include the HTTP headers that you know are not going to be modified in transit. - conf = {{{packageName}}}.Configuration( - signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( - key_id = 'my-key-id', - private_key_path = 'rsa.pem', - signing_scheme = signing.SCHEME_HS2019, - signing_algorithm = signing.ALGORITHM_RSASSA_PSS, - signed_headers = [signing.HEADER_REQUEST_TARGET, - signing.HEADER_CREATED, - signing.HEADER_EXPIRES, - signing.HEADER_HOST, - signing.HEADER_DATE, - signing.HEADER_DIGEST, - 'Content-Type', - 'User-Agent' - ], - signature_max_validity = datetime.timedelta(minutes=5) - ) - ) +conf = {{{packageName}}}.Configuration( + signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( + key_id = 'my-key-id', + private_key_path = 'rsa.pem', + signing_scheme = {{{packageName}}}.signing.SCHEME_HS2019, + signing_algorithm = {{{packageName}}}.signing.ALGORITHM_RSASSA_PSS, + signed_headers = [{{{packageName}}}.signing.HEADER_REQUEST_TARGET, + {{{packageName}}}.signing.HEADER_CREATED, + {{{packageName}}}.signing.HEADER_EXPIRES, + {{{packageName}}}.signing.HEADER_HOST, + {{{packageName}}}.signing.HEADER_DATE, + {{{packageName}}}.signing.HEADER_DIGEST, + 'Content-Type', + 'User-Agent' + ], + signature_max_validity = datetime.timedelta(minutes=5) + ) +) {{/hasHttpSignatureMethods}} {{/hasAuthMethods}} """ diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index b474eb264a..7d9811fdfb 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -1,12 +1,12 @@ ```python from __future__ import print_function +{{#apiInfo}}{{#apis}}{{^hasMore}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/hasMore}}{{/apis}}{{/apiInfo}} import time import {{{packageName}}} from pprint import pprint {{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} {{> python_doc_auth_partial}} -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" + # Enter a context with an instance of the API client with {{{packageName}}}.ApiClient(configuration) as api_client: # Create an instance of the API class diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index d8cfc4ad11..3086d770b1 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -1,51 +1,113 @@ +# Defining the host is optional and defaults to {{{basePath}}} +# See configuration.py for a list of all supported configuration parameters. +configuration = {{{packageName}}}.Configuration( + host = "{{{basePath}}}" +) + {{#hasAuthMethods}} +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. {{#authMethods}} -configuration = {{{packageName}}}.Configuration() {{#isBasic}} {{#isBasicBasic}} + # Configure HTTP basic authorization: {{{name}}} -configuration.username = 'YOUR_USERNAME' -configuration.password = 'YOUR_PASSWORD' +configuration = {{{packageName}}}.Configuration( + username = 'YOUR_USERNAME', + password = 'YOUR_PASSWORD' +) {{/isBasicBasic}} {{#isBasicBearer}} + # Configure Bearer authorization{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}: {{{name}}} -configuration.access_token = 'YOUR_BEARER_TOKEN' +configuration = {{{packageName}}}.Configuration( + access_token = 'YOUR_BEARER_TOKEN' +) {{/isBasicBearer}} {{#isHttpSignature}} -# Configure HTTP signature authorization: {{{name}}} -# You can specify the signing key-id, private key path, signing scheme, signing algorithm, -# list of signed headers and signature max validity. -configuration.signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( - key_id = 'my-key-id', - private_key_path = 'rsa.pem', - signing_scheme = signing.SCHEME_HS2019, - signing_algorithm = signing.ALGORITHM_RSASSA_PSS, - signed_headers = [signing.HEADER_REQUEST_TARGET, - signing.HEADER_CREATED, - signing.HEADER_EXPIRES, - signing.HEADER_HOST, - signing.HEADER_DATE, - signing.HEADER_DIGEST, - 'Content-Type', - 'Content-Length', - 'User-Agent' - ], - signature_max_validity = datetime.timedelta(minutes=5) + +# Configure HTTP message signature: {{{name}}} +# The HTTP Signature Header mechanism that can be used by a client to +# authenticate the sender of a message and ensure that particular headers +# have not been modified in transit. +# +# You can specify the signing key-id, private key path, signing scheme, +# signing algorithm, list of signed headers and signature max validity. +# The 'key_id' parameter is an opaque string that the API server can use +# to lookup the client and validate the signature. +# The 'private_key_path' parameter should be the path to a file that +# contains a DER or base-64 encoded private key. +# The 'private_key_passphrase' parameter is optional. Set the passphrase +# if the private key is encrypted. +# The 'signed_headers' parameter is used to specify the list of +# HTTP headers included when generating the signature for the message. +# You can specify HTTP headers that you want to protect with a cryptographic +# signature. Note that proxies may add, modify or remove HTTP headers +# for legitimate reasons, so you should only add headers that you know +# will not be modified. For example, if you want to protect the HTTP request +# body, you can specify the Digest header. In that case, the client calculates +# the digest of the HTTP request body and includes the digest in the message +# signature. +# The 'signature_max_validity' parameter is optional. It is configured as a +# duration to express when the signature ceases to be valid. The client calculates +# the expiration date every time it generates the cryptographic signature +# of an HTTP request. The API server may have its own security policy +# that controls the maximum validity of the signature. The client max validity +# must be lower than the server max validity. +# The time on the client and server must be synchronized, otherwise the +# server may reject the client signature. +# +# The client must use a combination of private key, signing scheme, +# signing algorithm and hash algorithm that matches the security policy of +# the API server. +# +# See {{{packageName}}}.signing for a list of all supported parameters. +configuration = {{{packageName}}}.Configuration( + host = "{{{basePath}}}", + signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( + key_id = 'my-key-id', + private_key_path = 'private_key.pem', + private_key_passphrase = 'YOUR_PASSPHRASE', + signing_scheme = {{{packageName}}}.signing.SCHEME_HS2019, + signing_algorithm = {{{packageName}}}.signing.ALGORITHM_ECDSA_MODE_FIPS_186_3, + hash_algorithm = {{{packageName}}}.signing.SCHEME_RSA_SHA256, + signed_headers = [ + {{{packageName}}}.signing.HEADER_REQUEST_TARGET, + {{{packageName}}}.signing.HEADER_CREATED, + {{{packageName}}}.signing.HEADER_EXPIRES, + {{{packageName}}}.signing.HEADER_HOST, + {{{packageName}}}.signing.HEADER_DATE, + {{{packageName}}}.signing.HEADER_DIGEST, + 'Content-Type', + 'Content-Length', + 'User-Agent' + ], + signature_max_validity = datetime.timedelta(minutes=5) + ) ) {{/isHttpSignature}} {{/isBasic}} {{#isApiKey}} + # Configure API key authorization: {{{name}}} -configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY' +configuration = {{{packageName}}}.Configuration( + host = "{{{basePath}}}", + api_key = { + '{{{keyParamName}}}': 'YOUR_API_KEY' + } +) # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer' {{/isApiKey}} {{#isOAuth}} + # Configure OAuth2 access token for authorization: {{{name}}} +configuration = {{{packageName}}}.Configuration( + host = "{{{basePath}}}" +) configuration.access_token = 'YOUR_ACCESS_TOKEN' {{/isOAuth}} {{/authMethods}} - -# Defining host is optional and default to {{{basePath}}} -configuration.host = "{{{basePath}}}" {{/hasAuthMethods}} From fa5f7e53df7ecd50ccacea3e4aacc93dbee2e309 Mon Sep 17 00:00:00 2001 From: Justin Niessner Date: Sun, 26 Apr 2020 16:33:42 -0400 Subject: [PATCH 104/180] [Python] Fix Python UTF-8 Encoding Issue (#5679) * Try decoding but don't bail on error * Switch binary and ByteArray to bytes * Read content type and parse appropriately * Remove response parsing * Remove response parsing and just return the data * Update petshop examples w/ new generator code * Fix copy/paste error with naming * Update petstore examples * Move response decoding to inside _preload_content block * Update the clients again * Use a raw string for the regex pattern * Regenerate petstore clients * Add bytes to python primitives as it's supported in 2.7 and 3 * Add bytes to the exports from model_utils * Import bytes from model_utils * Add conditional typing for regex pattern to match variable type * Regenerate petstore clients * Use read() instead of text() for asyncio * Regenerate petstore clients * Remove unused six import * Regenerate petstore clients * Add newline to kick Circle to re-run * Remove whitespace from tox.ini * Update more examples after ensure_updated * Add sample updates that didn't run with the --batch flag * Remove extra bracket in regex to remove warning * Stop printing debug messages * Add bytes examples to python doc generators * Update generated FakeApi docs * Regenerate api_client.py * Remove print statements from generated clients * Update bytes example in FakeApi.md. Again. I swear. * Add yet another seemingly missing doc update * Catch the error, decode the body, and re-throw * Remove the updates now that the change is non-breaking * Regenerate client * Add bytes deserialization test * Update exception parsing * Add exception parsing for python-experimental * Regenerate client with minor changes * Revert test changes * Regenerate model_utils.py * Update confusing test name * Remove bytes from mapping and examples * Add back in the old binary/ByteArray to str mapping * Update docs and api_client template * Add experimental api_client changes * Regenerate samples again * Add Tornado handling to early return * Try fixing Tornado python returns * More documentation changes * Re-generate the client code * Remove bytes from test_format_test * Remove more leftover bytes usages * Switch bytes validation back to string * Fix format_test template and regenerate * Remove unused bytes var * Remove bytes import from models and regenerate * Remove bytes import from test_deserialization * Reduce nested ifs * Remove byte logic for now * Regenerate client after latest changes * Remove another bytes usage * Regenerate after removing dangling byte string usage * Reduce the scope of the try/catch in api_client * Regenerate after try/catch cleanup * Swap catch for except * Regenerate Python client after api_client change * Fix lint error on the generated api_client * Add binary format test back in w/ string * Add decoding to python-experimental and regenerate * Import re into python-experimental api_client * Ensure file upload json response is utf-8 encoded bytes --- api_client.mustache | 47 ++++++++++++++------ asyncio/rest.mustache | 2 +- python-experimental/api_client.mustache | 57 +++++++++++++++++-------- rest.mustache | 5 --- tornado/rest.mustache | 7 +-- 5 files changed, 76 insertions(+), 42 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index de25b7cf97..66d3577f3c 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -22,7 +22,7 @@ import tornado.gen from {{packageName}}.configuration import Configuration import {{modelPackage}} from {{packageName}} import rest -from {{packageName}}.exceptions import ApiValueError +from {{packageName}}.exceptions import ApiValueError, ApiException class ApiClient(object): @@ -186,22 +186,43 @@ class ApiClient(object): # use server/host defined in path or operation instead url = _host + resource_path - # perform request and return response - response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( - method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, - _preload_content=_preload_content, - _request_timeout=_request_timeout) + try: + # perform request and return response + response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + except ApiException as e: + e.body = e.body.decode('utf-8') if six.PY3 else e.body + raise e + + content_type = response_data.getheader('content-type') self.last_response = response_data return_data = response_data - if _preload_content: - # deserialize response data - if response_type: - return_data = self.deserialize(response_data, response_type) - else: - return_data = None + + if not _preload_content: + {{^tornado}} + return return_data + {{/tornado}} + {{#tornado}} + raise tornado.gen.Return(return_data) + {{/tornado}} + + if six.PY3 and response_type not in ["file", "bytes"]: + match = None + if content_type is not None: + match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) + encoding = match.group(1) if match else "utf-8" + response_data.data = response_data.data.decode(encoding) + + # deserialize response data + if response_type: + return_data = self.deserialize(response_data, response_type) + else: + return_data = None {{^tornado}} if _return_http_data_only: diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index f2099c7531..44531fce5a 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -166,7 +166,7 @@ class RESTClientObject(object): r = await self.pool_manager.request(**args) if _preload_content: - data = await r.text() + data = await r.read() r = RESTResponse(r, data) # log response body diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 774dae89c6..5285a7b806 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -7,6 +7,7 @@ import atexit import mimetypes from multiprocessing.pool import ThreadPool import os +import re # python 2 and python 3 compatibility library import six @@ -17,7 +18,7 @@ import tornado.gen from {{packageName}} import rest from {{packageName}}.configuration import Configuration -from {{packageName}}.exceptions import ApiValueError +from {{packageName}}.exceptions import ApiValueError, ApiException from {{packageName}}.model_utils import ( ModelNormal, ModelSimple, @@ -176,26 +177,48 @@ class ApiClient(object): # use server/host defined in path or operation instead url = _host + resource_path - # perform request and return response - response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( - method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, - _preload_content=_preload_content, - _request_timeout=_request_timeout) + try: + # perform request and return response + response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( + method, url, query_params=query_params, headers=header_params, + post_params=post_params, body=body, + _preload_content=_preload_content, + _request_timeout=_request_timeout) + except ApiException as e: + e.body = e.body.decode('utf-8') if six.PY3 else e.body + raise e + + content_type = response_data.getheader('content-type') self.last_response = response_data return_data = response_data - if _preload_content: - # deserialize response data - if response_type: - return_data = self.deserialize( - response_data, - response_type, - _check_type - ) - else: - return_data = None + + if not _preload_content: + {{^tornado}} + return (return_data) + {{/tornado}} + {{#tornado}} + raise tornado.gen.Return(return_data) + {{/tornado}} + return return_data + + if six.PY3 and response_type not in ["file", "bytes"]: + match = None + if content_type is not None: + match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) + encoding = match.group(1) if match else "utf-8" + response_data.data = response_data.data.decode(encoding) + + # deserialize response data + if response_type: + return_data = self.deserialize( + response_data, + response_type, + _check_type + ) + else: + return_data = None {{^tornado}} if _return_http_data_only: diff --git a/rest.mustache b/rest.mustache index 772efe91b3..fe7abfdfc0 100644 --- a/rest.mustache +++ b/rest.mustache @@ -209,11 +209,6 @@ class RESTClientObject(object): if _preload_content: r = RESTResponse(r) - # In the python 3, the response.data is bytes. - # we need to decode it to string. - if six.PY3: - r.data = r.data.decode('utf8') - # log response body logger.debug("response body: %s", r.data) diff --git a/tornado/rest.mustache b/tornado/rest.mustache index e7a760f370..2679760ea5 100644 --- a/tornado/rest.mustache +++ b/tornado/rest.mustache @@ -8,7 +8,6 @@ import logging import re # python 2 and python 3 compatibility library -import six from six.moves.urllib.parse import urlencode import tornado import tornado.gen @@ -28,11 +27,7 @@ class RESTResponse(io.IOBase): self.reason = resp.reason if resp.body: - # In Python 3, the response body is utf-8 encoded bytes. - if six.PY3: - self.data = resp.body.decode('utf-8') - else: - self.data = resp.body + self.data = resp.body else: self.data = None From e7ba20df13cedd7cbe3b2bae43aa1bb59c11a9b5 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 3 May 2020 11:44:04 -0700 Subject: [PATCH 105/180] Adds memoization and deserialization through 2 or more discriminators (#6124) * Adds cached_property decorator, adds feature to move through n discriminators * Adds v3 sample with 2 discriminators * Adds tests of Shape, Tringle, and Quadrilateral traveling through 2 discriminators * Adds test_deserialization.py:test_deserialize_shape * Simplifes XTriangle sample spec schemas * Simplifies Shape schema definition, updates go+python-experimental samples * Fixes python-experimental test_dog tests * Separates off python-experimental spec --- python-experimental/model.mustache | 3 + .../model_templates/classvars.mustache | 4 +- .../method_discriminator.mustache | 6 +- .../method_init_composed.mustache | 2 + .../method_init_normal.mustache | 1 + .../method_init_shared.mustache | 21 ++- .../method_set_attribute.mustache | 5 +- .../model_templates/model_composed.mustache | 2 +- .../model_templates/model_normal.mustache | 4 +- .../model_templates/model_simple.mustache | 4 +- python-experimental/model_utils.mustache | 161 ++++++++++++------ 11 files changed, 142 insertions(+), 71 deletions(-) diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index ef7da57282..9afb17b527 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -13,6 +13,9 @@ from {{packageName}}.model_utils import ( # noqa: F401 ModelComposed, ModelNormal, ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, date, datetime, file_type, diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 8b49e58edb..fe54e34f5b 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -94,7 +94,7 @@ additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} - @staticmethod + @cached_property def openapi_types(): """ This must be a class method so a model may have properties that are @@ -113,7 +113,7 @@ {{/optionalVars}} } - @staticmethod + @cached_property def discriminator(): {{^discriminator}}return None{{/discriminator}}{{#discriminator}}val = { {{#mappedModels}} diff --git a/python-experimental/model_templates/method_discriminator.mustache b/python-experimental/model_templates/method_discriminator.mustache index c4baa722ff..de06fb461e 100644 --- a/python-experimental/model_templates/method_discriminator.mustache +++ b/python-experimental/model_templates/method_discriminator.mustache @@ -1,10 +1,10 @@ @classmethod - def get_discriminator_class(cls, from_server, data): + def get_discriminator_class(cls, data): """Returns the child class specified by the discriminator""" - discriminator = cls.discriminator() + discriminator = cls.discriminator discr_propertyname_py = list(discriminator.keys())[0] discr_propertyname_js = cls.attribute_map[discr_propertyname_py] - if from_server: + if discr_propertyname_js in data: class_name = data[discr_propertyname_js] else: class_name = data[discr_propertyname_py] diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index e00bf129b2..a5d948f0dd 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -4,6 +4,7 @@ '_from_server', '_path_to_item', '_configuration', + '_visited_composed_classes', '_composed_instances', '_var_name_to_model_instances', '_additional_properties_model_instances', @@ -16,6 +17,7 @@ '_path_to_item': _path_to_item, '_from_server': _from_server, '_configuration': _configuration, + '_visited_composed_classes': self._visited_composed_classes, } required_args = { {{#requiredVars}} diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index d26506c56c..8433c49f2f 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -4,6 +4,7 @@ '_from_server', '_path_to_item', '_configuration', + '_visited_composed_classes', ]) {{> python-experimental/model_templates/method_init_shared }} diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 9dd5bc2b6f..1631d57eec 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,4 +1,5 @@ - def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, **kwargs): # noqa: E501 + @convert_js_args_to_python_args + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI {{#requiredVars}} @@ -31,6 +32,21 @@ deserializing a file_type parameter. If passed, type conversion is attempted If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) {{#optionalVars}} {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 {{/optionalVars}} @@ -40,4 +56,5 @@ self._check_type = _check_type self._from_server = _from_server self._path_to_item = _path_to_item - self._configuration = _configuration \ No newline at end of file + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) \ No newline at end of file diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache index bcafb71368..f4a36e42f2 100644 --- a/python-experimental/model_templates/method_set_attribute.mustache +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -6,9 +6,8 @@ path_to_item.extend(self._path_to_item) path_to_item.append(name) - openapi_types = self.openapi_types() - if name in openapi_types: - required_types_mixed = openapi_types[name] + if name in self.openapi_types: + required_types_mixed = self.openapi_types[name] elif self.additional_properties_type is None: raise ApiKeyError( "{0} has no key '{1}'".format(type(self).__name__, name), diff --git a/python-experimental/model_templates/model_composed.mustache b/python-experimental/model_templates/model_composed.mustache index d53d89cef2..002b2a5789 100644 --- a/python-experimental/model_templates/model_composed.mustache +++ b/python-experimental/model_templates/model_composed.mustache @@ -26,7 +26,7 @@ class {{unescapedDescription}}(ModelComposed): {{> python-experimental/model_templates/method_init_composed }} - @staticmethod + @cached_property def _composed_schemas(): # we need this here to make our import statements work # we must store _composed_schemas in here so the code is only run diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache index 8bfe6ada48..f9d82ef2a8 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/python-experimental/model_templates/model_normal.mustache @@ -24,9 +24,7 @@ class {{unescapedDescription}}(ModelNormal): {{/optionalVars}} } - @staticmethod - def _composed_schemas(): - return None + _composed_schemas = {} {{> python-experimental/model_templates/method_init_normal}}{{#discriminator}} diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index 465918dfa5..95b8a81715 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -11,8 +11,6 @@ class {{unescapedDescription}}(ModelSimple): {{> python-experimental/model_templates/classvars }} - @staticmethod - def _composed_schemas(): - return None + _composed_schemas = None {{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 58da408a19..e6b1df6b0e 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -35,6 +35,24 @@ else: from builtins import int, str +class cached_property(object): + # this caches the result of the function call for fn with no inputs + # use this as a decorator on fuction methods that you want converted + # into cached properties + result_key = '_results' + + def __init__(self, fn): + self._fn = fn + + def __get__(self, instance, cls=None): + try: + return vars(self)[self.result_key] + except KeyError: + result = self._fn() + setattr(self, self.result_key, result) + return result + + class OpenApiModel(object): """The base class for all OpenAPIModels""" @@ -42,6 +60,55 @@ class OpenApiModel(object): {{> python-experimental/model_templates/methods_shared }} + def __new__(cls, *args, **kwargs): + # this function uses the discriminator to + # pick a new schema/class to instantiate because a discriminator + # propertyName value was passed in + + visited_composed_classes = kwargs.get('_visited_composed_classes', ()) + if ( + cls.discriminator is None or + cls in visited_composed_classes + ): + # we don't have a discriminator + # or we have already visited this class before and are sure that we + # want to instantiate it this time + return super(OpenApiModel, cls).__new__(cls) + + oneof_anyof_classes = [] + oneof_anyof_classes.extend(cls._composed_schemas.get('oneOf', ())) + oneof_anyof_classes.extend(cls._composed_schemas.get('anyOf', ())) + new_cls = cls.get_discriminator_class(kwargs) + if new_cls is None: + disc_prop_name_py = list(cls.discriminator.keys())[0] + disc_prop_name_js = cls.attribute_map[disc_prop_name_py] + path_to_item = kwargs.get('_path_to_item', ()) + disc_prop_value = kwargs.get( + disc_prop_name_js, kwargs.get(disc_prop_name_py)) + raise ApiValueError( + "Cannot deserialize input data due to invalid discriminator " + "value. The OpenAPI document has no mapping for discriminator " + "property '%s'='%s' at path: %s" % + (disc_prop_name_js, disc_prop_value, path_to_item) + ) + + if new_cls in visited_composed_classes: + # if we are coming from the chosen new_cls use cls instead + return super(OpenApiModel, cls).__new__(cls) + + oneof_anyof_child = new_cls in oneof_anyof_classes + kwargs['_visited_composed_classes'] = visited_composed_classes + (cls,) + + if cls._composed_schemas.get('allOf') and oneof_anyof_child: + # validate that we can make self because when we make the + # new_cls it will not include the allOf validations in self + self_inst = super(OpenApiModel, cls).__new__(cls) + self_inst.__init__(*args, **kwargs) + + new_inst = new_cls.__new__(new_cls, *args, **kwargs) + new_inst.__init__(*args, **kwargs) + return new_inst + class ModelSimple(OpenApiModel): """the parent class of models whose type != object in their @@ -473,10 +540,12 @@ def change_keys_js_to_python(input_dict, model_class): document). """ + if getattr(model_class, 'attribute_map', None) is None: + return input_dict output_dict = {} reversed_attr_map = {value: key for key, value in - six.iteritems(model_class.attribute_map)} - for javascript_key, value in six.iteritems(input_dict): + model_class.attribute_map.items()} + for javascript_key, value in input_dict.items(): python_key = reversed_attr_map.get(javascript_key) if python_key is None: # if the key is unknown, it is in error or it is an @@ -553,21 +622,6 @@ def deserialize_primitive(data, klass, path_to_item): ) -def fix_model_input_data(model_data, model_class): - # this is only called on classes where the input data is a dict - fixed_model_data = change_keys_js_to_python( - model_data, - model_class - ) - if model_class._composed_schemas() is not None: - for allof_class in model_class._composed_schemas()['allOf']: - fixed_model_data = change_keys_js_to_python( - fixed_model_data, - allof_class - ) - return fixed_model_data - - def deserialize_model(model_data, model_class, path_to_item, check_type, configuration, from_server): """Deserializes model_data to model instance. @@ -596,23 +650,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, _configuration=configuration, _from_server=from_server) - used_model_class = model_class - if model_class.discriminator() is not None: - used_model_class = model_class.get_discriminator_class( - from_server, model_data) - - if issubclass(used_model_class, ModelSimple): - instance = used_model_class(value=model_data, **kw_args) + if issubclass(model_class, ModelSimple): + instance = model_class(value=model_data, **kw_args) return instance if isinstance(model_data, list): - instance = used_model_class(*model_data, **kw_args) + instance = model_class(*model_data, **kw_args) if isinstance(model_data, dict): - fixed_model_data = change_keys_js_to_python( - model_data, - used_model_class - ) - kw_args.update(fixed_model_data) - instance = used_model_class(**kw_args) + kw_args.update(model_data) + instance = model_class(**kw_args) return instance @@ -833,7 +878,7 @@ def model_to_dict(model_instance, serialize=True): result = {} model_instances = [model_instance] - if model_instance._composed_schemas() is not None: + if model_instance._composed_schemas: model_instances.extend(model_instance._composed_instances) for model_instance in model_instances: for attr, value in six.iteritems(model_instance._data_store): @@ -914,6 +959,17 @@ def get_py3_class_name(input_class): return input_class.__name__ +def convert_js_args_to_python_args(fn): + from functools import wraps + @wraps(fn) + def wrapped_init(self, *args, **kwargs): + from_server = kwargs.get('_from_server', False) + if from_server: + kwargs = change_keys_js_to_python(kwargs, self.__class__) + return fn(self, *args, **kwargs) + return wrapped_init + + def get_allof_instances(self, model_args, constant_args): """ Args: @@ -927,18 +983,17 @@ def get_allof_instances(self, model_args, constant_args): composed_instances (list) """ composed_instances = [] - for allof_class in self._composed_schemas()['allOf']: - - # transform js keys to python keys in fixed_model_args - fixed_model_args = change_keys_js_to_python( - model_args, allof_class) + for allof_class in self._composed_schemas['allOf']: + # no need to handle changing js keys to python because + # for composed schemas, allof parameters are included in the + # composed schema and were changed to python keys in __new__ # extract a dict of only required keys from fixed_model_args kwargs = {} - var_names = set(allof_class.openapi_types().keys()) + var_names = set(allof_class.openapi_types.keys()) for var_name in var_names: - if var_name in fixed_model_args: - kwargs[var_name] = fixed_model_args[var_name] + if var_name in model_args: + kwargs[var_name] = model_args[var_name] # and use it to make the instance kwargs.update(constant_args) @@ -950,8 +1005,8 @@ def get_allof_instances(self, model_args, constant_args): "Invalid inputs given to generate an instance of '%s'. The " "input data was invalid for the allOf schema '%s' in the composed " "schema '%s'. Error=%s" % ( - allof_class.__class__.__name__, - allof_class.__class__.__name__, + allof_class.__name__, + allof_class.__name__, self.__class__.__name__, str(ex) ) @@ -979,13 +1034,13 @@ def get_oneof_instance(self, model_args, constant_args): Returns oneof_instance (instance/None) """ - if len(self._composed_schemas()['oneOf']) == 0: + if len(self._composed_schemas['oneOf']) == 0: return None oneof_instances = [] # Iterate over each oneOf schema and determine if the input data # matches the oneOf schemas. - for oneof_class in self._composed_schemas()['oneOf']: + for oneof_class in self._composed_schemas['oneOf']: # transform js keys from input data to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( model_args, oneof_class) @@ -995,7 +1050,7 @@ def get_oneof_instance(self, model_args, constant_args): # additionalProperties attribute in the OAS document) are not added to # the dict. kwargs = {} - var_names = set(oneof_class.openapi_types().keys()) + var_names = set(oneof_class.openapi_types.keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] @@ -1039,16 +1094,16 @@ def get_anyof_instances(self, model_args, constant_args): anyof_instances (list) """ anyof_instances = [] - if len(self._composed_schemas()['anyOf']) == 0: + if len(self._composed_schemas['anyOf']) == 0: return anyof_instances - for anyof_class in self._composed_schemas()['anyOf']: + for anyof_class in self._composed_schemas['anyOf']: # transform js keys to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python(model_args, anyof_class) # extract a dict of only required keys from these_model_vars kwargs = {} - var_names = set(anyof_class.openapi_types().keys()) + var_names = set(anyof_class.openapi_types.keys()) for var_name in var_names: if var_name in fixed_model_args: kwargs[var_name] = fixed_model_args[var_name] @@ -1089,7 +1144,7 @@ def get_var_name_to_model_instances(self, composed_instances): all_instances = [self] all_instances.extend(composed_instances) for instance in all_instances: - for var_name in instance.openapi_types(): + for var_name in instance.openapi_types: if var_name not in var_name_to_model_instances: var_name_to_model_instances[var_name] = [instance] else: @@ -1105,7 +1160,7 @@ def get_unused_args(self, composed_instances, model_args): if var_name_py in unused_args: del unused_args[var_name_py] for instance in composed_instances: - if instance.__class__ in self._composed_schemas()['allOf']: + if instance.__class__ in self._composed_schemas['allOf']: for var_name_py in instance.attribute_map: if var_name_py in unused_args: del unused_args[var_name_py] @@ -1125,9 +1180,7 @@ def validate_get_composed_info(constant_args, model_args, self): Openapi schemas are python classes. Exceptions are raised if: - - no oneOf schema matches the model_args input data - - > 1 oneOf schema matches the model_args input data - - > 1 oneOf schema matches the model_args input data + - 0 or > 1 oneOf schema matches the model_args input data - no anyOf schema matches the model_args input data - any of the allOf schemas do not match the model_args input data @@ -1136,7 +1189,7 @@ def validate_get_composed_info(constant_args, model_args, self): model_args (dict): these are the required and optional spec args that were passed in to make this model self (class): the class that we are instantiating - This class contains self._composed_schemas() + This class contains self._composed_schemas Returns: composed_info (list): length three From 98407305933c0ed240c68d33ff818a5f118b0996 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 10 May 2020 19:02:41 -0700 Subject: [PATCH 106/180] [python-experimental] Raise builtin AttributeError instead of custom ApiKeyError (#6229) * Use AttributeError instead of ApiKeyError because that's what the hasattr builtin function uses * Use AttributeError instead of ApiKeyError because that's what the hasattr builtin function uses * fix unit tests * create ApiAttributeError exception * fix formatting * run samples scripts --- __init__package.mustache | 1 + exceptions.mustache | 19 +++++++++++++++++++ .../method_set_attribute.mustache | 5 +++-- .../methods_setattr_getattr_composed.mustache | 10 ++++++---- .../methods_setattr_getattr_normal.mustache | 5 +++-- python-experimental/model_utils.mustache | 1 + 6 files changed, 33 insertions(+), 8 deletions(-) diff --git a/__init__package.mustache b/__init__package.mustache index 72376acdc3..aee16448ad 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -18,6 +18,7 @@ from {{packageName}}.exceptions import OpenApiException from {{packageName}}.exceptions import ApiTypeError from {{packageName}}.exceptions import ApiValueError from {{packageName}}.exceptions import ApiKeyError +from {{packageName}}.exceptions import ApiAttributeError from {{packageName}}.exceptions import ApiException # import models into sdk package {{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} diff --git a/exceptions.mustache b/exceptions.mustache index dd012f34a0..b187ee9d47 100644 --- a/exceptions.mustache +++ b/exceptions.mustache @@ -56,6 +56,25 @@ class ApiValueError(OpenApiException, ValueError): super(ApiValueError, self).__init__(full_msg) +class ApiAttributeError(OpenApiException, AttributeError): + def __init__(self, msg, path_to_item=None): + """ + Raised when an attribute reference or assignment fails. + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiAttributeError, self).__init__(full_msg) + + class ApiKeyError(OpenApiException, KeyError): def __init__(self, msg, path_to_item=None): """ diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache index f4a36e42f2..15067fff80 100644 --- a/python-experimental/model_templates/method_set_attribute.mustache +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -9,8 +9,9 @@ if name in self.openapi_types: required_types_mixed = self.openapi_types[name] elif self.additional_properties_type is None: - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), + raise ApiAttributeError( + "{0} has no attribute '{1}'".format( + type(self).__name__, name), path_to_item ) elif self.additional_properties_type is not None: diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index 9420fe1582..dd118d30f9 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -24,8 +24,9 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), + raise ApiAttributeError( + "{0} has no attribute '{1}'".format( + type(self).__name__, name), path_to_item ) @@ -54,8 +55,9 @@ values.append(v) len_values = len(values) if len_values == 0: - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), + raise ApiAttributeError( + "{0} has no attribute '{1}'".format( + type(self).__name__, name), path_to_item ) elif len_values == 1: diff --git a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache index f92663ab20..9fc6344908 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache @@ -18,7 +18,8 @@ if self._path_to_item: path_to_item.extend(self._path_to_item) path_to_item.append(name) - raise ApiKeyError( - "{0} has no key '{1}'".format(type(self).__name__, name), + raise ApiAttributeError( + "{0} has no attribute '{1}'".format( + type(self).__name__, name), [name] ) \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index e6b1df6b0e..0be7362f6f 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -14,6 +14,7 @@ import six from {{packageName}}.exceptions import ( ApiKeyError, + ApiAttributeError, ApiTypeError, ApiValueError, ) From f300c07e53edac12409ebd6c7267626a324b1113 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Mon, 11 May 2020 03:18:34 -0700 Subject: [PATCH 107/180] [python-experimental] Improve error message for regex matching, add unit tests. (#6226) * Improve error message * Add unit tests for regular expressions --- python-experimental/model_utils.mustache | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 0be7362f6f..6aad98176f 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -405,14 +405,15 @@ def check_validations(validations, input_variable_path, input_values): if ('regex' in current_validations and not re.search(current_validations['regex']['pattern'], input_values, flags=flags)): - raise ApiValueError( - r"Invalid value for `%s`, must be a follow pattern or equal to " - r"`%s` with flags=`%s`" % ( - input_variable_path[0], - current_validations['regex']['pattern'], - flags - ) - ) + err_msg = r"Invalid value for `%s`, must match regular expression `%s`" % ( + input_variable_path[0], + current_validations['regex']['pattern'] + ) + if flags != 0: + # Don't print the regex flags if the flags are not + # specified in the OAS document. + err_msg = r"%s with flags=`%s`" % (err_msg, flags) + raise ApiValueError(err_msg) def order_response_types(required_types): From 7accc67412e54a64de91087492a0aef9d2762604 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Mon, 11 May 2020 16:57:49 -0700 Subject: [PATCH 108/180] [codegen][Python-experimental] Discriminator NPE fix, handle 'null' type, #4906 enhancements (#5809) * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Runs ensure up to date * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Fix NPE when at least one extension is defined but not x-discriminator-value * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Adds updates from Sebastien Rosset * Removes newlines * Add documentation and new getValidDiscriminatorMappings function * Add documentation and new getValidDiscriminatorMappings function * Add documentation and new getValidDiscriminatorMappings function * Add documentation and new getValidDiscriminatorMappings function * Add documentation and new getValidDiscriminatorMappings function * Add documentation and new getValidDiscriminatorMappings function * throw exception if discriminator mappingName argument is null * handle scenario when composed schema has 'null' type * remove extraneous characters in comments * Uses df.isString * Traverse discriminators to resolve discriminator mapping * Fixes tests be correctly setting df.isString * Remove unused method * Updates discriminatorExplicitMappingVerbose description per PR feedback * Adds description of how mappedModels is populated * Adds the suggestion exception raising when a MappedModel mappingName is null * Actually resolves merge conflicts * Adds addComposedMappedModels and testComposedSchemaOneOfDiscriminatorMap * Requires that discriminators be required properties * Strengthens discriminaotr validation, adds better error messages, adds schema oneof samples * Adds oneOf and anyOf invalidDiscriminator tests * Updates incorrect addOneOfInterfaceModel invocation * Runs ensure-up-to-date * Adds updates from Sebastien Rosset * Removes newlines * Uses df.isString * Fixes tests be correctly setting df.isString * Updates discriminatorExplicitMappingVerbose description per PR feedback * Adds description of how mappedModels is populated * Adds the suggestion exception raising when a MappedModel mappingName is null * Actually resolves merge conflicts * Switches two methods to package private because they are needed for testing * Allow nulls in MappedModel.getMappingName * Remove exception when mappingName is null value * Remove exception when mappingName is null value * resolve merge conflicts * resolve merge conflicts * Execute scripts in the bin directory * Fix CI issues and address PR review comments: better documentation and fix white space issues. * Fix CI issues and address PR review comments: better documentation and fix white space issues. * run sample scripts * resolve merge conflicts * fix end-of-line issue * resolve merge conflicts * resolve merge issues * Handle case when discriminator is not specified in input data * minor changes and add code comments * Refactor get_discriminator code * Add unit test with missing discriminator property * improve get_discriminator function * Run sample scripts * add unit tests for recursive get_discriminator_class * fix unit test issues * fix formatting issues * fix formatting issues * fix formatting issues * fix index out of range exception * fix formatting issues * fix formatting issues * fix formatting issues. Finally figured out how to check formatting in local workspace Co-authored-by: Justin Black Co-authored-by: William Cheng --- .../method_discriminator.mustache | 12 -- .../model_templates/model_composed.mustache | 4 +- .../model_templates/model_normal.mustache | 4 +- python-experimental/model_utils.mustache | 145 ++++++++++++++++-- 4 files changed, 134 insertions(+), 31 deletions(-) delete mode 100644 python-experimental/model_templates/method_discriminator.mustache diff --git a/python-experimental/model_templates/method_discriminator.mustache b/python-experimental/model_templates/method_discriminator.mustache deleted file mode 100644 index de06fb461e..0000000000 --- a/python-experimental/model_templates/method_discriminator.mustache +++ /dev/null @@ -1,12 +0,0 @@ - @classmethod - def get_discriminator_class(cls, data): - """Returns the child class specified by the discriminator""" - discriminator = cls.discriminator - discr_propertyname_py = list(discriminator.keys())[0] - discr_propertyname_js = cls.attribute_map[discr_propertyname_py] - if discr_propertyname_js in data: - class_name = data[discr_propertyname_js] - else: - class_name = data[discr_propertyname_py] - class_name_to_discr_class = discriminator[discr_propertyname_py] - return class_name_to_discr_class.get(class_name) \ No newline at end of file diff --git a/python-experimental/model_templates/model_composed.mustache b/python-experimental/model_templates/model_composed.mustache index 002b2a5789..7e9e86cbfc 100644 --- a/python-experimental/model_templates/model_composed.mustache +++ b/python-experimental/model_templates/model_composed.mustache @@ -51,6 +51,4 @@ class {{unescapedDescription}}(ModelComposed): {{{.}}}, {{/oneOf}} ], - }{{#discriminator}} - -{{> python-experimental/model_templates/method_discriminator }}{{/discriminator}} \ No newline at end of file + } \ No newline at end of file diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache index f9d82ef2a8..21254c55d1 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/python-experimental/model_templates/model_normal.mustache @@ -26,6 +26,4 @@ class {{unescapedDescription}}(ModelNormal): _composed_schemas = {} -{{> python-experimental/model_templates/method_init_normal}}{{#discriminator}} - -{{> python-experimental/model_templates/method_discriminator }}{{/discriminator}} \ No newline at end of file +{{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 6aad98176f..9111fcb830 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -66,31 +66,78 @@ class OpenApiModel(object): # pick a new schema/class to instantiate because a discriminator # propertyName value was passed in + # Build a list containing all oneOf and anyOf descendants. + oneof_anyof_classes = None + if cls._composed_schemas is not None: + oneof_anyof_classes = ( + cls._composed_schemas.get('oneOf', ()) + + cls._composed_schemas.get('anyOf', ())) + if (oneof_anyof_classes and none_type in oneof_anyof_classes and + len(args) == 1 and args[0] is None): + # The input data is the 'null' value AND one of the oneOf/anyOf children + # is the 'null' type (which is introduced in OAS schema >= 3.1). + return None + visited_composed_classes = kwargs.get('_visited_composed_classes', ()) if ( cls.discriminator is None or cls in visited_composed_classes ): - # we don't have a discriminator - # or we have already visited this class before and are sure that we - # want to instantiate it this time + # This openapi schema (cls) does not have a discriminator + # Or we have already visited this class before and are sure that we + # want to instantiate it this time. + # + # If we are making an instance of a composed schema Descendent + # which allOf includes Ancestor, then Ancestor contains + # a discriminator that includes Descendent. + # So if we make an instance of Descendent, we have to make an + # instance of Ancestor to hold the allOf properties. + # This code detects that use case and makes the instance of Ancestor + # For example: + # When making an instance of Dog, _visited_composed_classes = (Dog,) + # then we make an instance of Animal to include in dog._composed_instances + # so when we are here, cls is Animal + # cls.discriminator != None + # cls not in _visited_composed_classes + # new_cls = Dog + # but we know we know that we already have Dog + # because it is in visited_composed_classes + # so make Animal here return super(OpenApiModel, cls).__new__(cls) - oneof_anyof_classes = [] - oneof_anyof_classes.extend(cls._composed_schemas.get('oneOf', ())) - oneof_anyof_classes.extend(cls._composed_schemas.get('anyOf', ())) - new_cls = cls.get_discriminator_class(kwargs) + # Get the name and value of the discriminator property. + # The discriminator name is obtained from the discriminator meta-data + # and the discriminator value is obtained from the input data. + discr_propertyname_py = list(cls.discriminator.keys())[0] + discr_propertyname_js = cls.attribute_map[discr_propertyname_py] + if discr_propertyname_js in kwargs: + discr_value = kwargs[discr_propertyname_js] + elif discr_propertyname_py in kwargs: + discr_value = kwargs[discr_propertyname_py] + else: + # The input data does not contain the discriminator property. + path_to_item = kwargs.get('_path_to_item', ()) + raise ApiValueError( + "Cannot deserialize input data due to missing discriminator. " + "The discriminator property '%s' is missing at path: %s" % + (discr_propertyname_js, path_to_item) + ) + + # Implementation note: the last argument to get_discriminator_class + # is a list of visited classes. get_discriminator_class may recursively + # call itself and update the list of visited classes, and the initial + # value must be an empty list. Hence not using 'visited_composed_classes' + new_cls = get_discriminator_class( + cls, discr_propertyname_py, discr_value, []) if new_cls is None: - disc_prop_name_py = list(cls.discriminator.keys())[0] - disc_prop_name_js = cls.attribute_map[disc_prop_name_py] path_to_item = kwargs.get('_path_to_item', ()) disc_prop_value = kwargs.get( - disc_prop_name_js, kwargs.get(disc_prop_name_py)) + discr_propertyname_js, kwargs.get(discr_propertyname_py)) raise ApiValueError( "Cannot deserialize input data due to invalid discriminator " "value. The OpenAPI document has no mapping for discriminator " "property '%s'='%s' at path: %s" % - (disc_prop_name_js, disc_prop_value, path_to_item) + (discr_propertyname_js, disc_prop_value, path_to_item) ) if new_cls in visited_composed_classes: @@ -101,7 +148,7 @@ class OpenApiModel(object): kwargs['_visited_composed_classes'] = visited_composed_classes + (cls,) if cls._composed_schemas.get('allOf') and oneof_anyof_child: - # validate that we can make self because when we make the + # Validate that we can make self because when we make the # new_cls it will not include the allOf validations in self self_inst = super(OpenApiModel, cls).__new__(cls) self_inst.__init__(*args, **kwargs) @@ -131,7 +178,29 @@ class ModelNormal(OpenApiModel): class ModelComposed(OpenApiModel): """the parent class of models whose type == object in their - swagger/openapi and have oneOf/allOf/anyOf""" + swagger/openapi and have oneOf/allOf/anyOf + + When one sets a property we use var_name_to_model_instances to store the value in + the correct class instances + run any type checking + validation code. + When one gets a property we use var_name_to_model_instances to get the value + from the correct class instances. + This allows multiple composed schemas to contain the same property with additive + constraints on the value. + + _composed_schemas (dict) stores the anyOf/allOf/oneOf classes + key (str): allOf/oneOf/anyOf + value (list): the classes in the XOf definition. + Note: none_type can be included when the openapi document version >= 3.1.0 + _composed_instances (list): stores a list of instances of the composed schemas + defined in _composed_schemas. When properties are accessed in the self instance, + they are returned from the self._data_store or the data stores in the instances + in self._composed_schemas + _var_name_to_model_instances (dict): maps between a variable name on self and + the composed instances (self included) which contain that data + key (str): property name + value (list): list of class instances, self or instances in _composed_instances + which contain the value that the key is referring to. + """ {{> python-experimental/model_templates/methods_setattr_getattr_composed }} @@ -624,6 +693,56 @@ def deserialize_primitive(data, klass, path_to_item): ) +def get_discriminator_class(model_class, + discr_name, + discr_value, cls_visited): + """Returns the child class specified by the discriminator. + + Args: + model_class (OpenApiModel): the model class. + discr_name (string): the name of the discriminator property. + discr_value (any): the discriminator value. + cls_visited (list): list of model classes that have been visited. + Used to determine the discriminator class without + visiting circular references indefinitely. + + Returns: + used_model_class (class/None): the chosen child class that will be used + to deserialize the data, for example dog.Dog. + If a class is not found, None is returned. + """ + + if model_class in cls_visited: + # The class has already been visited and no suitable class was found. + return None + cls_visited.append(model_class) + used_model_class = None + if discr_name in model_class.discriminator: + class_name_to_discr_class = model_class.discriminator[discr_name] + used_model_class = class_name_to_discr_class.get(discr_value) + if used_model_class is None: + # We didn't find a discriminated class in class_name_to_discr_class. + # The discriminator mapping may exist in a descendant (anyOf, oneOf) + # or ancestor (allOf). + # Ancestor example: in the "Dog -> Mammal -> Chordate -> Animal" + # hierarchy, the discriminator mappings may be defined at any level + # in the hieararchy. + # Descendant example: a schema is oneOf[Plant, Mammal], and each + # oneOf child may itself be an allOf with some arbitrary hierarchy, + # and a graph traversal is required to find the discriminator. + composed_children = model_class._composed_schemas.get('oneOf', ()) + \ + model_class._composed_schemas.get('anyOf', ()) + \ + model_class._composed_schemas.get('allOf', ()) + for cls in composed_children: + # Check if the schema has inherited discriminators. + if cls.discriminator is not None: + used_model_class = get_discriminator_class( + cls, discr_name, discr_value, cls_visited) + if used_model_class is not None: + return used_model_class + return used_model_class + + def deserialize_model(model_data, model_class, path_to_item, check_type, configuration, from_server): """Deserializes model_data to model instance. From 89b5c2f58ca57a41d6c8178e022c46987270a270 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Tue, 12 May 2020 23:09:25 -0700 Subject: [PATCH 109/180] [Python-experimental] JSON schema 'null' type should be modeled as 'none_type' (#6121) * Handle null type * Handle null type * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * improve documentation * Handle 'null' type * Handle 'null' type. Add unit tests * Add NullType for go * Add NullType for go * fix modeling of AnyType for go-experimental * execute scripts in bin directory * Add review comments * Add 'null' type in oneOf * Improve OAS YAML file for golang openapi3 samples * 'Any type' includes the null value, so 'isNullable' should be set to TRUE * 'Any type' includes the null value, so 'isNullable' should be set to TRUE * Handle AnyType and NullType * handle anytype for go-experimental * Log warning instead of error * anyOf/oneOf * Change x-golang-is-container extension to x-golang-has-wrapper * Add code comments * Handle Object and any type * Handle Object and any type * Handle object and any type * add code comments * handle additional properties * handle additional properties * handle additional properties * handle anytype and objecttype for go-exerimental * Move golang changes to a separate branch * Move golang changes to a separate branch * Better names for the OAS document test properties * Move golang changes to a separate branch * Run samples scripts * Run samples scripts * fix unit test issues * Handle none type * Fix index out of range exception * fix formatting issues * fix formatting issues * fix formatting issues. Finally figured out how to check formatting in local workspace * fix formatting issues * run samples scripts --- python-experimental/model_utils.mustache | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 9111fcb830..fcbb59e791 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -1153,7 +1153,7 @@ def get_oneof_instance(self, model_args, constant_args): and path to item. Returns - oneof_instance (instance/None) + oneof_instance (instance) """ if len(self._composed_schemas['oneOf']) == 0: return None @@ -1162,6 +1162,13 @@ def get_oneof_instance(self, model_args, constant_args): # Iterate over each oneOf schema and determine if the input data # matches the oneOf schemas. for oneof_class in self._composed_schemas['oneOf']: + # The composed oneOf schema allows the 'null' type and the input data + # is the null value. This is a OAS >= 3.1 feature. + if oneof_class is none_type: + # skip none_types because we are deserializing dict data. + # none_type deserialization is handled in the __new__ method + continue + # transform js keys from input data to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python( model_args, oneof_class) @@ -1207,9 +1214,11 @@ def get_anyof_instances(self, model_args, constant_args): Args: self: the class we are handling model_args (dict): var_name to var_value - used to make instances + The input data, e.g. the payload that must match at least one + anyOf child schema in the OpenAPI document. constant_args (dict): var_name to var_value - used to make instances + args that every model requires, including configuration, server + and path to item. Returns anyof_instances (list) @@ -1219,6 +1228,13 @@ def get_anyof_instances(self, model_args, constant_args): return anyof_instances for anyof_class in self._composed_schemas['anyOf']: + # The composed oneOf schema allows the 'null' type and the input data + # is the null value. This is a OAS >= 3.1 feature. + if anyof_class is none_type: + # skip none_types because we are deserializing dict data. + # none_type deserialization is handled in the __new__ method + continue + # transform js keys to python keys in fixed_model_args fixed_model_args = change_keys_js_to_python(model_args, anyof_class) From ffce474665c03cf625ec9982c09024ec16611d9f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Wed, 13 May 2020 09:11:43 -0700 Subject: [PATCH 110/180] [python-experimental] Support schema property which has $ref to 'oneOf' schema (#6262) * Add reference to oneOf schema * Add model showing unit test failure with ref to oneOf schema * Updates get_discriminator_class to return visited_composed_classes * Fixes broken test, adds is_valid_type * move unit test to test_drawing.py file * Add more unit tests * invoke git pull from spacether fork * invoke git pull from spacether fork * Improve unit tests Co-authored-by: Justin Black --- python-experimental/model_utils.mustache | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index fcbb59e791..3c99e7fb99 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -872,6 +872,31 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, return input_value +def is_valid_type(input_class_simple, valid_classes): + """ + Args: + input_class_simple (class): the class of the input_value that we are + checking + valid_classes (tuple): the valid classes that the current item + should be + Returns: + bool + """ + valid_type = input_class_simple in valid_classes + if not valid_type and issubclass(input_class_simple, OpenApiModel): + for valid_class in valid_classes: + if not valid_class.discriminator: + continue + discr_propertyname_py = list(valid_class.discriminator.keys())[0] + discriminator_classes = ( + valid_class.discriminator[discr_propertyname_py].values() + ) + valid_type = is_valid_type(input_class_simple, discriminator_classes) + if valid_type: + return True + return valid_type + + def validate_and_convert_types(input_value, required_types_mixed, path_to_item, from_server, _check_type, configuration=None): """Raises a TypeError is there is a problem, otherwise returns value @@ -904,7 +929,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, valid_classes, child_req_types_by_current_type = results input_class_simple = get_simple_class(input_value) - valid_type = input_class_simple in set(valid_classes) + valid_type = is_valid_type(input_class_simple, valid_classes) if not valid_type: if configuration: # if input_value is not valid_type try to convert it From 804fd584b87f9e95428738817faee2327b164f88 Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 17 May 2020 09:06:12 -0700 Subject: [PATCH 111/180] [python-experimental] Support schema property which has $ref to 'oneOf' schema and child schema is null type (#6275) * Handle null type * Handle null type * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * Handle null type. Add 'null' type in the OAS document for testing purpose * improve documentation * Handle 'null' type * Handle 'null' type. Add unit tests * Add NullType for go * Add NullType for go * fix modeling of AnyType for go-experimental * execute scripts in bin directory * Add review comments * Add 'null' type in oneOf * Improve OAS YAML file for golang openapi3 samples * 'Any type' includes the null value, so 'isNullable' should be set to TRUE * 'Any type' includes the null value, so 'isNullable' should be set to TRUE * Handle AnyType and NullType * handle anytype for go-experimental * Log warning instead of error * anyOf/oneOf * Change x-golang-is-container extension to x-golang-has-wrapper * Add code comments * Handle Object and any type * Handle Object and any type * Handle object and any type * add code comments * handle additional properties * handle additional properties * handle additional properties * handle anytype and objecttype for go-exerimental * Move golang changes to a separate branch * Move golang changes to a separate branch * Better names for the OAS document test properties * Move golang changes to a separate branch * Run samples scripts * Run samples scripts * fix unit test issues * Handle none type * Fix index out of range exception * fix formatting issues * fix formatting issues * fix formatting issues. Finally figured out how to check formatting in local workspace * fix formatting issues * Add reference to oneOf schema * Add model showing unit test failure with ref to oneOf schema * Updates get_discriminator_class to return visited_composed_classes * Fixes broken test, adds is_valid_type * run samples scripts * move unit test to test_drawing.py file * Add more unit tests * invoke git pull from spacether fork * invoke git pull from spacether fork * Improve unit tests * Add is_nullable_type util function * Add unit test for null value * Add 'ShapeOrNull' type to handle the oneOf/anyOf scenario when the child schema is the null type * Support schema property which has to 'oneOf' schema and child schema is null type * Support schema property which has to 'oneOf' schema and child schema is null type * Support schema property which has to 'oneOf' schema and child schema is null type * Mustache template should use invokerPackage tag to generate import * handle null type in oneOf/anyOf * handle null type in oneOf/anyOf * Add more unit test for nullable shape * resolve merge conflicts * resolve merge conflicts * handle null type in oneOf/anyOf Co-authored-by: Justin Black --- python-experimental/model_utils.mustache | 35 ++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 3c99e7fb99..ce0191f3ea 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -872,6 +872,32 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, return input_value +def is_type_nullable(input_type): + """ + Returns true if None is an allowed value for the specified input_type. + + A type is nullable if at least one of the following conditions is true: + 1. The OAS 'nullable' attribute has been specified, + 1. The type is the 'null' type, + 1. The type is a anyOf/oneOf composed schema, and a child schema is + the 'null' type. + Args: + input_type (type): the class of the input_value that we are + checking + Returns: + bool + """ + if input_type is none_type: + return True + if issubclass(input_type, ModelComposed): + # If oneOf/anyOf, check if the 'null' type is one of the allowed types. + for t in input_type._composed_schemas.get('oneOf', ()): + if is_type_nullable(t): return True + for t in input_type._composed_schemas.get('anyOf', ()): + if is_type_nullable(t): return True + return False + + def is_valid_type(input_class_simple, valid_classes): """ Args: @@ -883,9 +909,14 @@ def is_valid_type(input_class_simple, valid_classes): bool """ valid_type = input_class_simple in valid_classes - if not valid_type and issubclass(input_class_simple, OpenApiModel): + if not valid_type and ( + issubclass(input_class_simple, OpenApiModel) or + input_class_simple is none_type): for valid_class in valid_classes: - if not valid_class.discriminator: + if input_class_simple is none_type and is_type_nullable(valid_class): + # Schema is oneOf/anyOf and the 'null' type is one of the allowed types. + return True + if not (issubclass(valid_class, OpenApiModel) and valid_class.discriminator): continue discr_propertyname_py = list(valid_class.discriminator.keys())[0] discriminator_classes = ( From 0b4f3a43a64d20b6cfb3a454263183664f79341d Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 17 May 2020 09:11:01 -0700 Subject: [PATCH 112/180] [codegen][python-experimental] Add configuration knob to disable JSON schema validation (#6227) * Add knob to disable JSON schema structural validation * Add knob to disable JSON schema structural validation * Fix formatting issues * execute sample scripts * execute sample scripts * fix multipleOf validation issue * Add validation log for multipleOf. Add customizable validation checks. add unit tests for JSON schema validation * Add validation log for multipleOf. Add customizable validation checks. add unit tests for JSON schema validation * Add validation log for multipleOf. Add customizable validation checks. add unit tests for JSON schema validation * Add validation log for multipleOf. Add customizable validation checks. add unit tests for JSON schema validation. Fix for python 2 * address review comments --- configuration.mustache | 29 ++++++++ python-experimental/api.mustache | 3 +- .../model_templates/classvars.mustache | 6 ++ .../method_set_attribute.mustache | 3 +- python-experimental/model_utils.mustache | 67 +++++++++++++++---- 5 files changed, 93 insertions(+), 15 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index dceab63e67..d1705eed25 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -14,8 +14,15 @@ import urllib3 import six from six.moves import http_client as httplib +from {{packageName}}.exceptions import ApiValueError +JSON_SCHEMA_VALIDATION_KEYWORDS = { + 'multipleOf', 'maximum', 'exclusiveMaximum', + 'minimum', 'exclusiveMinimum', 'maxLength', + 'minLength', 'pattern', 'maxItems', 'minItems' +} + class Configuration(object): """NOTE: This class is auto generated by OpenAPI Generator @@ -43,6 +50,19 @@ class Configuration(object): then all undeclared properties received by the server are injected into the additional properties map. In that case, there are undeclared properties, and nothing to discard. + :param disabled_client_side_validations (string): Comma-separated list of + JSON schema validation keywords to disable JSON schema structural validation + rules. The following keywords may be specified: multipleOf, maximum, + exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength, pattern, + maxItems, minItems. + By default, the validation is performed for data generated locally by the client + and data received from the server, independent of any validation performed by + the server side. If the input data does not satisfy the JSON schema validation + rules specified in the OpenAPI document, an exception is raised. + If disabled_client_side_validations is set, structural validation is + disabled. This can be useful to troubleshoot data validation problem, such as + when the OpenAPI document validation rules do not match the actual API data + received by the server. {{#hasHttpSignatureMethods}} :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration @@ -139,6 +159,7 @@ conf = {{{packageName}}}.Configuration( api_key=None, api_key_prefix=None, username=None, password=None, discard_unknown_keys=False, + disabled_client_side_validations="", {{#hasHttpSignatureMethods}} signing_info=None, {{/hasHttpSignatureMethods}} @@ -172,6 +193,7 @@ conf = {{{packageName}}}.Configuration( """Password for HTTP basic authentication """ self.discard_unknown_keys = discard_unknown_keys + self.disabled_client_side_validations = disabled_client_side_validations {{#hasHttpSignatureMethods}} if signing_info is not None: signing_info.host = host @@ -277,6 +299,13 @@ conf = {{{packageName}}}.Configuration( def __setattr__(self, name, value): object.__setattr__(self, name, value) + if name == 'disabled_client_side_validations': + s = set(filter(None, value.split(','))) + for v in s: + if v not in JSON_SCHEMA_VALIDATION_KEYWORDS: + raise ApiValueError( + "Invalid keyword: '{0}''".format(v)) + self._disabled_client_side_validations = s {{#hasHttpSignatureMethods}} if name == "signing_info" and value is not None: # Ensure the host paramater from signing info is the same as diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 4cf1d423e8..44fc3a8997 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -376,7 +376,8 @@ class Endpoint(object): check_validations( self.validations, (param,), - kwargs[param] + kwargs[param], + configuration=self.api_client.configuration ) if kwargs['_check_input_type'] is False: diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index fe54e34f5b..471c16c10a 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -57,6 +57,9 @@ {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} }, {{/pattern}} +{{#multipleOf}} + 'multiple_of': {{multipleOf}}, +{{/multipleOf}} }, {{/hasValidation}} {{/requiredVars}} @@ -87,6 +90,9 @@ {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} }, {{/pattern}} +{{#multipleOf}} + 'multiple_of': {{multipleOf}}, +{{/multipleOf}} }, {{/hasValidation}} {{/optionalVars}} diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache index 15067fff80..fddbc7c2ea 100644 --- a/python-experimental/model_templates/method_set_attribute.mustache +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -45,6 +45,7 @@ check_validations( self.validations, (name,), - value + value, + self._configuration ) self.__dict__['_data_store'][name] = value \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index ce0191f3ea..1c163a915a 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -369,17 +369,50 @@ def check_allowed_values(allowed_values, input_variable_path, input_values): ) -def check_validations(validations, input_variable_path, input_values): +def is_json_validation_enabled(schema_keyword, configuration=None): + """Returns true if JSON schema validation is enabled for the specified + validation keyword. This can be used to skip JSON schema structural validation + as requested in the configuration. + + Args: + schema_keyword (string): the name of a JSON schema validation keyword. + configuration (Configuration): the configuration class. + """ + + return (configuration is None or + not hasattr(configuration, '_disabled_client_side_validations') or + schema_keyword not in configuration._disabled_client_side_validations) + + +def check_validations( + validations, input_variable_path, input_values, + configuration=None): """Raises an exception if the input_values are invalid Args: - validations (dict): the validation dictionary - input_variable_path (tuple): the path to the input variable + validations (dict): the validation dictionary. + input_variable_path (tuple): the path to the input variable. input_values (list/str/int/float/date/datetime): the values that we - are checking + are checking. + configuration (Configuration): the configuration class. """ + current_validations = validations[input_variable_path] - if ('max_length' in current_validations and + if (is_json_validation_enabled('multipleOf', configuration) and + 'multiple_of' in current_validations and + isinstance(input_values, (int, float)) and + not (float(input_values) / current_validations['multiple_of']).is_integer()): + # Note 'multipleOf' will be as good as the floating point arithmetic. + raise ApiValueError( + "Invalid value for `%s`, value must be a multiple of " + "`%s`" % ( + input_variable_path[0], + current_validations['multiple_of'] + ) + ) + + if (is_json_validation_enabled('maxLength', configuration) and + 'max_length' in current_validations and len(input_values) > current_validations['max_length']): raise ApiValueError( "Invalid value for `%s`, length must be less than or equal to " @@ -389,7 +422,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('min_length' in current_validations and + if (is_json_validation_enabled('minLength', configuration) and + 'min_length' in current_validations and len(input_values) < current_validations['min_length']): raise ApiValueError( "Invalid value for `%s`, length must be greater than or equal to " @@ -399,7 +433,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('max_items' in current_validations and + if (is_json_validation_enabled('maxItems', configuration) and + 'max_items' in current_validations and len(input_values) > current_validations['max_items']): raise ApiValueError( "Invalid value for `%s`, number of items must be less than or " @@ -409,7 +444,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('min_items' in current_validations and + if (is_json_validation_enabled('minItems', configuration) and + 'min_items' in current_validations and len(input_values) < current_validations['min_items']): raise ValueError( "Invalid value for `%s`, number of items must be greater than or " @@ -432,7 +468,8 @@ def check_validations(validations, input_variable_path, input_values): max_val = input_values min_val = input_values - if ('exclusive_maximum' in current_validations and + if (is_json_validation_enabled('exclusiveMaximum', configuration) and + 'exclusive_maximum' in current_validations and max_val >= current_validations['exclusive_maximum']): raise ApiValueError( "Invalid value for `%s`, must be a value less than `%s`" % ( @@ -441,7 +478,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('inclusive_maximum' in current_validations and + if (is_json_validation_enabled('maximum', configuration) and + 'inclusive_maximum' in current_validations and max_val > current_validations['inclusive_maximum']): raise ApiValueError( "Invalid value for `%s`, must be a value less than or equal to " @@ -451,7 +489,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('exclusive_minimum' in current_validations and + if (is_json_validation_enabled('exclusiveMinimum', configuration) and + 'exclusive_minimum' in current_validations and min_val <= current_validations['exclusive_minimum']): raise ApiValueError( "Invalid value for `%s`, must be a value greater than `%s`" % @@ -461,7 +500,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) - if ('inclusive_minimum' in current_validations and + if (is_json_validation_enabled('minimum', configuration) and + 'inclusive_minimum' in current_validations and min_val < current_validations['inclusive_minimum']): raise ApiValueError( "Invalid value for `%s`, must be a value greater than or equal " @@ -471,7 +511,8 @@ def check_validations(validations, input_variable_path, input_values): ) ) flags = current_validations.get('regex', {}).get('flags', 0) - if ('regex' in current_validations and + if (is_json_validation_enabled('pattern', configuration) and + 'regex' in current_validations and not re.search(current_validations['regex']['pattern'], input_values, flags=flags)): err_msg = r"Invalid value for `%s`, must match regular expression `%s`" % ( From c9608838a5c9b085f0d78f95d5a12ea1df0d945f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 21 May 2020 18:59:31 -0700 Subject: [PATCH 113/180] [Python-experimental] Should accept float value serialized without decimal point (#6386) * Mustache template should use invokerPackage tag to generate import * A float may be serialized as an integer, e.g. '3' is a valid serialized float * A float may be serialized as an integer, e.g. '3' is a valid serialized float * add unit tests --- python-experimental/model_utils.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 1c163a915a..7c566933a5 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -229,6 +229,7 @@ COERCION_INDEX_BY_TYPE = { UPCONVERSION_TYPE_PAIRS = ( (str, datetime), (str, date), + (int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float. (list, ModelComposed), (dict, ModelComposed), (list, ModelNormal), From 95d0e6f9ab7f0f727486cefd9d3b0bde6046330f Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 22 May 2020 09:44:15 -0700 Subject: [PATCH 114/180] [python-experimental] Add support for pep 3134, attach cause of exception (#6388) * Mustache template should use invokerPackage tag to generate import * Add exception cause * using six module for exception chaining in Python 3.x --- python-experimental/model_utils.mustache | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 7c566933a5..c1c3c934aa 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -725,14 +725,14 @@ def deserialize_primitive(data, klass, path_to_item): # '7' -> 7.0 -> '7.0' != '7' raise ValueError('This is not a float') return converted_value - except (OverflowError, ValueError): + except (OverflowError, ValueError) as ex: # parse can raise OverflowError - raise ApiValueError( + six.raise_from(ApiValueError( "{0}Failed to parse {1} as {2}".format( additional_message, repr(data), get_py3_class_name(klass) ), path_to_item=path_to_item - ) + ), ex) def get_discriminator_class(model_class, @@ -1220,7 +1220,7 @@ def get_allof_instances(self, model_args, constant_args): allof_instance = allof_class(**kwargs) composed_instances.append(allof_instance) except Exception as ex: - raise ApiValueError( + six.raise_from(ApiValueError( "Invalid inputs given to generate an instance of '%s'. The " "input data was invalid for the allOf schema '%s' in the composed " "schema '%s'. Error=%s" % ( @@ -1229,7 +1229,7 @@ def get_allof_instances(self, model_args, constant_args): self.__class__.__name__, str(ex) ) - ) + ), ex) return composed_instances From 18c73295920f08c0fedf27e9be17d1b2db1ef50b Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Fri, 22 May 2020 19:09:12 -0700 Subject: [PATCH 115/180] [Python-experimental] Rename from_server variable to json_variable_naming (#6390) * Mustache template should use invokerPackage tag to generate import * Add unit test showing how to construct objects from a JSON dict * rename from_server to json_variable_naming * rename from_server to json_variable_naming * fix code so it can execute in python 2.x * rename variable * fix typo * fix typo * fix deprecation warning * fix deprecation warning * fix deprecation warning --- .../method_init_composed.mustache | 4 +- .../method_init_normal.mustache | 2 +- .../method_init_shared.mustache | 10 ++-- .../method_set_attribute.mustache | 2 +- python-experimental/model_utils.mustache | 54 +++++++++++-------- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index a5d948f0dd..67750cb17a 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -1,7 +1,7 @@ required_properties = set([ '_data_store', '_check_type', - '_from_server', + '_spec_property_naming', '_path_to_item', '_configuration', '_visited_composed_classes', @@ -15,7 +15,7 @@ constant_args = { '_check_type': _check_type, '_path_to_item': _path_to_item, - '_from_server': _from_server, + '_spec_property_naming': _spec_property_naming, '_configuration': _configuration, '_visited_composed_classes': self._visited_composed_classes, } diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index 8433c49f2f..9a3aeaefea 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -1,7 +1,7 @@ required_properties = set([ '_data_store', '_check_type', - '_from_server', + '_spec_property_naming', '_path_to_item', '_configuration', '_visited_composed_classes', diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 1631d57eec..3a77f7e8a8 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,5 +1,5 @@ @convert_js_args_to_python_args - def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _from_server=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI {{#requiredVars}} @@ -26,8 +26,10 @@ _path_to_item (tuple/list): This is a list of keys or values to drill down to the model in received_data when deserializing a response - _from_server (bool): True if the data is from the server - False if the data is from the client (default) + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) _configuration (Configuration): the instance to use when deserializing a file_type parameter. If passed, type conversion is attempted @@ -54,7 +56,7 @@ self._data_store = {} self._check_type = _check_type - self._from_server = _from_server + self._spec_property_naming = _spec_property_naming self._path_to_item = _path_to_item self._configuration = _configuration self._visited_composed_classes = _visited_composed_classes + (self.__class__,) \ No newline at end of file diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/python-experimental/model_templates/method_set_attribute.mustache index fddbc7c2ea..8ba0529cd0 100644 --- a/python-experimental/model_templates/method_set_attribute.mustache +++ b/python-experimental/model_templates/method_set_attribute.mustache @@ -33,7 +33,7 @@ if self._check_type: value = validate_and_convert_types( - value, required_types_mixed, path_to_item, self._from_server, + value, required_types_mixed, path_to_item, self._spec_property_naming, self._check_type, configuration=self._configuration) if (name,) in self.allowed_values: check_allowed_values( diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index c1c3c934aa..a0d2dd2e5b 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -564,15 +564,17 @@ def order_response_types(required_types): return sorted_types -def remove_uncoercible(required_types_classes, current_item, from_server, +def remove_uncoercible(required_types_classes, current_item, spec_property_naming, must_convert=True): """Only keeps the type conversions that are possible Args: required_types_classes (tuple): tuple of classes that are required these should be ordered by COERCION_INDEX_BY_TYPE - from_server (bool): a boolean of whether the data is from the server - if false, the data is from the client + spec_property_naming (bool): True if the variable names in the input + data are serialized names as specified in the OpenAPI document. + False if the variables names in the input data are python + variable names in PEP-8 snake case. current_item (any): the current item (input data) to be converted Keyword Args: @@ -602,7 +604,7 @@ def remove_uncoercible(required_types_classes, current_item, from_server, continue class_pair = (current_type_simple, required_type_class_simplified) - if must_convert and class_pair in COERCIBLE_TYPE_PAIRS[from_server]: + if must_convert and class_pair in COERCIBLE_TYPE_PAIRS[spec_property_naming]: results_classes.append(required_type_class) elif class_pair in UPCONVERSION_TYPE_PAIRS: results_classes.append(required_type_class) @@ -786,7 +788,7 @@ def get_discriminator_class(model_class, def deserialize_model(model_data, model_class, path_to_item, check_type, - configuration, from_server): + configuration, spec_property_naming): """Deserializes model_data to model instance. Args: @@ -796,8 +798,10 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, check_type (bool): whether to check the data tupe for the values in the model configuration (Configuration): the instance to use to convert files - from_server (bool): True if the data is from the server - False if the data is from the client + spec_property_naming (bool): True if the variable names in the input + data are serialized names as specified in the OpenAPI document. + False if the variables names in the input data are python + variable names in PEP-8 snake case. Returns: model instance @@ -811,7 +815,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, kw_args = dict(_check_type=check_type, _path_to_item=path_to_item, _configuration=configuration, - _from_server=from_server) + _spec_property_naming=spec_property_naming) if issubclass(model_class, ModelSimple): instance = model_class(value=model_data, **kw_args) @@ -862,7 +866,7 @@ def deserialize_file(response_data, configuration, content_disposition=None): def attempt_convert_item(input_value, valid_classes, path_to_item, - configuration, from_server, key_type=False, + configuration, spec_property_naming, key_type=False, must_convert=False, check_type=True): """ Args: @@ -870,8 +874,10 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, valid_classes (any): the classes that are valid path_to_item (list): the path to the item to convert configuration (Configuration): the instance to use to convert files - from_server (bool): True if data is from the server, False is data is - from the client + spec_property_naming (bool): True if the variable names in the input + data are serialized names as specified in the OpenAPI document. + False if the variables names in the input data are python + variable names in PEP-8 snake case. key_type (bool): if True we need to convert a key type (not supported) must_convert (bool): if True we must convert check_type (bool): if True we check the type or the returned data in @@ -887,7 +893,7 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, """ valid_classes_ordered = order_response_types(valid_classes) valid_classes_coercible = remove_uncoercible( - valid_classes_ordered, input_value, from_server) + valid_classes_ordered, input_value, spec_property_naming) if not valid_classes_coercible or key_type: # we do not handle keytype errors, json will take care # of this for us @@ -899,7 +905,7 @@ def attempt_convert_item(input_value, valid_classes, path_to_item, if issubclass(valid_class, OpenApiModel): return deserialize_model(input_value, valid_class, path_to_item, check_type, - configuration, from_server) + configuration, spec_property_naming) elif valid_class == file_type: return deserialize_file(input_value, configuration) return deserialize_primitive(input_value, valid_class, @@ -971,7 +977,7 @@ def is_valid_type(input_class_simple, valid_classes): def validate_and_convert_types(input_value, required_types_mixed, path_to_item, - from_server, _check_type, configuration=None): + spec_property_naming, _check_type, configuration=None): """Raises a TypeError is there is a problem, otherwise returns value Args: @@ -982,8 +988,10 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, path_to_item: (list) the path to the data being validated this stores a list of keys or indices to get to the data being validated - from_server (bool): True if data is from the server - False if data is from the client + spec_property_naming (bool): True if the variable names in the input + data are serialized names as specified in the OpenAPI document. + False if the variables names in the input data are python + variable names in PEP-8 snake case. _check_type: (boolean) if true, type will be checked and conversion will be attempted. configuration: (Configuration): the configuration class to use @@ -1011,7 +1019,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, valid_classes, path_to_item, configuration, - from_server, + spec_property_naming, key_type=False, must_convert=True ) @@ -1024,14 +1032,14 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, if len(valid_classes) > 1 and configuration: # there are valid classes which are not the current class valid_classes_coercible = remove_uncoercible( - valid_classes, input_value, from_server, must_convert=False) + valid_classes, input_value, spec_property_naming, must_convert=False) if valid_classes_coercible: converted_instance = attempt_convert_item( input_value, valid_classes_coercible, path_to_item, configuration, - from_server, + spec_property_naming, key_type=False, must_convert=False ) @@ -1058,7 +1066,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, inner_value, inner_required_types, inner_path, - from_server, + spec_property_naming, _check_type, configuration=configuration ) @@ -1076,7 +1084,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, inner_val, inner_required_types, inner_path, - from_server, + spec_property_naming, _check_type, configuration=configuration ) @@ -1182,8 +1190,8 @@ def convert_js_args_to_python_args(fn): from functools import wraps @wraps(fn) def wrapped_init(self, *args, **kwargs): - from_server = kwargs.get('_from_server', False) - if from_server: + spec_property_naming = kwargs.get('_spec_property_naming', False) + if spec_property_naming: kwargs = change_keys_js_to_python(kwargs, self.__class__) return fn(self, *args, **kwargs) return wrapped_init From a9e712e3cb31c5fe2d32d4a4dbe196a3fb7fe7aa Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Sun, 24 May 2020 17:21:00 -0700 Subject: [PATCH 116/180] [Python-experimental] Fix type error if oneof/anyof child schema is null type (#6387) * Mustache template should use invokerPackage tag to generate import * Fix runtime exception when composed schema has 'null' type * Fix runtime exception when composed schema has 'null' type --- python-experimental/model_utils.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index a0d2dd2e5b..c9a527ab6f 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -779,7 +779,7 @@ def get_discriminator_class(model_class, model_class._composed_schemas.get('allOf', ()) for cls in composed_children: # Check if the schema has inherited discriminators. - if cls.discriminator is not None: + if hasattr(cls, 'discriminator') and cls.discriminator is not None: used_model_class = get_discriminator_class( cls, discr_name, discr_value, cls_visited) if used_model_class is not None: From 2b908e159d2da083b1f61ff746160dda491064cd Mon Sep 17 00:00:00 2001 From: Justin Black Date: Wed, 27 May 2020 20:33:43 -0700 Subject: [PATCH 117/180] python-experimental updates ancestor + adds descendant discriminator tests (#6417) * Updates comments in new method * Adds missing line in model_utils.py * Removes biology examples, adds ParentPet ancestor example + test, adds Pig schemas * Updates comment and var names in get_discriminator_class, adds testMammal test * Updates comment --- python-experimental/model_utils.mustache | 71 ++++++++++++++---------- 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index c9a527ab6f..49ad6f35e3 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -83,26 +83,22 @@ class OpenApiModel(object): cls.discriminator is None or cls in visited_composed_classes ): - # This openapi schema (cls) does not have a discriminator - # Or we have already visited this class before and are sure that we - # want to instantiate it this time. + # Use case 1: this openapi schema (cls) does not have a discriminator + # Use case 2: we have already visited this class before and are sure that we + # want to instantiate it this time. We have visited this class deserializing + # a payload with a discriminator. During that process we traveled through + # this class but did not make an instance of it. Now we are making an + # instance of a composed class which contains cls in it, so this time make an instance of cls. # - # If we are making an instance of a composed schema Descendent - # which allOf includes Ancestor, then Ancestor contains - # a discriminator that includes Descendent. - # So if we make an instance of Descendent, we have to make an - # instance of Ancestor to hold the allOf properties. - # This code detects that use case and makes the instance of Ancestor - # For example: - # When making an instance of Dog, _visited_composed_classes = (Dog,) - # then we make an instance of Animal to include in dog._composed_instances - # so when we are here, cls is Animal - # cls.discriminator != None - # cls not in _visited_composed_classes - # new_cls = Dog - # but we know we know that we already have Dog - # because it is in visited_composed_classes - # so make Animal here + # Here's an example of use case 2: If Animal has a discriminator + # petType and we pass in "Dog", and the class Dog + # allOf includes Animal, we move through Animal + # once using the discriminator, and pick Dog. + # Then in the composed schema dog Dog, we will make an instance of the + # Animal class (because Dal has allOf: Animal) but this time we won't travel + # through Animal's discriminator because we passed in + # _visited_composed_classes = (Animal,) + return super(OpenApiModel, cls).__new__(cls) # Get the name and value of the discriminator property. @@ -141,7 +137,22 @@ class OpenApiModel(object): ) if new_cls in visited_composed_classes: - # if we are coming from the chosen new_cls use cls instead + # if we are making an instance of a composed schema Descendent + # which allOf includes Ancestor, then Ancestor contains + # a discriminator that includes Descendent. + # So if we make an instance of Descendent, we have to make an + # instance of Ancestor to hold the allOf properties. + # This code detects that use case and makes the instance of Ancestor + # For example: + # When making an instance of Dog, _visited_composed_classes = (Dog,) + # then we make an instance of Animal to include in dog._composed_instances + # so when we are here, cls is Animal + # cls.discriminator != None + # cls not in _visited_composed_classes + # new_cls = Dog + # but we know we know that we already have Dog + # because it is in visited_composed_classes + # so make Animal here return super(OpenApiModel, cls).__new__(cls) oneof_anyof_child = new_cls in oneof_anyof_classes @@ -766,18 +777,20 @@ def get_discriminator_class(model_class, used_model_class = class_name_to_discr_class.get(discr_value) if used_model_class is None: # We didn't find a discriminated class in class_name_to_discr_class. + # So look in the ancestor or descendant discriminators # The discriminator mapping may exist in a descendant (anyOf, oneOf) # or ancestor (allOf). - # Ancestor example: in the "Dog -> Mammal -> Chordate -> Animal" + # Ancestor example: in the GrandparentAnimal -> ParentPet -> ChildCat # hierarchy, the discriminator mappings may be defined at any level - # in the hieararchy. - # Descendant example: a schema is oneOf[Plant, Mammal], and each - # oneOf child may itself be an allOf with some arbitrary hierarchy, - # and a graph traversal is required to find the discriminator. - composed_children = model_class._composed_schemas.get('oneOf', ()) + \ - model_class._composed_schemas.get('anyOf', ()) + \ - model_class._composed_schemas.get('allOf', ()) - for cls in composed_children: + # in the hierarchy. + # Descendant example: mammal -> whale/zebra/Pig -> BasquePig/DanishPig + # if we try to make BasquePig from mammal, we need to travel through + # the oneOf descendant discriminators to find BasquePig + descendant_classes = model_class._composed_schemas.get('oneOf', ()) + \ + model_class._composed_schemas.get('anyOf', ()) + ancestor_classes = model_class._composed_schemas.get('allOf', ()) + possible_classes = descendant_classes + ancestor_classes + for cls in possible_classes: # Check if the schema has inherited discriminators. if hasattr(cls, 'discriminator') and cls.discriminator is not None: used_model_class = get_discriminator_class( From 35b2b7d7c20a1fa04885c711eacfb5b1740e0e1b Mon Sep 17 00:00:00 2001 From: Sebastien Rosset Date: Thu, 28 May 2020 09:40:48 -0700 Subject: [PATCH 118/180] [codegen][python-experimental] Composed schema with additionalProperties (#6290) * Mustache template should use invokerPackage tag to generate import * Add a unit test for allOf and additionalProperties * Fix getAdditionalProperties * Add code comments * Add code comments * set nullable for additionalproperties * add variants of additionalProperties * Add more unit tests * Handle additionalProperties for composed schemas * improve code comments * Add code comments * Add code comments * Add code comments * Add code comments * Add code comments * Add assertions in unit tests * Add new property to support the 'additionalProperties' keyword with composed schemas * run sample scripts * fix unit tests to handle additionalProperties * Handle additional properties and composed schema * Handle additional properties and composed schema * Add support for additionalProperties and composed schema * Format java code * Add more unit tests for Python * Handle reference in additionalProperty keyword * Handle reference in additionalProperty keyword * Add use case for additionalProperties and reference * run sample scripts * resolve schema reference * Add OpenAPI argument * Add OpenAPI argument * Add OpenAPI argument * Add OpenAPI argument * Add OpenAPI argument * Handle additional property keyword with reference * Handle additional property keyword with reference * Handle additional property keyword with reference * Handle additional property keyword with reference * add additionalproperties attribute with boolean values * Run sample scripts * handle additional properties * Handle additionalProperties boolean values * Run sample scripts * fix javadoc issues * fix javadoc issues * Add Locale to String.toLowerCase * execute sample scripts * handle additional properties * Add code comments * Handle imports of referenced models in additional properties * Handle isNullable class * handle nullable type * improve documentation, run sample scripts * improve documentation, run sample scripts * execute sample scripts * execute sample scripts * Execute sample scripts * Run samples scripts * set legacyAdditionalPropertiesBehavior to true by default, except python * create separate yaml file to avoid having lots of changes in the pr * create separate yaml file to avoid having lots of changes in the pr * create separate yaml file to avoid having lots of changes in the pr * create separate yaml file to avoid having lots of changes in the pr * create separate yaml file to avoid having lots of changes in the pr * create separate yaml file to avoid having lots of changes in the pr * Change name of CLI option * Generate doc * Add TODO statement * add code comments * run samples scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * refactor cli option for additional properties * refactor cli option for additional properties * run samples scripts * run sample scripts * run sample scripts * run sample scripts * run sample scripts * Add yaml comments * small refactor * small refactor * run sample scripts * run sample scripts * fix unit tests * Set disallowAdditionalPropertiesIfNotPresent flag * reduced size of test yaml file * simplify code and add imports directly * rename some of the properties used in tests * Handle more scenarios for nullable types * add code comments * Adds *args input to __init__ method to fix test testFruitNullValue * Resolve merge issues * run samples scripts * run doc generator * fix merge conflicts Co-authored-by: Justin Black --- python-experimental/model.mustache | 1 + .../model_templates/classvars.mustache | 2 ++ .../method_init_shared.mustache | 23 ++++++++++++++++++- python-experimental/model_utils.mustache | 22 +++++++++--------- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 9afb17b527..0790c61435 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -10,6 +10,7 @@ import six # noqa: F401 import nulltype # noqa: F401 from {{packageName}}.model_utils import ( # noqa: F401 + ApiTypeError, ModelComposed, ModelNormal, ModelSimple, diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 471c16c10a..9fc3f83433 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -100,6 +100,8 @@ additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} + _nullable = {{#isNullable}}True{{/isNullable}}{{^isNullable}}False{{/isNullable}} + @cached_property def openapi_types(): """ diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 3a77f7e8a8..78059150f2 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -1,5 +1,5 @@ @convert_js_args_to_python_args - def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}{{#requiredVars}}{{#defaultValue}}, {{name}}={{{defaultValue}}}{{/defaultValue}}{{/requiredVars}}, _check_type=True, _spec_property_naming=False, _path_to_item=(), _configuration=None, _visited_composed_classes=(), **kwargs): # noqa: E501 + def __init__(self{{#requiredVars}}{{^defaultValue}}, {{name}}{{/defaultValue}}{{/requiredVars}}, *args, **kwargs): # noqa: E501 """{{classname}} - a model defined in OpenAPI {{#requiredVars}} @@ -54,6 +54,27 @@ {{/optionalVars}} """ +{{#requiredVars}} +{{#defaultValue}} + {{name}} = kwargs.get('{{name}}', {{{defaultValue}}}) +{{/defaultValue}} +{{/requiredVars}} + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + self._data_store = {} self._check_type = _check_type self._spec_property_naming = _spec_property_naming diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 49ad6f35e3..b1db9b329c 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -66,16 +66,8 @@ class OpenApiModel(object): # pick a new schema/class to instantiate because a discriminator # propertyName value was passed in - # Build a list containing all oneOf and anyOf descendants. - oneof_anyof_classes = None - if cls._composed_schemas is not None: - oneof_anyof_classes = ( - cls._composed_schemas.get('oneOf', ()) + - cls._composed_schemas.get('anyOf', ())) - if (oneof_anyof_classes and none_type in oneof_anyof_classes and - len(args) == 1 and args[0] is None): - # The input data is the 'null' value AND one of the oneOf/anyOf children - # is the 'null' type (which is introduced in OAS schema >= 3.1). + if len(args) == 1 and args[0] is None and is_type_nullable(cls): + # The input data is the 'null' value and the type is nullable. return None visited_composed_classes = kwargs.get('_visited_composed_classes', ()) @@ -155,6 +147,12 @@ class OpenApiModel(object): # so make Animal here return super(OpenApiModel, cls).__new__(cls) + # Build a list containing all oneOf and anyOf descendants. + oneof_anyof_classes = None + if cls._composed_schemas is not None: + oneof_anyof_classes = ( + cls._composed_schemas.get('oneOf', ()) + + cls._composed_schemas.get('anyOf', ())) oneof_anyof_child = new_cls in oneof_anyof_classes kwargs['_visited_composed_classes'] = visited_composed_classes + (cls,) @@ -950,8 +948,10 @@ def is_type_nullable(input_type): """ if input_type is none_type: return True + if issubclass(input_type, OpenApiModel) and input_type._nullable: + return True if issubclass(input_type, ModelComposed): - # If oneOf/anyOf, check if the 'null' type is one of the allowed types. + # If oneOf/anyOf, check if the 'null' type is one of the allowed types. for t in input_type._composed_schemas.get('oneOf', ()): if is_type_nullable(t): return True for t in input_type._composed_schemas.get('anyOf', ()): From 591899af81d946eb990d0190010fbf5aa18a09fc Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 1 Jun 2020 00:25:37 -0700 Subject: [PATCH 119/180] [python-experimental] Quicken package loading (#6437) * apis and models contains all apis and models, omits loading them in the package namespace * Runs git add -a and commits it * Fixes test_outer_enum.py * Fixes test_fruit.py * Updates test_fruit and test_mammal * Fixes test_parent_pet * Updates test_discard_unknown_properties.py * Updates test_deserialization.py * Updates v2 docs md files for apis + the readme * Fixes v2 tests * v2 doc updates * Updates v3 docs * Reverts python_doc_auth_partial.mustache * Adds sys to v3 tests * Adds FILES update Co-authored-by: Justin Black --- python-experimental/README_common.mustache | 39 ++++++++++++++++++-- python-experimental/__init__api.mustache | 3 ++ python-experimental/__init__apis.mustache | 19 ++++++++++ python-experimental/__init__model.mustache | 8 ++-- python-experimental/__init__models.mustache | 18 +++++++++ python-experimental/__init__package.mustache | 17 +-------- python-experimental/api_doc_example.mustache | 6 ++- python-experimental/api_test.mustache | 36 ++++++++++++++++++ python-experimental/model_test.mustache | 10 +++-- 9 files changed, 129 insertions(+), 27 deletions(-) create mode 100644 python-experimental/__init__api.mustache create mode 100644 python-experimental/__init__apis.mustache create mode 100644 python-experimental/__init__models.mustache create mode 100644 python-experimental/api_test.mustache diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index 7d9811fdfb..0f6dcb41d6 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -4,13 +4,22 @@ from __future__ import print_function import time import {{{packageName}}} from pprint import pprint -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} +{{#apiInfo}} +{{#apis}} +{{#-first}} +from {{apiPackage}} import {{classVarName}} +{{#imports}} +{{{import}}} +{{/imports}} +{{#operations}} +{{#operation}} +{{#-first}} {{> python_doc_auth_partial}} # Enter a context with an instance of the API client with {{{packageName}}}.ApiClient(configuration) as api_client: # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) + api_instance = {{classVarName}}.{{{classname}}}(api_client) {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} {{/allParams}} @@ -20,7 +29,12 @@ with {{{packageName}}}.ApiClient(configuration) as api_client: pprint(api_response){{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) - {{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} +{{/-first}} +{{/operation}} +{{/operations}} +{{/-first}} +{{/apis}} +{{/apiInfo}} ``` ## Documentation for API Endpoints @@ -77,3 +91,22 @@ Class | Method | HTTP request | Description {{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} {{/hasMore}}{{/apis}}{{/apiInfo}} + +## Notes for Large OpenAPI documents +If the OpenAPI document is large, imports in {{{packageName}}}.apis and {{{packageName}}}.models may fail with a +RecursionError indicating the maximum recursion limit has been exceeded. In that case, there are a couple of solutions: + +Solution 1: +Use specific imports for apis and models like: +- `from {{{packageName}}}.api.default_api import DefaultApi` +- `from {{{packageName}}}.model.pet import Pet` + +Solution 1: +Before importing the package, adjust the maximum recursion limit as shown below: +``` +import sys +sys.setrecursionlimit(1500) +import {{{packageName}}} +from {{{packageName}}}.apis import * +from {{{packageName}}}.models import * +``` diff --git a/python-experimental/__init__api.mustache b/python-experimental/__init__api.mustache new file mode 100644 index 0000000000..d37ee6c78b --- /dev/null +++ b/python-experimental/__init__api.mustache @@ -0,0 +1,3 @@ +# do not import all apis into this module because that uses a lot of memory and stack frames +# if you need the ability to import all models from one package, import them with +# from {{packageName}.apis import DefaultApi, PetApi \ No newline at end of file diff --git a/python-experimental/__init__apis.mustache b/python-experimental/__init__apis.mustache new file mode 100644 index 0000000000..b5b7065e1e --- /dev/null +++ b/python-experimental/__init__apis.mustache @@ -0,0 +1,19 @@ +# coding: utf-8 + +# flake8: noqa + +# import all apis into this package +# if you have many ampis here with many many models used in each api this may +# raise a RecursionError +# to avoid this, import only the api that you directly need like: +# from {{packagename}}.api.pet_api import PetApi +# or import this package, but before doing it, use: +# import sys +# sys.setrecursionlimit(n) + +# import apis into api package +{{#apiInfo}} +{{#apis}} +from {{apiPackage}}.{{classVarName}} import {{classname}} +{{/apis}} +{{/apiInfo}} \ No newline at end of file diff --git a/python-experimental/__init__model.mustache b/python-experimental/__init__model.mustache index ca86cb8a62..cfe32b7849 100644 --- a/python-experimental/__init__model.mustache +++ b/python-experimental/__init__model.mustache @@ -1,7 +1,5 @@ -# coding: utf-8 - -# flake8: noqa -{{>partial_header}} - # we can not import model classes here because that would create a circular # reference which would not work in python2 +# do not import all models into this module because that uses a lot of memory and stack frames +# if you need the ability to import all models from one package, import them with +# from {{packageName}.models import ModelA, ModelB diff --git a/python-experimental/__init__models.mustache b/python-experimental/__init__models.mustache new file mode 100644 index 0000000000..abe69dc035 --- /dev/null +++ b/python-experimental/__init__models.mustache @@ -0,0 +1,18 @@ +# coding: utf-8 + +# flake8: noqa + +# import all models into this package +# if you have many models here with many references from one model to another this may +# raise a RecursionError +# to avoid this, import only the models that you directly need like: +# from from {{modelPackage}}.pet import Pet +# or import this package, but before doing it, use: +# import sys +# sys.setrecursionlimit(n) + +{{#models}} +{{#model}} +from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} +{{/model}} +{{/models}} diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache index 1d74d016ab..a949d50850 100644 --- a/python-experimental/__init__package.mustache +++ b/python-experimental/__init__package.mustache @@ -8,13 +8,6 @@ from __future__ import absolute_import __version__ = "{{packageVersion}}" -# import apis into sdk package -{{#apiInfo}} -{{#apis}} -from {{apiPackage}}.{{classVarName}} import {{classname}} -{{/apis}} -{{/apiInfo}} - # import ApiClient from {{packageName}}.api_client import ApiClient @@ -26,14 +19,8 @@ from {{packageName}}.signing import HttpSigningConfiguration # import exceptions from {{packageName}}.exceptions import OpenApiException +from {{packageName}}.exceptions import ApiAttributeError from {{packageName}}.exceptions import ApiTypeError from {{packageName}}.exceptions import ApiValueError from {{packageName}}.exceptions import ApiKeyError -from {{packageName}}.exceptions import ApiException - -# import models into sdk package -{{#models}} -{{#model}} -from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} -{{/model}} -{{/models}} +from {{packageName}}.exceptions import ApiException \ No newline at end of file diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index ae7b8a6979..23cf85e9df 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -2,6 +2,10 @@ from __future__ import print_function import time import {{{packageName}}} +from {{apiPackage}} import {{classVarName}} +{{#imports}} +{{{.}}} +{{/imports}} from pprint import pprint {{> python_doc_auth_partial}} # Enter a context with an instance of the API client @@ -12,7 +16,7 @@ with {{{packageName}}}.ApiClient(configuration) as api_client: with {{{packageName}}}.ApiClient() as api_client: {{/hasAuthMethods}} # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) + api_instance = {{classVarName}}.{{{classname}}}(api_client) {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} diff --git a/python-experimental/api_test.mustache b/python-experimental/api_test.mustache new file mode 100644 index 0000000000..e04b32f96e --- /dev/null +++ b/python-experimental/api_test.mustache @@ -0,0 +1,36 @@ +# coding: utf-8 + +{{>partial_header}} + +from __future__ import absolute_import + +import unittest + +import {{packageName}} +from {{apiPackage}}.{{classVarName}} import {{classname}} # noqa: E501 + + +class {{#operations}}Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" + + def setUp(self): + self.api = {{classname}}() # noqa: E501 + + def tearDown(self): + pass + + {{#operation}} + def test_{{operationId}}(self): + """Test case for {{{operationId}}} + +{{#summary}} + {{{summary}}} # noqa: E501 +{{/summary}} + """ + pass + + {{/operation}} +{{/operations}} + +if __name__ == '__main__': + unittest.main() diff --git a/python-experimental/model_test.mustache b/python-experimental/model_test.mustache index 4fd1263b5f..5b9a91d2d0 100644 --- a/python-experimental/model_test.mustache +++ b/python-experimental/model_test.mustache @@ -3,12 +3,16 @@ {{>partial_header}} from __future__ import absolute_import - +import sys import unittest +import {{packageName}} {{#models}} {{#model}} -import {{packageName}} +{{#imports}} +{{{.}}} +{{/imports}} +from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} class Test{{unescapedDescription}}(unittest.TestCase): @@ -23,7 +27,7 @@ class Test{{unescapedDescription}}(unittest.TestCase): def test{{unescapedDescription}}(self): """Test {{unescapedDescription}}""" # FIXME: construct object with mandatory attributes with example values - # model = {{packageName}}.{{unescapedDescription}}() # noqa: E501 + # model = {{unescapedDescription}}() # noqa: E501 pass {{/model}} From 4e0e68b51b2a767eec3f45506ae3452e1145d033 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Thu, 4 Jun 2020 16:50:53 +0200 Subject: [PATCH 120/180] [BUG][python] Support named arrays (#6493) * [python] Support named arrays * Fix named array type * Use ModelSimple * Reset samples * Regenerated * Animal farm test * Array of enums * Clean-up * Clean-up * Clean-up * Fix array type generation * simplify * array model is not alias * Array model has one value field * ensure up-to-date * ./bin/utils/ensure-up-to-date --batch * Solve issue with missing import for array model * regenerate --- python-experimental/model.mustache | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 0790c61435..490629c5a3 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -37,7 +37,12 @@ from {{packageName}}.model_utils import ( # noqa: F401 {{> python-experimental/model_templates/model_simple }} {{/isAlias}} {{^isAlias}} +{{#isArrayModel}} +{{> python-experimental/model_templates/model_simple }} +{{/isArrayModel}} +{{^isArrayModel}} {{> python-experimental/model_templates/model_normal }} +{{/isArrayModel}} {{/isAlias}} {{/interfaces}} {{#interfaces}} From a56947578ed10024277bbcd1539be7c109be1c40 Mon Sep 17 00:00:00 2001 From: Alexey Volkov Date: Thu, 4 Jun 2020 08:46:35 -0700 Subject: [PATCH 121/180] [Python] Fixed docstrings in api.mustache (#6391) * [Python] Fixed docstrings Fixes https://github.com/swagger-api/swagger-codegen/issues/9630 * Updated generated files * Fixed python-experimental * Updated generated files * Fully fixed the format of the docstrings * Updated generated files * Updated generated files in openapi3 --- api.mustache | 23 +++++++++++++++++------ model.mustache | 2 +- python-experimental/api.mustache | 1 + python-experimental/api_client.mustache | 15 +++++++++++---- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/api.mustache b/api.mustache index f2c5541835..18ced57845 100644 --- a/api.mustache +++ b/api.mustache @@ -38,6 +38,7 @@ class {{classname}}(object): {{/notes}} This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True + {{#sortParamsByRequiredFlag}} >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} @@ -46,20 +47,24 @@ class {{classname}}(object): {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async_req bool: execute request asynchronously {{#allParams}} - :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} + :param {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} + :type {{paramName}}: {{dataType}}{{#optional}}, optional{{/optional}} {{/allParams}} + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. + :type _preload_content: bool, optional :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. - :return: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + :return: Returns the result object. If the method is called asynchronously, returns the request thread. + :rtype: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} """ kwargs['_return_http_data_only'] = True return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 @@ -72,6 +77,7 @@ class {{classname}}(object): {{/notes}} This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True + {{#sortParamsByRequiredFlag}} >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) {{/sortParamsByRequiredFlag}} @@ -80,22 +86,27 @@ class {{classname}}(object): {{/sortParamsByRequiredFlag}} >>> result = thread.get() - :param async_req bool: execute request asynchronously {{#allParams}} - :param {{dataType}} {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/optional}} + :param {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} + :type {{paramName}}: {{dataType}}{{#optional}}, optional{{/optional}} {{/allParams}} + :param async_req: Whether to execute the request asynchronously. + :type async_req: bool, optional :param _return_http_data_only: response data without head status code and headers + :type _return_http_data_only: bool, optional :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. + :type _preload_content: bool, optional :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. - :return: {{#returnType}}tuple({{returnType}}, status_code(int), headers(HTTPHeaderDict)){{/returnType}}{{^returnType}}None{{/returnType}} + :return: Returns the result object. If the method is called asynchronously, returns the request thread. + :rtype: {{#returnType}}tuple({{returnType}}, status_code(int), headers(HTTPHeaderDict)){{/returnType}}{{^returnType}}None{{/returnType}} """ {{#servers.0}} diff --git a/model.mustache b/model.mustache index 112246604d..2b3299a6f2 100644 --- a/model.mustache +++ b/model.mustache @@ -107,7 +107,7 @@ class {{classname}}(object): {{/description}} :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 - :type: {{dataType}} + :type {{name}}: {{dataType}} """ {{^isNullable}} {{#required}} diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 44fc3a8997..92e909165d 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -66,6 +66,7 @@ class {{classname}}(object): {{/notes}} This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True + >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) >>> result = thread.get() diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index 5285a7b806..d17177a832 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -291,6 +291,7 @@ class ApiClient(object): ({str: (bool, str, int, float, date, datetime, str, none_type)},) :param _check_type: boolean, whether to check the types of the data received from the server + :type _check_type: bool :return: deserialized object. """ @@ -350,22 +351,28 @@ class ApiClient(object): (float, none_type) ([int, none_type],) ({str: (bool, str, int, float, date, datetime, str, none_type)},) - :param files dict: key -> field name, value -> a list of open file + :param files: key -> field name, value -> a list of open file objects for `multipart/form-data`. + :type files: dict :param async_req bool: execute request asynchronously + :type async_req: bool, optional :param _return_http_data_only: response data without head status code and headers + :type _return_http_data_only: bool, optional :param collection_formats: dict of collection formats for path, query, header, and post parameters. + :type collection_formats: dict, optional :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. + :type _preload_content: bool, optional :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. :param _check_type: boolean describing if the data back from the server should have its type checked. + :type _check_type: bool, optional :return: If async_req parameter is True, the request will be called asynchronously. @@ -559,9 +566,9 @@ class ApiClient(object): :param headers: Header parameters dict to be updated. :param querys: Query parameters tuple list to be updated. :param auth_settings: Authentication setting identifiers list. - :resource_path: A string representation of the HTTP request resource path. - :method: A string representation of the HTTP request method. - :body: A object representing the body of the HTTP request. + :param resource_path: A string representation of the HTTP request resource path. + :param method: A string representation of the HTTP request method. + :param body: A object representing the body of the HTTP request. The object type is the return value of sanitize_for_serialization(). """ if not auth_settings: From 21847dba944a51a18071d850492118919f160a18 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Thu, 11 Jun 2020 04:06:39 +0200 Subject: [PATCH 122/180] [Python] Update docstring and fix a typo (#6612) * [Python] Update docstring and fix a typo * regenerate --- python-experimental/__init__apis.mustache | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/python-experimental/__init__apis.mustache b/python-experimental/__init__apis.mustache index b5b7065e1e..da3937f8c5 100644 --- a/python-experimental/__init__apis.mustache +++ b/python-experimental/__init__apis.mustache @@ -2,18 +2,21 @@ # flake8: noqa -# import all apis into this package -# if you have many ampis here with many many models used in each api this may -# raise a RecursionError -# to avoid this, import only the api that you directly need like: -# from {{packagename}}.api.pet_api import PetApi +# Import all APIs into this package. +# If you have many APIs here with many many models used in each API this may +# raise a `RecursionError`. +# In order to avoid this, import only the API that you directly need like: +# +# from {{packagename}}.api.pet_api import PetApi +# # or import this package, but before doing it, use: -# import sys -# sys.setrecursionlimit(n) +# +# import sys +# sys.setrecursionlimit(n) -# import apis into api package +# Import APIs into API package: {{#apiInfo}} {{#apis}} from {{apiPackage}}.{{classVarName}} import {{classname}} {{/apis}} -{{/apiInfo}} \ No newline at end of file +{{/apiInfo}} From d3a6d482e238b62cf3bffbc5ef2c1a613da961d1 Mon Sep 17 00:00:00 2001 From: Warren Gray Date: Thu, 11 Jun 2020 02:40:10 -0400 Subject: [PATCH 123/180] [python-client] Enable per-request auth settings (#6569) * Enable per-request access token in Python client. * Add missing regenerated sample files. * Rework to the more general case of overriding the auth settings for a request. * Add unit tests. * Update api_client.mustache so that request_auth overrides all other auth settings when specified. --- api.mustache | 10 ++++++-- api_client.mustache | 57 ++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/api.mustache b/api.mustache index 18ced57845..1dcbb86078 100644 --- a/api.mustache +++ b/api.mustache @@ -103,6 +103,10 @@ class {{classname}}(object): number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :type _request_auth: dict, optional :return: Returns the result object. If the method is called asynchronously, returns the request thread. @@ -137,7 +141,8 @@ class {{classname}}(object): 'async_req', '_return_http_data_only', '_preload_content', - '_request_timeout' + '_request_timeout', + '_request_auth' ] ) @@ -266,6 +271,7 @@ class {{classname}}(object): {{#servers.0}} _host=local_var_host, {{/servers.0}} - collection_formats=collection_formats) + collection_formats=collection_formats, + _request_auth=local_var_params.get('_request_auth')) {{/operation}} {{/operations}} diff --git a/api_client.mustache b/api_client.mustache index 66d3577f3c..7eb04b6943 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -132,7 +132,8 @@ class ApiClient(object): query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None): + _preload_content=True, _request_timeout=None, _host=None, + _request_auth=None): config = self.configuration @@ -173,7 +174,9 @@ class ApiClient(object): post_params.extend(self.files_parameters(files)) # auth setting - self.update_params_for_auth(header_params, query_params, auth_settings) + self.update_params_for_auth( + header_params, query_params, auth_settings, + request_auth=_request_auth) # body if body: @@ -347,7 +350,8 @@ class ApiClient(object): body=None, post_params=None, files=None, response_type=None, auth_settings=None, async_req=None, _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None): + _preload_content=True, _request_timeout=None, _host=None, + _request_auth=None): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -377,6 +381,10 @@ class ApiClient(object): number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the authentication + in the spec for a single request. + :type _request_token: dict, optional :return: If async_req parameter is True, the request will be called asynchronously. @@ -390,7 +398,8 @@ class ApiClient(object): body, post_params, files, response_type, auth_settings, _return_http_data_only, collection_formats, - _preload_content, _request_timeout, _host) + _preload_content, _request_timeout, _host, + _request_auth) return self.pool.apply_async(self.__call_api, (resource_path, method, path_params, @@ -403,7 +412,7 @@ class ApiClient(object): collection_formats, _preload_content, _request_timeout, - _host)) + _host, _request_auth)) def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, _preload_content=True, @@ -550,29 +559,45 @@ class ApiClient(object): else: return content_types[0] - def update_params_for_auth(self, headers, querys, auth_settings): + def update_params_for_auth(self, headers, querys, auth_settings, + request_auth=None): """Updates header and query params based on authentication setting. :param headers: Header parameters dict to be updated. :param querys: Query parameters tuple list to be updated. :param auth_settings: Authentication setting identifiers list. + :param request_auth: if set, the provided settings will + override the token in the configuration. """ if not auth_settings: return + if request_auth: + self._apply_auth_params(headers, querys, request_auth) + return + for auth in auth_settings: auth_setting = self.configuration.auth_settings().get(auth) if auth_setting: - if auth_setting['in'] == 'cookie': - headers['Cookie'] = auth_setting['value'] - elif auth_setting['in'] == 'header': - headers[auth_setting['key']] = auth_setting['value'] - elif auth_setting['in'] == 'query': - querys.append((auth_setting['key'], auth_setting['value'])) - else: - raise ApiValueError( - 'Authentication token must be in `query` or `header`' - ) + self._apply_auth_params(headers, querys, auth_setting) + + def _apply_auth_params(self, headers, querys, auth_setting): + """Updates the request parameters based on a single auth_setting + + :param headers: Header parameters dict to be updated. + :param querys: Query parameters tuple list to be updated. + :param auth_setting: auth settings for the endpoint + """ + if auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] + elif auth_setting['in'] == 'header': + headers[auth_setting['key']] = auth_setting['value'] + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ApiValueError( + 'Authentication token must be in `query` or `header`' + ) def __deserialize_file(self, response): """Deserializes body to file From 247544d20d2079917f8d5ca05cb768e3cccbafe9 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Thu, 11 Jun 2020 18:19:57 +0200 Subject: [PATCH 124/180] [feature][python] Support aliasing of API keys (#6469) * [python] Support aliasing of API keys * Support for aliasing and prefix * Make more realistic usage * Regenerate * Document alias in generated code * Support override of aliased keys * Use diferent id and name for api keys * ensure up-to-date * Simple example without x-auth-id-alias * regenerate docs * Regenerate * Provide separate spec for x-auth-id-alias * Apply suggestions from code review * regenerated --- configuration.mustache | 12 ++++++++---- python_doc_auth_partial.mustache | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index d1705eed25..f74ae45f28 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -423,15 +423,16 @@ conf = {{{packageName}}}.Configuration( self.__logger_format = value self.logger_formatter = logging.Formatter(self.__logger_format) - def get_api_key_with_prefix(self, identifier): + def get_api_key_with_prefix(self, identifier, alias=None): """Gets API key (with prefix if set). :param identifier: The identifier of apiKey. + :param alias: The alternative identifier of apiKey. :return: The token for api key authentication. """ if self.refresh_api_key_hook is not None: self.refresh_api_key_hook(self) - key = self.api_key.get(identifier) + key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None) if key: prefix = self.api_key_prefix.get(identifier) if prefix: @@ -462,12 +463,15 @@ conf = {{{packageName}}}.Configuration( auth = {} {{#authMethods}} {{#isApiKey}} - if '{{keyParamName}}' in self.api_key: + if '{{name}}' in self.api_key{{#vendorExtensions.x-auth-id-alias}} or '{{.}}' in self.api_key{{/vendorExtensions.x-auth-id-alias}}: auth['{{name}}'] = { 'type': 'api_key', 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, 'key': '{{keyParamName}}', - 'value': self.get_api_key_with_prefix('{{keyParamName}}') + 'value': self.get_api_key_with_prefix( + '{{name}}',{{#vendorExtensions.x-auth-id-alias}} + alias='{{.}}',{{/vendorExtensions.x-auth-id-alias}} + ), } {{/isApiKey}} {{#isBasic}} diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 3086d770b1..460c2df938 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -95,11 +95,11 @@ configuration = {{{packageName}}}.Configuration( configuration = {{{packageName}}}.Configuration( host = "{{{basePath}}}", api_key = { - '{{{keyParamName}}}': 'YOUR_API_KEY' + '{{name}}': 'YOUR_API_KEY' } ) # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer' +# configuration.api_key_prefix['{{name}}'] = 'Bearer' {{/isApiKey}} {{#isOAuth}} From 265154ebccf289a907571d7e6faf9e2e9d964bcb Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Mon, 15 Jun 2020 21:53:43 +0200 Subject: [PATCH 125/180] [Python] Add attribute_map to simple model (#6669) * [python] Add missing attribute_map definition * regenerated --- python-experimental/model_templates/model_simple.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index 95b8a81715..bc582ff796 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -11,6 +11,8 @@ class {{unescapedDescription}}(ModelSimple): {{> python-experimental/model_templates/classvars }} + attribute_map = {} + _composed_schemas = None {{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file From 2d731f53cdc30beeb303c99718cb4946d9f2f49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 16 Jun 2020 16:52:45 +0200 Subject: [PATCH 126/180] [Python] Remove duplicate definition of Endpoint class (#6667) * Remove duplicate definition of Endpoint class The class is copied in every API modules, we can share it alongside the API client. * Regenerate examples --- python-experimental/api.mustache | 226 +----------------------- python-experimental/api_client.mustache | 226 +++++++++++++++++++++++- 2 files changed, 226 insertions(+), 226 deletions(-) diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 92e909165d..3d0b4a06af 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -10,11 +10,7 @@ import sys # noqa: F401 # python 2 and python 3 compatibility library import six -from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( - ApiTypeError, - ApiValueError -) +from {{packageName}}.api_client import ApiClient, Endpoint from {{packageName}}.model_utils import ( # noqa: F401 check_allowed_values, check_validations, @@ -293,223 +289,3 @@ class {{classname}}(object): ) {{/operation}} {{/operations}} - - -class Endpoint(object): - def __init__(self, settings=None, params_map=None, root_map=None, - headers_map=None, api_client=None, callable=None): - """Creates an endpoint - - Args: - settings (dict): see below key value pairs - 'response_type' (tuple/None): response type - 'auth' (list): a list of auth type keys - 'endpoint_path' (str): the endpoint path - 'operation_id' (str): endpoint string identifier - 'http_method' (str): POST/PUT/PATCH/GET etc - 'servers' (list): list of str servers that this endpoint is at - params_map (dict): see below key value pairs - 'all' (list): list of str endpoint parameter names - 'required' (list): list of required parameter names - 'nullable' (list): list of nullable parameter names - 'enum' (list): list of parameters with enum values - 'validation' (list): list of parameters with validations - root_map - 'validations' (dict): the dict mapping endpoint parameter tuple - paths to their validation dictionaries - 'allowed_values' (dict): the dict mapping endpoint parameter - tuple paths to their allowed_values (enum) dictionaries - 'openapi_types' (dict): param_name to openapi type - 'attribute_map' (dict): param_name to camelCase name - 'location_map' (dict): param_name to 'body', 'file', 'form', - 'header', 'path', 'query' - collection_format_map (dict): param_name to `csv` etc. - headers_map (dict): see below key value pairs - 'accept' (list): list of Accept header strings - 'content_type' (list): list of Content-Type header strings - api_client (ApiClient) api client instance - callable (function): the function which is invoked when the - Endpoint is called - """ - self.settings = settings - self.params_map = params_map - self.params_map['all'].extend([ - 'async_req', - '_host_index', - '_preload_content', - '_request_timeout', - '_return_http_data_only', - '_check_input_type', - '_check_return_type' - ]) - self.params_map['nullable'].extend(['_request_timeout']) - self.validations = root_map['validations'] - self.allowed_values = root_map['allowed_values'] - self.openapi_types = root_map['openapi_types'] - extra_types = { - 'async_req': (bool,), - '_host_index': (int,), - '_preload_content': (bool,), - '_request_timeout': (none_type, int, (int,), [int]), - '_return_http_data_only': (bool,), - '_check_input_type': (bool,), - '_check_return_type': (bool,) - } - self.openapi_types.update(extra_types) - self.attribute_map = root_map['attribute_map'] - self.location_map = root_map['location_map'] - self.collection_format_map = root_map['collection_format_map'] - self.headers_map = headers_map - self.api_client = api_client - self.callable = callable - - def __validate_inputs(self, kwargs): - for param in self.params_map['enum']: - if param in kwargs: - check_allowed_values( - self.allowed_values, - (param,), - kwargs[param] - ) - - for param in self.params_map['validation']: - if param in kwargs: - check_validations( - self.validations, - (param,), - kwargs[param], - configuration=self.api_client.configuration - ) - - if kwargs['_check_input_type'] is False: - return - - for key, value in six.iteritems(kwargs): - fixed_val = validate_and_convert_types( - value, - self.openapi_types[key], - [key], - False, - kwargs['_check_input_type'], - configuration=self.api_client.configuration - ) - kwargs[key] = fixed_val - - def __gather_params(self, kwargs): - params = { - 'body': None, - 'collection_format': {}, - 'file': {}, - 'form': [], - 'header': {}, - 'path': {}, - 'query': [] - } - - for param_name, param_value in six.iteritems(kwargs): - param_location = self.location_map.get(param_name) - if param_location is None: - continue - if param_location: - if param_location == 'body': - params['body'] = param_value - continue - base_name = self.attribute_map[param_name] - if (param_location == 'form' and - self.openapi_types[param_name] == (file_type,)): - params['file'][param_name] = [param_value] - elif (param_location == 'form' and - self.openapi_types[param_name] == ([file_type],)): - # param_value is already a list - params['file'][param_name] = param_value - elif param_location in {'form', 'query'}: - param_value_full = (base_name, param_value) - params[param_location].append(param_value_full) - if param_location not in {'form', 'query'}: - params[param_location][base_name] = param_value - collection_format = self.collection_format_map.get(param_name) - if collection_format: - params['collection_format'][base_name] = collection_format - - return params - - def __call__(self, *args, **kwargs): - """ This method is invoked when endpoints are called - Example: - pet_api = PetApi() - pet_api.add_pet # this is an instance of the class Endpoint - pet_api.add_pet() # this invokes pet_api.add_pet.__call__() - which then invokes the callable functions stored in that endpoint at - pet_api.add_pet.callable or self.callable in this class - """ - return self.callable(self, *args, **kwargs) - - def call_with_http_info(self, **kwargs): - - try: - _host = self.settings['servers'][kwargs['_host_index']] - except IndexError: - if self.settings['servers']: - raise ApiValueError( - "Invalid host index. Must be 0 <= index < %s" % - len(self.settings['servers']) - ) - _host = None - - for key, value in six.iteritems(kwargs): - if key not in self.params_map['all']: - raise ApiTypeError( - "Got an unexpected parameter '%s'" - " to method `%s`" % - (key, self.settings['operation_id']) - ) - # only throw this nullable ApiValueError if _check_input_type - # is False, if _check_input_type==True we catch this case - # in self.__validate_inputs - if (key not in self.params_map['nullable'] and value is None - and kwargs['_check_input_type'] is False): - raise ApiValueError( - "Value may not be None for non-nullable parameter `%s`" - " when calling `%s`" % - (key, self.settings['operation_id']) - ) - - for key in self.params_map['required']: - if key not in kwargs.keys(): - raise ApiValueError( - "Missing the required parameter `%s` when calling " - "`%s`" % (key, self.settings['operation_id']) - ) - - self.__validate_inputs(kwargs) - - params = self.__gather_params(kwargs) - - accept_headers_list = self.headers_map['accept'] - if accept_headers_list: - params['header']['Accept'] = self.api_client.select_header_accept( - accept_headers_list) - - content_type_headers_list = self.headers_map['content_type'] - if content_type_headers_list: - header_list = self.api_client.select_header_content_type( - content_type_headers_list) - params['header']['Content-Type'] = header_list - - return self.api_client.call_api( - self.settings['endpoint_path'], self.settings['http_method'], - params['path'], - params['query'], - params['header'], - body=params['body'], - post_params=params['form'], - files=params['file'], - response_type=self.settings['response_type'], - auth_settings=self.settings['auth'], - async_req=kwargs['async_req'], - _check_type=kwargs['_check_return_type'], - _return_http_data_only=kwargs['_return_http_data_only'], - _preload_content=kwargs['_preload_content'], - _request_timeout=kwargs['_request_timeout'], - _host=_host, - collection_formats=params['collection_format']) diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index d17177a832..da5dbfb341 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -18,16 +18,20 @@ import tornado.gen from {{packageName}} import rest from {{packageName}}.configuration import Configuration -from {{packageName}}.exceptions import ApiValueError, ApiException +from {{packageName}}.exceptions import ApiTypeError, ApiValueError, ApiException from {{packageName}}.model_utils import ( ModelNormal, ModelSimple, ModelComposed, + check_allowed_values, + check_validations, date, datetime, deserialize_file, file_type, + int, model_to_dict, + none_type, str, validate_and_convert_types ) @@ -597,3 +601,223 @@ class ApiClient(object): raise ApiValueError( 'Authentication token must be in `query` or `header`' ) + + +class Endpoint(object): + def __init__(self, settings=None, params_map=None, root_map=None, + headers_map=None, api_client=None, callable=None): + """Creates an endpoint + + Args: + settings (dict): see below key value pairs + 'response_type' (tuple/None): response type + 'auth' (list): a list of auth type keys + 'endpoint_path' (str): the endpoint path + 'operation_id' (str): endpoint string identifier + 'http_method' (str): POST/PUT/PATCH/GET etc + 'servers' (list): list of str servers that this endpoint is at + params_map (dict): see below key value pairs + 'all' (list): list of str endpoint parameter names + 'required' (list): list of required parameter names + 'nullable' (list): list of nullable parameter names + 'enum' (list): list of parameters with enum values + 'validation' (list): list of parameters with validations + root_map + 'validations' (dict): the dict mapping endpoint parameter tuple + paths to their validation dictionaries + 'allowed_values' (dict): the dict mapping endpoint parameter + tuple paths to their allowed_values (enum) dictionaries + 'openapi_types' (dict): param_name to openapi type + 'attribute_map' (dict): param_name to camelCase name + 'location_map' (dict): param_name to 'body', 'file', 'form', + 'header', 'path', 'query' + collection_format_map (dict): param_name to `csv` etc. + headers_map (dict): see below key value pairs + 'accept' (list): list of Accept header strings + 'content_type' (list): list of Content-Type header strings + api_client (ApiClient) api client instance + callable (function): the function which is invoked when the + Endpoint is called + """ + self.settings = settings + self.params_map = params_map + self.params_map['all'].extend([ + 'async_req', + '_host_index', + '_preload_content', + '_request_timeout', + '_return_http_data_only', + '_check_input_type', + '_check_return_type' + ]) + self.params_map['nullable'].extend(['_request_timeout']) + self.validations = root_map['validations'] + self.allowed_values = root_map['allowed_values'] + self.openapi_types = root_map['openapi_types'] + extra_types = { + 'async_req': (bool,), + '_host_index': (int,), + '_preload_content': (bool,), + '_request_timeout': (none_type, int, (int,), [int]), + '_return_http_data_only': (bool,), + '_check_input_type': (bool,), + '_check_return_type': (bool,) + } + self.openapi_types.update(extra_types) + self.attribute_map = root_map['attribute_map'] + self.location_map = root_map['location_map'] + self.collection_format_map = root_map['collection_format_map'] + self.headers_map = headers_map + self.api_client = api_client + self.callable = callable + + def __validate_inputs(self, kwargs): + for param in self.params_map['enum']: + if param in kwargs: + check_allowed_values( + self.allowed_values, + (param,), + kwargs[param] + ) + + for param in self.params_map['validation']: + if param in kwargs: + check_validations( + self.validations, + (param,), + kwargs[param], + configuration=self.api_client.configuration + ) + + if kwargs['_check_input_type'] is False: + return + + for key, value in six.iteritems(kwargs): + fixed_val = validate_and_convert_types( + value, + self.openapi_types[key], + [key], + False, + kwargs['_check_input_type'], + configuration=self.api_client.configuration + ) + kwargs[key] = fixed_val + + def __gather_params(self, kwargs): + params = { + 'body': None, + 'collection_format': {}, + 'file': {}, + 'form': [], + 'header': {}, + 'path': {}, + 'query': [] + } + + for param_name, param_value in six.iteritems(kwargs): + param_location = self.location_map.get(param_name) + if param_location is None: + continue + if param_location: + if param_location == 'body': + params['body'] = param_value + continue + base_name = self.attribute_map[param_name] + if (param_location == 'form' and + self.openapi_types[param_name] == (file_type,)): + params['file'][param_name] = [param_value] + elif (param_location == 'form' and + self.openapi_types[param_name] == ([file_type],)): + # param_value is already a list + params['file'][param_name] = param_value + elif param_location in {'form', 'query'}: + param_value_full = (base_name, param_value) + params[param_location].append(param_value_full) + if param_location not in {'form', 'query'}: + params[param_location][base_name] = param_value + collection_format = self.collection_format_map.get(param_name) + if collection_format: + params['collection_format'][base_name] = collection_format + + return params + + def __call__(self, *args, **kwargs): + """ This method is invoked when endpoints are called + Example: + pet_api = PetApi() + pet_api.add_pet # this is an instance of the class Endpoint + pet_api.add_pet() # this invokes pet_api.add_pet.__call__() + which then invokes the callable functions stored in that endpoint at + pet_api.add_pet.callable or self.callable in this class + """ + return self.callable(self, *args, **kwargs) + + def call_with_http_info(self, **kwargs): + + try: + _host = self.settings['servers'][kwargs['_host_index']] + except IndexError: + if self.settings['servers']: + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" % + len(self.settings['servers']) + ) + _host = None + + for key, value in six.iteritems(kwargs): + if key not in self.params_map['all']: + raise ApiTypeError( + "Got an unexpected parameter '%s'" + " to method `%s`" % + (key, self.settings['operation_id']) + ) + # only throw this nullable ApiValueError if _check_input_type + # is False, if _check_input_type==True we catch this case + # in self.__validate_inputs + if (key not in self.params_map['nullable'] and value is None + and kwargs['_check_input_type'] is False): + raise ApiValueError( + "Value may not be None for non-nullable parameter `%s`" + " when calling `%s`" % + (key, self.settings['operation_id']) + ) + + for key in self.params_map['required']: + if key not in kwargs.keys(): + raise ApiValueError( + "Missing the required parameter `%s` when calling " + "`%s`" % (key, self.settings['operation_id']) + ) + + self.__validate_inputs(kwargs) + + params = self.__gather_params(kwargs) + + accept_headers_list = self.headers_map['accept'] + if accept_headers_list: + params['header']['Accept'] = self.api_client.select_header_accept( + accept_headers_list) + + content_type_headers_list = self.headers_map['content_type'] + if content_type_headers_list: + header_list = self.api_client.select_header_content_type( + content_type_headers_list) + params['header']['Content-Type'] = header_list + + return self.api_client.call_api( + self.settings['endpoint_path'], self.settings['http_method'], + params['path'], + params['query'], + params['header'], + body=params['body'], + post_params=params['form'], + files=params['file'], + response_type=self.settings['response_type'], + auth_settings=self.settings['auth'], + async_req=kwargs['async_req'], + _check_type=kwargs['_check_return_type'], + _return_http_data_only=kwargs['_return_http_data_only'], + _preload_content=kwargs['_preload_content'], + _request_timeout=kwargs['_request_timeout'], + _host=_host, + collection_formats=params['collection_format']) From 57f64fc96f55ffef1253ce065e8001eefeeff738 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Mon, 22 Jun 2020 20:07:18 +0200 Subject: [PATCH 127/180] [Python] enum serialization (#6746) * [Python] enum serialization * Fix serialization of nested enum --- python-experimental/model_utils.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index b1db9b329c..58859114bd 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -951,7 +951,7 @@ def is_type_nullable(input_type): if issubclass(input_type, OpenApiModel) and input_type._nullable: return True if issubclass(input_type, ModelComposed): - # If oneOf/anyOf, check if the 'null' type is one of the allowed types. + # If oneOf/anyOf, check if the 'null' type is one of the allowed types. for t in input_type._composed_schemas.get('oneOf', ()): if is_type_nullable(t): return True for t in input_type._composed_schemas.get('anyOf', ()): @@ -975,7 +975,7 @@ def is_valid_type(input_class_simple, valid_classes): input_class_simple is none_type): for valid_class in valid_classes: if input_class_simple is none_type and is_type_nullable(valid_class): - # Schema is oneOf/anyOf and the 'null' type is one of the allowed types. + # Schema is oneOf/anyOf and the 'null' type is one of the allowed types. return True if not (issubclass(valid_class, OpenApiModel) and valid_class.discriminator): continue @@ -1138,6 +1138,8 @@ def model_to_dict(model_instance, serialize=True): if hasattr(item[1], '_data_store') else item, value.items() )) + elif isinstance(value, ModelSimple): + result[attr] = value.value elif hasattr(value, '_data_store'): result[attr] = model_to_dict(value, serialize=serialize) else: From 3d3d771ed53c28eb6370acaeafb1b9b239c02152 Mon Sep 17 00:00:00 2001 From: Jiri Kuncar Date: Fri, 26 Jun 2020 06:28:54 +0200 Subject: [PATCH 128/180] [Python] Support for per-operation servers (#6557) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Dynamic server support * regenerated * Apply suggestions from code review Co-authored-by: Thomas Hervé * regenerated * Add ParameterizedServer feature to Python experimental * Fix lookup of server variables * Add tests and change default value for servers * Fix server variables * Return base path when index is None * Use HOST * Apply suggestions from code review * Apply suggestions from code review * regenerated * Add specific tests for dynamic servers * regenerated * add docstring * regenerated * Fix wrong merge resolution Co-authored-by: Thomas Hervé --- configuration.mustache | 44 ++++++++++++++++++++++--- python-experimental/api.mustache | 34 ++++++++++++++++--- python-experimental/api_client.mustache | 12 +++++-- 3 files changed, 78 insertions(+), 12 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index f74ae45f28..6afe91d027 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -67,6 +67,15 @@ class Configuration(object): :param signing_info: Configuration parameters for the HTTP signature security scheme. Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration {{/hasHttpSignatureMethods}} + :param server_index: Index to servers configuration. + :param server_variables: Mapping with string values to replace variables in + templated server configuration. The validation of enums is performed for + variables with defined enum values before. + :param server_operation_index: Mapping from operation ID to an index to server + configuration. + :param server_operation_variables: Mapping from operation ID to a mapping with + string values to replace variables in templated server configuration. + The validation of enums is performed for variables with defined enum values before. {{#hasAuthMethods}} :Example: @@ -155,7 +164,7 @@ conf = {{{packageName}}}.Configuration( _default = None - def __init__(self, host="{{{basePath}}}", + def __init__(self, host=None, api_key=None, api_key_prefix=None, username=None, password=None, discard_unknown_keys=False, @@ -163,12 +172,22 @@ conf = {{{packageName}}}.Configuration( {{#hasHttpSignatureMethods}} signing_info=None, {{/hasHttpSignatureMethods}} + server_index=None, server_variables=None, + server_operation_index=None, server_operation_variables=None, ): """Constructor """ - self.host = host + self._base_path = "{{{basePath}}}" if host is None else host """Default Base url """ + self.server_index = 0 if server_index is None and host is None else server_index + self.server_operation_index = server_operation_index or {} + """Default server index + """ + self.server_variables = server_variables or {} + self.server_operation_variables = server_operation_variables or {} + """Default server variables + """ self.temp_folder_path = None """Temp file folder for downloading files """ @@ -565,14 +584,18 @@ conf = {{{packageName}}}.Configuration( {{/servers}} ] - def get_host_from_settings(self, index, variables=None): + def get_host_from_settings(self, index, variables=None, servers=None): """Gets host URL based on the index and variables :param index: array index of the host settings :param variables: hash of variable and the corresponding value + :param servers: an array of host settings or None :return: URL based on host settings """ + if index is None: + return self._base_path + variables = {} if variables is None else variables - servers = self.get_host_settings() + servers = self.get_host_settings() if servers is None else servers try: server = servers[index] @@ -584,7 +607,7 @@ conf = {{{packageName}}}.Configuration( url = server['url'] # go through variables and replace placeholders - for variable_name, variable in server['variables'].items(): + for variable_name, variable in server.get('variables', {}).items(): used_value = variables.get( variable_name, variable['default_value']) @@ -599,3 +622,14 @@ conf = {{{packageName}}}.Configuration( url = url.replace("{" + variable_name + "}", used_value) return url + + @property + def host(self): + """Return generated host.""" + return self.get_host_from_settings(self.server_index, variables=self.server_variables) + + @host.setter + def host(self, value): + """Fix base path.""" + self._base_path = value + self.server_index = None diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 3d0b4a06af..ad5decabf0 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -99,9 +99,9 @@ class {{classname}}(object): _check_return_type (bool): specifies if type checking should be done one the data received from the server. Default is True. - _host_index (int): specifies the index of the server + _host_index (int/None): specifies the index of the server that we want to use. - Default is 0. + Default is read from the configuration. async_req (bool): execute request asynchronously Returns: @@ -127,7 +127,7 @@ class {{classname}}(object): kwargs['_check_return_type'] = kwargs.get( '_check_return_type', True ) - kwargs['_host_index'] = kwargs.get('_host_index', 0) + kwargs['_host_index'] = kwargs.get('_host_index') {{#requiredParams}} kwargs['{{paramName}}'] = \ {{paramName}} @@ -156,13 +156,37 @@ class {{classname}}(object): {{#-first}} 'servers': [ {{/-first}} - '{{{url}}}'{{^-last}},{{/-last}} + { + 'url': "{{{url}}}", + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + 'variables': { + {{/-first}} + '{{{name}}}': { + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + 'default_value': "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + 'enum_values': [ + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ] + {{/-last}} + {{/enumValues}} + }{{^-last}},{{/-last}} + {{#-last}} + } + {{/-last}} + {{/variables}} + }, {{#-last}} ] {{/-last}} {{/servers}} {{^servers}} - 'servers': [], + 'servers': None, {{/servers}} }, params_map={ diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index da5dbfb341..d3b0b6f60e 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -656,7 +656,7 @@ class Endpoint(object): self.openapi_types = root_map['openapi_types'] extra_types = { 'async_req': (bool,), - '_host_index': (int,), + '_host_index': (none_type, int), '_preload_content': (bool,), '_request_timeout': (none_type, int, (int,), [int]), '_return_http_data_only': (bool,), @@ -755,7 +755,15 @@ class Endpoint(object): def call_with_http_info(self, **kwargs): try: - _host = self.settings['servers'][kwargs['_host_index']] + index = self.api_client.configuration.server_operation_index.get( + self.settings['operation_id'], self.api_client.configuration.server_index + ) if kwargs['_host_index'] is None else kwargs['_host_index'] + server_variables = self.api_client.configuration.server_operation_variables.get( + self.settings['operation_id'], self.api_client.configuration.server_variables + ) + _host = self.api_client.configuration.get_host_from_settings( + index, variables=server_variables, servers=self.settings['servers'] + ) except IndexError: if self.settings['servers']: raise ApiValueError( From 9e15550767ab2ea52d44ecd45f7217fcb06e3e97 Mon Sep 17 00:00:00 2001 From: Matthew Davis <7035647+mdavis-xyz@users.noreply.github.com> Date: Fri, 3 Jul 2020 20:39:53 +1000 Subject: [PATCH 129/180] clarify direction of py client side validation flag (#6850) * clarify direction of py client side validation flag * change pet store py cli validation disable example Co-authored-by: Matthew Davis Co-authored-by: EC2 Default User --- configuration.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration.mustache b/configuration.mustache index 6afe91d027..8025a1b655 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -299,7 +299,7 @@ conf = {{{packageName}}}.Configuration( self.retries = None """Adding retries to override urllib3 default value 3 """ - # Disable client side validation + # Enable client side validation self.client_side_validation = True def __deepcopy__(self, memo): From b669e224c83b6d08c70aff9217d1cde59cd9d58c Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sat, 18 Jul 2020 10:13:22 -0700 Subject: [PATCH 130/180] Python-exp remove codegemodel mutation, allow mixed OneOf types (#6797) * Stops converting primitive models into object models, adds ComposedSchemas with mixed type * Samples update for python-exp --- python-experimental/model.mustache | 15 +- python-experimental/model_doc.mustache | 9 + .../model_templates/classvars.mustache | 87 +++----- .../docstring_init_required_kwargs.mustache | 30 +++ .../method_init_normal.mustache | 3 + .../method_init_shared.mustache | 31 +-- .../method_init_simple.mustache | 66 ++++++ .../model_templates/model_simple.mustache | 2 +- .../model_templates/validations.mustache | 28 +++ python-experimental/model_utils.mustache | 206 ++++++++++++++---- 10 files changed, 343 insertions(+), 134 deletions(-) create mode 100644 python-experimental/model_templates/docstring_init_required_kwargs.mustache create mode 100644 python-experimental/model_templates/method_init_simple.mustache create mode 100644 python-experimental/model_templates/validations.mustache diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 490629c5a3..e89b3d5633 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -33,17 +33,22 @@ from {{packageName}}.model_utils import ( # noqa: F401 {{^interfaces}} -{{#isAlias}} -{{> python-experimental/model_templates/model_simple }} -{{/isAlias}} -{{^isAlias}} {{#isArrayModel}} {{> python-experimental/model_templates/model_simple }} {{/isArrayModel}} +{{#isEnum}} +{{> python-experimental/model_templates/model_simple }} +{{/isEnum}} +{{#isAlias}} +{{> python-experimental/model_templates/model_simple }} +{{/isAlias}} {{^isArrayModel}} +{{^isEnum}} +{{^isAlias}} {{> python-experimental/model_templates/model_normal }} -{{/isArrayModel}} {{/isAlias}} +{{/isEnum}} +{{/isArrayModel}} {{/interfaces}} {{#interfaces}} {{#-last}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index a1e57131bc..b5aa50c432 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -5,6 +5,15 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- +{{#isEnum}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} +{{/isEnum}} +{{#isAlias}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} +{{/isAlias}} +{{#isArrayModel}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}.md){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} +{{/isArrayModel}} {{#requiredVars}} {{^defaultValue}} **{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 9fc3f83433..5186e6621f 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -1,4 +1,16 @@ allowed_values = { +{{#isEnum}} + ('value',): { +{{#isNullable}} + 'None': None, +{{/isNullable}} +{{#allowableValues}} +{{#enumVars}} + '{{name}}': {{{value}}}, +{{/enumVars}} +{{/allowableValues}} + }, +{{/isEnum}} {{#requiredVars}} {{#isEnum}} ('{{name}}',): { @@ -30,70 +42,24 @@ } validations = { +{{#isAlias}} +{{^isEnum}} +{{^isArrayModel}} + ('value',): { +{{> python-experimental/model_templates/validations }} +{{/isArrayModel}} +{{/isEnum}} +{{/isAlias}} {{#requiredVars}} {{#hasValidation}} ('{{name}}',): { -{{#maxLength}} - 'max_length': {{maxLength}}, -{{/maxLength}} -{{#minLength}} - 'min_length': {{minLength}}, -{{/minLength}} -{{#maxItems}} - 'max_items': {{maxItems}}, -{{/maxItems}} -{{#minItems}} - 'min_items': {{minItems}}, -{{/minItems}} -{{#maximum}} - {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, -{{/maximum}} -{{#minimum}} - {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, -{{/minimum}} -{{#pattern}} - 'regex': { - 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} - {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} - }, -{{/pattern}} -{{#multipleOf}} - 'multiple_of': {{multipleOf}}, -{{/multipleOf}} - }, +{{> python-experimental/model_templates/validations }} {{/hasValidation}} {{/requiredVars}} {{#optionalVars}} {{#hasValidation}} ('{{name}}',): { -{{#maxLength}} - 'max_length': {{maxLength}}, -{{/maxLength}} -{{#minLength}} - 'min_length': {{minLength}}, -{{/minLength}} -{{#maxItems}} - 'max_items': {{maxItems}}, -{{/maxItems}} -{{#minItems}} - 'min_items': {{minItems}}, -{{/minItems}} -{{#maximum}} - {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, -{{/maximum}} -{{#minimum}} - {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, -{{/minimum}} -{{#pattern}} - 'regex': { - 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} - {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} - }, -{{/pattern}} -{{#multipleOf}} - 'multiple_of': {{multipleOf}}, -{{/multipleOf}} - }, +{{> python-experimental/model_templates/validations }} {{/hasValidation}} {{/optionalVars}} } @@ -113,6 +79,15 @@ and the value is attribute type. """ return { +{{#isAlias}} + 'value': ({{{dataType}}},), +{{/isAlias}} +{{#isEnum}} + 'value': ({{{dataType}}},), +{{/isEnum}} +{{#isArrayModel}} + 'value': ({{{dataType}}},), +{{/isArrayModel}} {{#requiredVars}} '{{name}}': ({{{dataType}}},), # noqa: E501 {{/requiredVars}} diff --git a/python-experimental/model_templates/docstring_init_required_kwargs.mustache b/python-experimental/model_templates/docstring_init_required_kwargs.mustache new file mode 100644 index 0000000000..b09f3950b9 --- /dev/null +++ b/python-experimental/model_templates/docstring_init_required_kwargs.mustache @@ -0,0 +1,30 @@ + _check_type (bool): if True, values for parameters in openapi_types + will be type checked and a TypeError will be + raised if the wrong type is input. + Defaults to True + _path_to_item (tuple/list): This is a list of keys or values to + drill down to the model in received_data + when deserializing a response + _spec_property_naming (bool): True if the variable names in the input data + are serialized names, as specified in the OpenAPI document. + False if the variable names in the input data + are pythonic names, e.g. snake case (default) + _configuration (Configuration): the instance to use when + deserializing a file_type parameter. + If passed, type conversion is attempted + If omitted no type conversion is done. + _visited_composed_classes (tuple): This stores a tuple of + classes that we have traveled through so that + if we see that class again we will not use its + discriminator again. + When traveling through a discriminator, the + composed schema that is + is traveled through is added to this set. + For example if Animal has a discriminator + petType and we pass in "Dog", and the class Dog + allOf includes Animal, we move through Animal + once using the discriminator, and pick Dog. + Then in Dog, we will make an instance of the + Animal class but this time we won't travel + through its discriminator because we passed in + _visited_composed_classes = (Animal,) \ No newline at end of file diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index 9a3aeaefea..7faf7a30ee 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -9,6 +9,9 @@ {{> python-experimental/model_templates/method_init_shared }} +{{#isEnum}} + self.value = value +{{/isEnum}} {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} diff --git a/python-experimental/model_templates/method_init_shared.mustache b/python-experimental/model_templates/method_init_shared.mustache index 78059150f2..e500b11e70 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/python-experimental/model_templates/method_init_shared.mustache @@ -19,36 +19,7 @@ {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{/defaultValue}} {{/requiredVars}} - _check_type (bool): if True, values for parameters in openapi_types - will be type checked and a TypeError will be - raised if the wrong type is input. - Defaults to True - _path_to_item (tuple/list): This is a list of keys or values to - drill down to the model in received_data - when deserializing a response - _spec_property_naming (bool): True if the variable names in the input data - are serialized names, as specified in the OpenAPI document. - False if the variable names in the input data - are pythonic names, e.g. snake case (default) - _configuration (Configuration): the instance to use when - deserializing a file_type parameter. - If passed, type conversion is attempted - If omitted no type conversion is done. - _visited_composed_classes (tuple): This stores a tuple of - classes that we have traveled through so that - if we see that class again we will not use its - discriminator again. - When traveling through a discriminator, the - composed schema that is - is traveled through is added to this set. - For example if Animal has a discriminator - petType and we pass in "Dog", and the class Dog - allOf includes Animal, we move through Animal - once using the discriminator, and pick Dog. - Then in Dog, we will make an instance of the - Animal class but this time we won't travel - through its discriminator because we passed in - _visited_composed_classes = (Animal,) +{{> python-experimental/model_templates/docstring_init_required_kwargs }} {{#optionalVars}} {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 {{/optionalVars}} diff --git a/python-experimental/model_templates/method_init_simple.mustache b/python-experimental/model_templates/method_init_simple.mustache new file mode 100644 index 0000000000..9d59b7ba09 --- /dev/null +++ b/python-experimental/model_templates/method_init_simple.mustache @@ -0,0 +1,66 @@ + required_properties = set([ + '_data_store', + '_check_type', + '_spec_property_naming', + '_path_to_item', + '_configuration', + '_visited_composed_classes', + ]) + + @convert_js_args_to_python_args + def __init__(self{{#hasRequired}}, value{{/hasRequired}}, *args, **kwargs): + """{{classname}} - a model defined in OpenAPI + +{{#hasRequired}} + Args: + value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 + +{{/hasRequired}} + Keyword Args: +{{^hasRequired}} + value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 +{{/hasRequired}} +{{> python-experimental/model_templates/docstring_init_required_kwargs }} + """ + +{{^hasRequired}} + if 'value' in kwargs: + value = kwargs.pop('value') + elif args: + args = list(args) + value = args.pop(0) + else: + value = {{{defaultValue}}} +{{/hasRequired}} + _check_type = kwargs.pop('_check_type', True) + _spec_property_naming = kwargs.pop('_spec_property_naming', False) + _path_to_item = kwargs.pop('_path_to_item', ()) + _configuration = kwargs.pop('_configuration', None) + _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) + + if args: + raise ApiTypeError( + "Invalid positional arguments=%s passed to %s. Remove those invalid positional arguments." % ( + args, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) + + self._data_store = {} + self._check_type = _check_type + self._spec_property_naming = _spec_property_naming + self._path_to_item = _path_to_item + self._configuration = _configuration + self._visited_composed_classes = _visited_composed_classes + (self.__class__,) + self.value = value + if kwargs: + raise ApiTypeError( + "Invalid named arguments=%s passed to %s. Remove those invalid named arguments." % ( + kwargs, + self.__class__.__name__, + ), + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) \ No newline at end of file diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index bc582ff796..1623ca5f6e 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -15,4 +15,4 @@ class {{unescapedDescription}}(ModelSimple): _composed_schemas = None -{{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file +{{> python-experimental/model_templates/method_init_simple}} \ No newline at end of file diff --git a/python-experimental/model_templates/validations.mustache b/python-experimental/model_templates/validations.mustache new file mode 100644 index 0000000000..6b91bffe22 --- /dev/null +++ b/python-experimental/model_templates/validations.mustache @@ -0,0 +1,28 @@ +{{#maxLength}} + 'max_length': {{maxLength}}, +{{/maxLength}} +{{#minLength}} + 'min_length': {{minLength}}, +{{/minLength}} +{{#maxItems}} + 'max_items': {{maxItems}}, +{{/maxItems}} +{{#minItems}} + 'min_items': {{minItems}}, +{{/minItems}} +{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}}, +{{/maximum}} +{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}}, +{{/minimum}} +{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + }, +{{/pattern}} +{{#multipleOf}} + 'multiple_of': {{multipleOf}}, +{{/multipleOf}} + }, \ No newline at end of file diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 58859114bd..1323b72499 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -54,6 +54,58 @@ class cached_property(object): return result +PRIMITIVE_TYPES = (list, float, int, bool, datetime, date, str, file_type) + +def allows_single_value_input(cls): + """ + This function returns True if the input composed schema model or any + descendant model allows a value only input + This is true for cases where oneOf contains items like: + oneOf: + - float + - NumberWithValidation + - StringEnum + - ArrayModel + - null + TODO: lru_cache this + """ + if ( + issubclass(cls, ModelSimple) or + cls in PRIMITIVE_TYPES + ): + return True + elif issubclass(cls, ModelComposed): + if not cls._composed_schemas['oneOf']: + return False + return any(allows_single_value_input(c) for c in cls._composed_schemas['oneOf']) + return False + +def composed_model_input_classes(cls): + """ + This function returns a list of the possible models that can be accepted as + inputs. + TODO: lru_cache this + """ + if issubclass(cls, ModelSimple) or cls in PRIMITIVE_TYPES: + return [cls] + elif issubclass(cls, ModelNormal): + if cls.discriminator is None: + return [cls] + else: + return get_discriminated_classes(cls) + elif issubclass(cls, ModelComposed): + if not cls._composed_schemas['oneOf']: + return [] + if cls.discriminator is None: + input_classes = [] + for c in cls._composed_schemas['oneOf']: + input_classes.extend(composed_model_input_classes(c)) + return input_classes + else: + return get_discriminated_classes(cls) + return [] + + class OpenApiModel(object): """The base class for all OpenAPIModels""" @@ -66,9 +118,17 @@ class OpenApiModel(object): # pick a new schema/class to instantiate because a discriminator # propertyName value was passed in - if len(args) == 1 and args[0] is None and is_type_nullable(cls): - # The input data is the 'null' value and the type is nullable. - return None + if len(args) == 1: + arg = args[0] + if arg is None and is_type_nullable(cls): + # The input data is the 'null' value and the type is nullable. + return None + + if issubclass(cls, ModelComposed) and allows_single_value_input(cls): + model_kwargs = {} + oneof_instance = get_oneof_instance(cls, model_kwargs, kwargs, model_arg=arg) + return oneof_instance + visited_composed_classes = kwargs.get('_visited_composed_classes', ()) if ( @@ -241,6 +301,10 @@ UPCONVERSION_TYPE_PAIRS = ( (int, float), # A float may be serialized as an integer, e.g. '3' is a valid serialized float. (list, ModelComposed), (dict, ModelComposed), + (str, ModelComposed), + (int, ModelComposed), + (float, ModelComposed), + (list, ModelComposed), (list, ModelNormal), (dict, ModelNormal), (str, ModelSimple), @@ -619,20 +683,53 @@ def remove_uncoercible(required_types_classes, current_item, spec_property_namin results_classes.append(required_type_class) return results_classes +def get_discriminated_classes(cls): + """ + Returns all the classes that a discriminator converts to + TODO: lru_cache this + """ + possible_classes = [] + key = list(cls.discriminator.keys())[0] + if is_type_nullable(cls): + possible_classes.append(cls) + for discr_cls in cls.discriminator[key].values(): + if hasattr(discr_cls, 'discriminator') and discr_cls.discriminator is not None: + possible_classes.extend(get_discriminated_classes(discr_cls)) + else: + possible_classes.append(discr_cls) + return possible_classes + + +def get_possible_classes(cls, from_server_context): + # TODO: lru_cache this + possible_classes = [cls] + if from_server_context: + return possible_classes + if hasattr(cls, 'discriminator') and cls.discriminator is not None: + possible_classes = [] + possible_classes.extend(get_discriminated_classes(cls)) + elif issubclass(cls, ModelComposed): + possible_classes.extend(composed_model_input_classes(cls)) + return possible_classes -def get_required_type_classes(required_types_mixed): + +def get_required_type_classes(required_types_mixed, spec_property_naming): """Converts the tuple required_types into a tuple and a dict described below Args: required_types_mixed (tuple/list): will contain either classes or instance of list or dict + spec_property_naming (bool): if True these values came from the + server, and we use the data types in our endpoints. + If False, we are client side and we need to include + oneOf and discriminator classes inside the data types in our endpoints Returns: (valid_classes, dict_valid_class_to_child_types_mixed): valid_classes (tuple): the valid classes that the current item should be - dict_valid_class_to_child_types_mixed (doct): + dict_valid_class_to_child_types_mixed (dict): valid_class (class): this is the key child_types_mixed (list/dict/tuple): describes the valid child types @@ -650,7 +747,7 @@ def get_required_type_classes(required_types_mixed): valid_classes.append(dict) child_req_types_by_current_type[dict] = required_type[str] else: - valid_classes.append(required_type) + valid_classes.extend(get_possible_classes(required_type, spec_property_naming)) return tuple(valid_classes), child_req_types_by_current_type @@ -803,7 +900,7 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, """Deserializes model_data to model instance. Args: - model_data (list/dict): data to instantiate the model + model_data (int/str/float/bool/none_type/list/dict): data to instantiate the model model_class (OpenApiModel): the model class path_to_item (list): path to the model in the received data check_type (bool): whether to check the data tupe for the values in @@ -829,14 +926,14 @@ def deserialize_model(model_data, model_class, path_to_item, check_type, _spec_property_naming=spec_property_naming) if issubclass(model_class, ModelSimple): - instance = model_class(value=model_data, **kw_args) - return instance - if isinstance(model_data, list): - instance = model_class(*model_data, **kw_args) + return model_class(model_data, **kw_args) + elif isinstance(model_data, list): + return model_class(*model_data, **kw_args) if isinstance(model_data, dict): kw_args.update(model_data) - instance = model_class(**kw_args) - return instance + return model_class(**kw_args) + elif isinstance(model_data, PRIMITIVE_TYPES): + return model_class(model_data, **kw_args) def deserialize_file(response_data, configuration, content_disposition=None): @@ -1019,7 +1116,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, Raises: ApiTypeError """ - results = get_required_type_classes(required_types_mixed) + results = get_required_type_classes(required_types_mixed, spec_property_naming) valid_classes, child_req_types_by_current_type = results input_class_simple = get_simple_class(input_value) @@ -1256,7 +1353,7 @@ def get_allof_instances(self, model_args, constant_args): return composed_instances -def get_oneof_instance(self, model_args, constant_args): +def get_oneof_instance(cls, model_kwargs, constant_kwargs, model_arg=None): """ Find the oneOf schema that matches the input data (e.g. payload). If exactly one schema matches the input data, an instance of that schema @@ -1264,25 +1361,33 @@ def get_oneof_instance(self, model_args, constant_args): If zero or more than one schema match the input data, an exception is raised. In OAS 3.x, the payload MUST, by validation, match exactly one of the schemas described by oneOf. + Args: - self: the class we are handling - model_args (dict): var_name to var_value + cls: the class we are handling + model_kwargs (dict): var_name to var_value The input data, e.g. the payload that must match a oneOf schema in the OpenAPI document. - constant_args (dict): var_name to var_value + constant_kwargs (dict): var_name to var_value args that every model requires, including configuration, server and path to item. + Kwargs: + model_arg: (int, float, bool, str, date, datetime, ModelSimple, None): + the value to assign to a primitive class or ModelSimple class + Notes: + - this is only passed in when oneOf includes types which are not object + - None is used to suppress handling of model_arg, nullable models are handled in __new__ + Returns oneof_instance (instance) """ - if len(self._composed_schemas['oneOf']) == 0: + if len(cls._composed_schemas['oneOf']) == 0: return None oneof_instances = [] # Iterate over each oneOf schema and determine if the input data # matches the oneOf schemas. - for oneof_class in self._composed_schemas['oneOf']: + for oneof_class in cls._composed_schemas['oneOf']: # The composed oneOf schema allows the 'null' type and the input data # is the null value. This is a OAS >= 3.1 feature. if oneof_class is none_type: @@ -1290,28 +1395,45 @@ def get_oneof_instance(self, model_args, constant_args): # none_type deserialization is handled in the __new__ method continue - # transform js keys from input data to python keys in fixed_model_args - fixed_model_args = change_keys_js_to_python( - model_args, oneof_class) - - # Extract a dict with the properties that are declared in the oneOf schema. - # Undeclared properties (e.g. properties that are allowed because of the - # additionalProperties attribute in the OAS document) are not added to - # the dict. - kwargs = {} - var_names = set(oneof_class.openapi_types.keys()) - for var_name in var_names: - if var_name in fixed_model_args: - kwargs[var_name] = fixed_model_args[var_name] + single_value_input = allows_single_value_input(oneof_class) + + if not single_value_input: + # transform js keys from input data to python keys in fixed_model_args + fixed_model_args = change_keys_js_to_python( + model_kwargs, oneof_class) + + # Extract a dict with the properties that are declared in the oneOf schema. + # Undeclared properties (e.g. properties that are allowed because of the + # additionalProperties attribute in the OAS document) are not added to + # the dict. + kwargs = {} + var_names = set(oneof_class.openapi_types.keys()) + for var_name in var_names: + if var_name in fixed_model_args: + kwargs[var_name] = fixed_model_args[var_name] + + # do not try to make a model with no input args + if len(kwargs) == 0: + continue - # do not try to make a model with no input args - if len(kwargs) == 0: - continue + # and use it to make the instance + kwargs.update(constant_kwargs) - # and use it to make the instance - kwargs.update(constant_args) try: - oneof_instance = oneof_class(**kwargs) + if not single_value_input: + oneof_instance = oneof_class(**kwargs) + else: + if issubclass(oneof_class, ModelSimple): + oneof_instance = oneof_class(model_arg, **constant_kwargs) + elif oneof_class in PRIMITIVE_TYPES: + oneof_instance = validate_and_convert_types( + model_arg, + (oneof_class,), + constant_kwargs['_path_to_item'], + constant_kwargs['_spec_property_naming'], + constant_kwargs['_check_type'], + configuration=constant_kwargs['_configuration'] + ) oneof_instances.append(oneof_instance) except Exception: pass @@ -1319,13 +1441,13 @@ def get_oneof_instance(self, model_args, constant_args): raise ApiValueError( "Invalid inputs given to generate an instance of %s. None " "of the oneOf schemas matched the input data." % - self.__class__.__name__ + cls.__name__ ) elif len(oneof_instances) > 1: raise ApiValueError( "Invalid inputs given to generate an instance of %s. Multiple " "oneOf schemas matched the inputs, but a max of one is allowed." % - self.__class__.__name__ + cls.__name__ ) return oneof_instances[0] @@ -1465,7 +1587,7 @@ def validate_get_composed_info(constant_args, model_args, self): composed_instances = [] allof_instances = get_allof_instances(self, model_args, constant_args) composed_instances.extend(allof_instances) - oneof_instance = get_oneof_instance(self, model_args, constant_args) + oneof_instance = get_oneof_instance(self.__class__, model_args, constant_args) if oneof_instance is not None: composed_instances.append(oneof_instance) anyof_instances = get_anyof_instances(self, model_args, constant_args) From 145902c7902a3f80a835317c4497599e5fb048b3 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 19 Jul 2020 09:45:56 -0700 Subject: [PATCH 131/180] [python-experimental] Removes python2 (#6991) * Removes future from python-exp v3 sample * Removes future from python-exp v2 sample * Deletes future from remaining python-exp files * Removes six from python-exp templates * Removes six from python-exp samples * Removes mock from python-exp * Python-exp switched to py3 * Removes python 2.7 for python-exp ci testing * Requires python>=3.3 for python-exp * Reverts unnecessary changes to two templates --- python-experimental/README.mustache | 2 +- python-experimental/README_common.mustache | 1 - .../README_onlypackage.mustache | 1 - python-experimental/__init__api.mustache | 2 +- python-experimental/__init__package.mustache | 2 - python-experimental/api.mustache | 7 - python-experimental/api_client.mustache | 27 +- python-experimental/api_doc_example.mustache | 1 - python-experimental/api_test.mustache | 2 - python-experimental/configuration.mustache | 632 ++++++++++++++++++ python-experimental/exceptions.mustache | 129 ++++ python-experimental/gitlab-ci.mustache | 35 + python-experimental/model.mustache | 4 - .../method_init_composed.mustache | 2 +- .../method_init_normal.mustache | 2 +- .../methods_todict_tostr_eq_shared.mustache | 7 +- .../methods_tostr_eq_simple.mustache | 8 +- python-experimental/model_test.mustache | 1 - python-experimental/model_utils.mustache | 54 +- python-experimental/requirements.mustache | 2 - python-experimental/rest.mustache | 279 ++++++++ python-experimental/setup.mustache | 4 +- python-experimental/signing.mustache | 3 +- .../test-requirements.mustache | 7 +- python-experimental/tox.mustache | 9 + python-experimental/travis.mustache | 21 + 26 files changed, 1138 insertions(+), 106 deletions(-) create mode 100644 python-experimental/configuration.mustache create mode 100644 python-experimental/exceptions.mustache create mode 100644 python-experimental/gitlab-ci.mustache create mode 100644 python-experimental/rest.mustache create mode 100644 python-experimental/tox.mustache create mode 100644 python-experimental/travis.mustache diff --git a/python-experimental/README.mustache b/python-experimental/README.mustache index 72c7f3de3f..3fb507c574 100644 --- a/python-experimental/README.mustache +++ b/python-experimental/README.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python 2.7 and 3.4+ +Python 3.4+ ## Installation & Usage ### pip install diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index 0f6dcb41d6..b996e676d1 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -1,5 +1,4 @@ ```python -from __future__ import print_function {{#apiInfo}}{{#apis}}{{^hasMore}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/hasMore}}{{/apis}}{{/apiInfo}} import time import {{{packageName}}} diff --git a/python-experimental/README_onlypackage.mustache b/python-experimental/README_onlypackage.mustache index 11c002c9aa..ee90ce7903 100644 --- a/python-experimental/README_onlypackage.mustache +++ b/python-experimental/README_onlypackage.mustache @@ -26,7 +26,6 @@ This python library package is generated without supporting files like setup.py To be able to use it, you will need these dependencies in your own package that uses this library: * urllib3 >= 1.15 -* six >= 1.10 * certifi * python-dateutil {{#asyncio}} diff --git a/python-experimental/__init__api.mustache b/python-experimental/__init__api.mustache index d37ee6c78b..1d37d33951 100644 --- a/python-experimental/__init__api.mustache +++ b/python-experimental/__init__api.mustache @@ -1,3 +1,3 @@ # do not import all apis into this module because that uses a lot of memory and stack frames -# if you need the ability to import all models from one package, import them with +# if you need the ability to import all apis from one package, import them with # from {{packageName}.apis import DefaultApi, PetApi \ No newline at end of file diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache index a949d50850..d0746d3aa6 100644 --- a/python-experimental/__init__package.mustache +++ b/python-experimental/__init__package.mustache @@ -4,8 +4,6 @@ {{>partial_header}} -from __future__ import absolute_import - __version__ = "{{packageVersion}}" # import ApiClient diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index ad5decabf0..776acbf5ec 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -2,14 +2,9 @@ {{>partial_header}} -from __future__ import absolute_import - import re # noqa: F401 import sys # noqa: F401 -# python 2 and python 3 compatibility library -import six - from {{packageName}}.api_client import ApiClient, Endpoint from {{packageName}}.model_utils import ( # noqa: F401 check_allowed_values, @@ -17,9 +12,7 @@ from {{packageName}}.model_utils import ( # noqa: F401 date, datetime, file_type, - int, none_type, - str, validate_and_convert_types ) {{#imports}} diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index d3b0b6f60e..b7112d202b 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -1,6 +1,5 @@ # coding: utf-8 {{>partial_header}} -from __future__ import absolute_import import json import atexit @@ -8,10 +7,8 @@ import mimetypes from multiprocessing.pool import ThreadPool import os import re +from urllib.parse import quote -# python 2 and python 3 compatibility library -import six -from six.moves.urllib.parse import quote {{#tornado}} import tornado.gen {{/tornado}} @@ -29,10 +26,8 @@ from {{packageName}}.model_utils import ( datetime, deserialize_file, file_type, - int, model_to_dict, none_type, - str, validate_and_convert_types ) @@ -59,10 +54,8 @@ class ApiClient(object): to the API. More threads means more concurrent API requests. """ - # six.binary_type python2=str, python3=bytes - # six.text_type python2=unicode, python3=str PRIMITIVE_TYPES = ( - (float, bool, six.binary_type, six.text_type) + six.integer_types + float, bool, bytes, str, int ) _pool = None @@ -189,7 +182,7 @@ class ApiClient(object): _preload_content=_preload_content, _request_timeout=_request_timeout) except ApiException as e: - e.body = e.body.decode('utf-8') if six.PY3 else e.body + e.body = e.body.decode('utf-8') raise e content_type = response_data.getheader('content-type') @@ -207,7 +200,7 @@ class ApiClient(object): {{/tornado}} return return_data - if six.PY3 and response_type not in ["file", "bytes"]: + if response_type not in ["file", "bytes"]: match = None if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) @@ -277,7 +270,7 @@ class ApiClient(object): return self.sanitize_for_serialization(obj.value) return {key: self.sanitize_for_serialization(val) - for key, val in six.iteritems(obj_dict)} + for key, val in obj_dict.items()} def deserialize(self, response, response_type, _check_type): """Deserializes response into an object. @@ -477,7 +470,7 @@ class ApiClient(object): new_params = [] if collection_formats is None: collection_formats = {} - for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': @@ -508,7 +501,7 @@ class ApiClient(object): return [] params = [] - for param_name, file_instances in six.iteritems(files): + for param_name, file_instances in files.items(): if file_instances is None: # if the file field is nullable, skip None values continue @@ -692,7 +685,7 @@ class Endpoint(object): if kwargs['_check_input_type'] is False: return - for key, value in six.iteritems(kwargs): + for key, value in kwargs.items(): fixed_val = validate_and_convert_types( value, self.openapi_types[key], @@ -714,7 +707,7 @@ class Endpoint(object): 'query': [] } - for param_name, param_value in six.iteritems(kwargs): + for param_name, param_value in kwargs.items(): param_location = self.location_map.get(param_name) if param_location is None: continue @@ -772,7 +765,7 @@ class Endpoint(object): ) _host = None - for key, value in six.iteritems(kwargs): + for key, value in kwargs.items(): if key not in self.params_map['all']: raise ApiTypeError( "Got an unexpected parameter '%s'" diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index 23cf85e9df..b7bbc009f5 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -1,5 +1,4 @@ ```python -from __future__ import print_function import time import {{{packageName}}} from {{apiPackage}} import {{classVarName}} diff --git a/python-experimental/api_test.mustache b/python-experimental/api_test.mustache index e04b32f96e..f9276b443c 100644 --- a/python-experimental/api_test.mustache +++ b/python-experimental/api_test.mustache @@ -2,8 +2,6 @@ {{>partial_header}} -from __future__ import absolute_import - import unittest import {{packageName}} diff --git a/python-experimental/configuration.mustache b/python-experimental/configuration.mustache new file mode 100644 index 0000000000..8b911bdddd --- /dev/null +++ b/python-experimental/configuration.mustache @@ -0,0 +1,632 @@ +# coding: utf-8 + +{{>partial_header}} + +import copy +import logging +{{^asyncio}} +import multiprocessing +{{/asyncio}} +import sys +import urllib3 + +from http import client as http_client +from {{packageName}}.exceptions import ApiValueError + + +JSON_SCHEMA_VALIDATION_KEYWORDS = { + 'multipleOf', 'maximum', 'exclusiveMaximum', + 'minimum', 'exclusiveMinimum', 'maxLength', + 'minLength', 'pattern', 'maxItems', 'minItems' +} + +class Configuration(object): + """NOTE: This class is auto generated by OpenAPI Generator + + Ref: https://openapi-generator.tech + Do not edit the class manually. + + :param host: Base url + :param api_key: Dict to store API key(s). + Each entry in the dict specifies an API key. + The dict key is the name of the security scheme in the OAS specification. + The dict value is the API key secret. + :param api_key_prefix: Dict to store API prefix (e.g. Bearer) + The dict key is the name of the security scheme in the OAS specification. + The dict value is an API key prefix when generating the auth data. + :param username: Username for HTTP basic authentication + :param password: Password for HTTP basic authentication + :param discard_unknown_keys: Boolean value indicating whether to discard + unknown properties. A server may send a response that includes additional + properties that are not known by the client in the following scenarios: + 1. The OpenAPI document is incomplete, i.e. it does not match the server + implementation. + 2. The client was generated using an older version of the OpenAPI document + and the server has been upgraded since then. + If a schema in the OpenAPI document defines the additionalProperties attribute, + then all undeclared properties received by the server are injected into the + additional properties map. In that case, there are undeclared properties, and + nothing to discard. + :param disabled_client_side_validations (string): Comma-separated list of + JSON schema validation keywords to disable JSON schema structural validation + rules. The following keywords may be specified: multipleOf, maximum, + exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength, pattern, + maxItems, minItems. + By default, the validation is performed for data generated locally by the client + and data received from the server, independent of any validation performed by + the server side. If the input data does not satisfy the JSON schema validation + rules specified in the OpenAPI document, an exception is raised. + If disabled_client_side_validations is set, structural validation is + disabled. This can be useful to troubleshoot data validation problem, such as + when the OpenAPI document validation rules do not match the actual API data + received by the server. +{{#hasHttpSignatureMethods}} + :param signing_info: Configuration parameters for the HTTP signature security scheme. + Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration +{{/hasHttpSignatureMethods}} + :param server_index: Index to servers configuration. + :param server_variables: Mapping with string values to replace variables in + templated server configuration. The validation of enums is performed for + variables with defined enum values before. + :param server_operation_index: Mapping from operation ID to an index to server + configuration. + :param server_operation_variables: Mapping from operation ID to a mapping with + string values to replace variables in templated server configuration. + The validation of enums is performed for variables with defined enum values before. + +{{#hasAuthMethods}} + :Example: +{{#hasApiKeyMethods}} + + API Key Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + cookieAuth: # name for the security scheme + type: apiKey + in: cookie + name: JSESSIONID # cookie name + + You can programmatically set the cookie: + +conf = {{{packageName}}}.Configuration( + api_key={'cookieAuth': 'abc123'} + api_key_prefix={'cookieAuth': 'JSESSIONID'} +) + + The following cookie will be added to the HTTP request: + Cookie: JSESSIONID abc123 +{{/hasApiKeyMethods}} +{{#hasHttpBasicMethods}} + + HTTP Basic Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + http_basic_auth: + type: http + scheme: basic + + Configure API client with HTTP basic authentication: + +conf = {{{packageName}}}.Configuration( + username='the-user', + password='the-password', +) + +{{/hasHttpBasicMethods}} +{{#hasHttpSignatureMethods}} + + HTTP Signature Authentication Example. + Given the following security scheme in the OpenAPI specification: + components: + securitySchemes: + http_basic_auth: + type: http + scheme: signature + + Configure API client with HTTP signature authentication. Use the 'hs2019' signature scheme, + sign the HTTP requests with the RSA-SSA-PSS signature algorithm, and set the expiration time + of the signature to 5 minutes after the signature has been created. + Note you can use the constants defined in the {{{packageName}}}.signing module, and you can + also specify arbitrary HTTP headers to be included in the HTTP signature, except for the + 'Authorization' header, which is used to carry the signature. + + One may be tempted to sign all headers by default, but in practice it rarely works. + This is beccause explicit proxies, transparent proxies, TLS termination endpoints or + load balancers may add/modify/remove headers. Include the HTTP headers that you know + are not going to be modified in transit. + +conf = {{{packageName}}}.Configuration( + signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( + key_id = 'my-key-id', + private_key_path = 'rsa.pem', + signing_scheme = {{{packageName}}}.signing.SCHEME_HS2019, + signing_algorithm = {{{packageName}}}.signing.ALGORITHM_RSASSA_PSS, + signed_headers = [{{{packageName}}}.signing.HEADER_REQUEST_TARGET, + {{{packageName}}}.signing.HEADER_CREATED, + {{{packageName}}}.signing.HEADER_EXPIRES, + {{{packageName}}}.signing.HEADER_HOST, + {{{packageName}}}.signing.HEADER_DATE, + {{{packageName}}}.signing.HEADER_DIGEST, + 'Content-Type', + 'User-Agent' + ], + signature_max_validity = datetime.timedelta(minutes=5) + ) +) +{{/hasHttpSignatureMethods}} +{{/hasAuthMethods}} + """ + + _default = None + + def __init__(self, host=None, + api_key=None, api_key_prefix=None, + username=None, password=None, + discard_unknown_keys=False, + disabled_client_side_validations="", +{{#hasHttpSignatureMethods}} + signing_info=None, +{{/hasHttpSignatureMethods}} + server_index=None, server_variables=None, + server_operation_index=None, server_operation_variables=None, + ): + """Constructor + """ + self._base_path = "{{{basePath}}}" if host is None else host + """Default Base url + """ + self.server_index = 0 if server_index is None and host is None else server_index + self.server_operation_index = server_operation_index or {} + """Default server index + """ + self.server_variables = server_variables or {} + self.server_operation_variables = server_operation_variables or {} + """Default server variables + """ + self.temp_folder_path = None + """Temp file folder for downloading files + """ + # Authentication Settings + self.api_key = {} + if api_key: + self.api_key = api_key + """dict to store API key(s) + """ + self.api_key_prefix = {} + if api_key_prefix: + self.api_key_prefix = api_key_prefix + """dict to store API prefix (e.g. Bearer) + """ + self.refresh_api_key_hook = None + """function hook to refresh API key if expired + """ + self.username = username + """Username for HTTP basic authentication + """ + self.password = password + """Password for HTTP basic authentication + """ + self.discard_unknown_keys = discard_unknown_keys + self.disabled_client_side_validations = disabled_client_side_validations +{{#hasHttpSignatureMethods}} + if signing_info is not None: + signing_info.host = host + self.signing_info = signing_info + """The HTTP signing configuration + """ +{{/hasHttpSignatureMethods}} +{{#hasOAuthMethods}} + self.access_token = None + """access token for OAuth/Bearer + """ +{{/hasOAuthMethods}} +{{^hasOAuthMethods}} +{{#hasBearerMethods}} + self.access_token = None + """access token for OAuth/Bearer + """ +{{/hasBearerMethods}} +{{/hasOAuthMethods}} + self.logger = {} + """Logging Settings + """ + self.logger["package_logger"] = logging.getLogger("{{packageName}}") + self.logger["urllib3_logger"] = logging.getLogger("urllib3") + self.logger_format = '%(asctime)s %(levelname)s %(message)s' + """Log format + """ + self.logger_stream_handler = None + """Log stream handler + """ + self.logger_file_handler = None + """Log file handler + """ + self.logger_file = None + """Debug file location + """ + self.debug = False + """Debug switch + """ + + self.verify_ssl = True + """SSL/TLS verification + Set this to false to skip verifying SSL certificate when calling API + from https server. + """ + self.ssl_ca_cert = None + """Set this to customize the certificate file to verify the peer. + """ + self.cert_file = None + """client certificate file + """ + self.key_file = None + """client key file + """ + self.assert_hostname = None + """Set this to True/False to enable/disable SSL hostname verification. + """ + + {{#asyncio}} + self.connection_pool_maxsize = 100 + """This value is passed to the aiohttp to limit simultaneous connections. + Default values is 100, None means no-limit. + """ + {{/asyncio}} + {{^asyncio}} + self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 + """urllib3 connection pool's maximum number of connections saved + per pool. urllib3 uses 1 connection as default value, but this is + not the best value when you are making a lot of possibly parallel + requests to the same host, which is often the case here. + cpu_count * 5 is used as default value to increase performance. + """ + {{/asyncio}} + + self.proxy = None + """Proxy URL + """ + self.proxy_headers = None + """Proxy headers + """ + self.safe_chars_for_path_param = '' + """Safe chars for path_param + """ + self.retries = None + """Adding retries to override urllib3 default value 3 + """ + # Enable client side validation + self.client_side_validation = True + + def __deepcopy__(self, memo): + cls = self.__class__ + result = cls.__new__(cls) + memo[id(self)] = result + for k, v in self.__dict__.items(): + if k not in ('logger', 'logger_file_handler'): + setattr(result, k, copy.deepcopy(v, memo)) + # shallow copy of loggers + result.logger = copy.copy(self.logger) + # use setters to configure loggers + result.logger_file = self.logger_file + result.debug = self.debug + return result + + def __setattr__(self, name, value): + object.__setattr__(self, name, value) + if name == 'disabled_client_side_validations': + s = set(filter(None, value.split(','))) + for v in s: + if v not in JSON_SCHEMA_VALIDATION_KEYWORDS: + raise ApiValueError( + "Invalid keyword: '{0}''".format(v)) + self._disabled_client_side_validations = s +{{#hasHttpSignatureMethods}} + if name == "signing_info" and value is not None: + # Ensure the host paramater from signing info is the same as + # Configuration.host. + value.host = self.host +{{/hasHttpSignatureMethods}} + + @classmethod + def set_default(cls, default): + """Set default instance of configuration. + + It stores default configuration, which can be + returned by get_default_copy method. + + :param default: object of Configuration + """ + cls._default = copy.deepcopy(default) + + @classmethod + def get_default_copy(cls): + """Return new instance of configuration. + + This method returns newly created, based on default constructor, + object of Configuration class or returns a copy of default + configuration passed by the set_default method. + + :return: The configuration object. + """ + if cls._default is not None: + return copy.deepcopy(cls._default) + return Configuration() + + @property + def logger_file(self): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + return self.__logger_file + + @logger_file.setter + def logger_file(self, value): + """The logger file. + + If the logger_file is None, then add stream handler and remove file + handler. Otherwise, add file handler and remove stream handler. + + :param value: The logger_file path. + :type: str + """ + self.__logger_file = value + if self.__logger_file: + # If set logging file, + # then add file handler and remove stream handler. + self.logger_file_handler = logging.FileHandler(self.__logger_file) + self.logger_file_handler.setFormatter(self.logger_formatter) + for _, logger in self.logger.items(): + logger.addHandler(self.logger_file_handler) + + @property + def debug(self): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + return self.__debug + + @debug.setter + def debug(self, value): + """Debug status + + :param value: The debug status, True or False. + :type: bool + """ + self.__debug = value + if self.__debug: + # if debug status is True, turn on debug logging + for _, logger in self.logger.items(): + logger.setLevel(logging.DEBUG) + # turn on http_client debug + http_client.HTTPConnection.debuglevel = 1 + else: + # if debug status is False, turn off debug logging, + # setting log level to default `logging.WARNING` + for _, logger in self.logger.items(): + logger.setLevel(logging.WARNING) + # turn off http_client debug + http_client.HTTPConnection.debuglevel = 0 + + @property + def logger_format(self): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + return self.__logger_format + + @logger_format.setter + def logger_format(self, value): + """The logger format. + + The logger_formatter will be updated when sets logger_format. + + :param value: The format string. + :type: str + """ + self.__logger_format = value + self.logger_formatter = logging.Formatter(self.__logger_format) + + def get_api_key_with_prefix(self, identifier, alias=None): + """Gets API key (with prefix if set). + + :param identifier: The identifier of apiKey. + :param alias: The alternative identifier of apiKey. + :return: The token for api key authentication. + """ + if self.refresh_api_key_hook is not None: + self.refresh_api_key_hook(self) + key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None) + if key: + prefix = self.api_key_prefix.get(identifier) + if prefix: + return "%s %s" % (prefix, key) + else: + return key + + def get_basic_auth_token(self): + """Gets HTTP basic authentication header (string). + + :return: The token for basic HTTP authentication. + """ + username = "" + if self.username is not None: + username = self.username + password = "" + if self.password is not None: + password = self.password + return urllib3.util.make_headers( + basic_auth=username + ':' + password + ).get('authorization') + + def auth_settings(self): + """Gets Auth Settings dict for api client. + + :return: The Auth Settings information dict. + """ + auth = {} +{{#authMethods}} +{{#isApiKey}} + if '{{name}}' in self.api_key{{#vendorExtensions.x-auth-id-alias}} or '{{.}}' in self.api_key{{/vendorExtensions.x-auth-id-alias}}: + auth['{{name}}'] = { + 'type': 'api_key', + 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, + 'key': '{{keyParamName}}', + 'value': self.get_api_key_with_prefix( + '{{name}}',{{#vendorExtensions.x-auth-id-alias}} + alias='{{.}}',{{/vendorExtensions.x-auth-id-alias}} + ), + } +{{/isApiKey}} +{{#isBasic}} + {{#isBasicBasic}} + if self.username is not None and self.password is not None: + auth['{{name}}'] = { + 'type': 'basic', + 'in': 'header', + 'key': 'Authorization', + 'value': self.get_basic_auth_token() + } + {{/isBasicBasic}} + {{#isBasicBearer}} + if self.access_token is not None: + auth['{{name}}'] = { + 'type': 'bearer', + 'in': 'header', + {{#bearerFormat}} + 'format': '{{{.}}}', + {{/bearerFormat}} + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } + {{/isBasicBearer}} + {{#isHttpSignature}} + if self.signing_info is not None: + auth['{{name}}'] = { + 'type': 'http-signature', + 'in': 'header', + 'key': 'Authorization', + 'value': None # Signature headers are calculated for every HTTP request + } + {{/isHttpSignature}} +{{/isBasic}} +{{#isOAuth}} + if self.access_token is not None: + auth['{{name}}'] = { + 'type': 'oauth2', + 'in': 'header', + 'key': 'Authorization', + 'value': 'Bearer ' + self.access_token + } +{{/isOAuth}} +{{/authMethods}} + return auth + + def to_debug_report(self): + """Gets the essential information for debugging. + + :return: The report for debugging. + """ + return "Python SDK Debug Report:\n"\ + "OS: {env}\n"\ + "Python Version: {pyversion}\n"\ + "Version of the API: {{version}}\n"\ + "SDK Package Version: {{packageVersion}}".\ + format(env=sys.platform, pyversion=sys.version) + + def get_host_settings(self): + """Gets an array of host settings + + :return: An array of host settings + """ + return [ + {{#servers}} + { + 'url': "{{{url}}}", + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + 'variables': { + {{/-first}} + '{{{name}}}': { + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + 'default_value': "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + 'enum_values': [ + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ] + {{/-last}} + {{/enumValues}} + }{{^-last}},{{/-last}} + {{#-last}} + } + {{/-last}} + {{/variables}} + }{{^-last}},{{/-last}} + {{/servers}} + ] + + def get_host_from_settings(self, index, variables=None, servers=None): + """Gets host URL based on the index and variables + :param index: array index of the host settings + :param variables: hash of variable and the corresponding value + :param servers: an array of host settings or None + :return: URL based on host settings + """ + if index is None: + return self._base_path + + variables = {} if variables is None else variables + servers = self.get_host_settings() if servers is None else servers + + try: + server = servers[index] + except IndexError: + raise ValueError( + "Invalid index {0} when selecting the host settings. " + "Must be less than {1}".format(index, len(servers))) + + url = server['url'] + + # go through variables and replace placeholders + for variable_name, variable in server.get('variables', {}).items(): + used_value = variables.get( + variable_name, variable['default_value']) + + if 'enum_values' in variable \ + and used_value not in variable['enum_values']: + raise ValueError( + "The variable `{0}` in the host URL has invalid value " + "{1}. Must be {2}.".format( + variable_name, variables[variable_name], + variable['enum_values'])) + + url = url.replace("{" + variable_name + "}", used_value) + + return url + + @property + def host(self): + """Return generated host.""" + return self.get_host_from_settings(self.server_index, variables=self.server_variables) + + @host.setter + def host(self, value): + """Fix base path.""" + self._base_path = value + self.server_index = None diff --git a/python-experimental/exceptions.mustache b/python-experimental/exceptions.mustache new file mode 100644 index 0000000000..8d445c6e24 --- /dev/null +++ b/python-experimental/exceptions.mustache @@ -0,0 +1,129 @@ +# coding: utf-8 + +{{>partial_header}} + + +class OpenApiException(Exception): + """The base exception class for all OpenAPIExceptions""" + + +class ApiTypeError(OpenApiException, TypeError): + def __init__(self, msg, path_to_item=None, valid_classes=None, + key_type=None): + """ Raises an exception for TypeErrors + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list): a list of keys an indices to get to the + current_item + None if unset + valid_classes (tuple): the primitive classes that current item + should be an instance of + None if unset + key_type (bool): False if our value is a value in a dict + True if it is a key in a dict + False if our item is an item in a list + None if unset + """ + self.path_to_item = path_to_item + self.valid_classes = valid_classes + self.key_type = key_type + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiTypeError, self).__init__(full_msg) + + +class ApiValueError(OpenApiException, ValueError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (list) the path to the exception in the + received_data dict. None if unset + """ + + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiValueError, self).__init__(full_msg) + + +class ApiAttributeError(OpenApiException, AttributeError): + def __init__(self, msg, path_to_item=None): + """ + Raised when an attribute reference or assignment fails. + + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiAttributeError, self).__init__(full_msg) + + +class ApiKeyError(OpenApiException, KeyError): + def __init__(self, msg, path_to_item=None): + """ + Args: + msg (str): the exception message + + Keyword Args: + path_to_item (None/list) the path to the exception in the + received_data dict + """ + self.path_to_item = path_to_item + full_msg = msg + if path_to_item: + full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) + super(ApiKeyError, self).__init__(full_msg) + + +class ApiException(OpenApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + if http_resp: + self.status = http_resp.status + self.reason = http_resp.reason + self.body = http_resp.data + self.headers = http_resp.getheaders() + else: + self.status = status + self.reason = reason + self.body = None + self.headers = None + + def __str__(self): + """Custom error messages for exception""" + error_message = "({0})\n"\ + "Reason: {1}\n".format(self.status, self.reason) + if self.headers: + error_message += "HTTP response headers: {0}\n".format( + self.headers) + + if self.body: + error_message += "HTTP response body: {0}\n".format(self.body) + + return error_message + + +def render_path(path_to_item): + """Returns a string representation of a path""" + result = "" + for pth in path_to_item: + if isinstance(pth, int): + result += "[{0}]".format(pth) + else: + result += "['{0}']".format(pth) + return result diff --git a/python-experimental/gitlab-ci.mustache b/python-experimental/gitlab-ci.mustache new file mode 100644 index 0000000000..a626e9c084 --- /dev/null +++ b/python-experimental/gitlab-ci.mustache @@ -0,0 +1,35 @@ +# ref: https://docs.gitlab.com/ee/ci/README.html + +stages: + - test + +.nosetest: + stage: test + script: + - pip install -r requirements.txt + - pip install -r test-requirements.txt + {{#useNose}} + - nosetests + {{/useNose}} + {{^useNose}} + - pytest --cov={{{packageName}}} + {{/useNose}} + +nosetest-3.3: + extends: .nosetest + image: python:3.3-alpine +nosetest-3.4: + extends: .nosetest + image: python:3.4-alpine +nosetest-3.5: + extends: .nosetest + image: python:3.5-alpine +nosetest-3.6: + extends: .nosetest + image: python:3.6-alpine +nosetest-3.7: + extends: .nosetest + image: python:3.7-alpine +nosetest-3.8: + extends: .nosetest + image: python:3.8-alpine diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index e89b3d5633..ad7d5ddb31 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -2,11 +2,9 @@ {{>partial_header}} -from __future__ import absolute_import import re # noqa: F401 import sys # noqa: F401 -import six # noqa: F401 import nulltype # noqa: F401 from {{packageName}}.model_utils import ( # noqa: F401 @@ -20,9 +18,7 @@ from {{packageName}}.model_utils import ( # noqa: F401 date, datetime, file_type, - int, none_type, - str, validate_get_composed_info, ) {{#models}} diff --git a/python-experimental/model_templates/method_init_composed.mustache b/python-experimental/model_templates/method_init_composed.mustache index 67750cb17a..7e64549acd 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/python-experimental/model_templates/method_init_composed.mustache @@ -41,7 +41,7 @@ for var_name, var_value in required_args.items(): setattr(self, var_name, var_value) - for var_name, var_value in six.iteritems(kwargs): + for var_name, var_value in kwargs.items(): if var_name in unused_args and \ self._configuration is not None and \ self._configuration.discard_unknown_keys and \ diff --git a/python-experimental/model_templates/method_init_normal.mustache b/python-experimental/model_templates/method_init_normal.mustache index 7faf7a30ee..4fee1c8449 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/python-experimental/model_templates/method_init_normal.mustache @@ -15,7 +15,7 @@ {{#requiredVars}} self.{{name}} = {{name}} {{/requiredVars}} - for var_name, var_value in six.iteritems(kwargs): + for var_name, var_value in kwargs.items(): if var_name not in self.attribute_map and \ self._configuration is not None and \ self._configuration.discard_unknown_keys and \ diff --git a/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache b/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache index d01d49ad77..17c441196a 100644 --- a/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache +++ b/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache @@ -13,17 +13,12 @@ if not set(self._data_store.keys()) == set(other._data_store.keys()): return False - for _var_name, this_val in six.iteritems(self._data_store): + for _var_name, this_val in self._data_store.items(): that_val = other._data_store[_var_name] types = set() types.add(this_val.__class__) types.add(that_val.__class__) vals_equal = this_val == that_val - if (not six.PY3 and - len(types) == 2 and unicode in types): # noqa: F821 - vals_equal = ( - this_val.encode('utf-8') == that_val.encode('utf-8') - ) if not vals_equal: return False return True \ No newline at end of file diff --git a/python-experimental/model_templates/methods_tostr_eq_simple.mustache b/python-experimental/model_templates/methods_tostr_eq_simple.mustache index 0bba565d22..4a7ef6ae5c 100644 --- a/python-experimental/model_templates/methods_tostr_eq_simple.mustache +++ b/python-experimental/model_templates/methods_tostr_eq_simple.mustache @@ -13,10 +13,4 @@ types.add(this_val.__class__) types.add(that_val.__class__) vals_equal = this_val == that_val - if not six.PY3 and len(types) == 2 and unicode in types: # noqa: F821 - vals_equal = ( - this_val.encode('utf-8') == that_val.encode('utf-8') - ) - if not vals_equal: - return False - return True \ No newline at end of file + return vals_equal \ No newline at end of file diff --git a/python-experimental/model_test.mustache b/python-experimental/model_test.mustache index 5b9a91d2d0..c5ffe2c255 100644 --- a/python-experimental/model_test.mustache +++ b/python-experimental/model_test.mustache @@ -2,7 +2,6 @@ {{>partial_header}} -from __future__ import absolute_import import sys import unittest diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 1323b72499..ab30c2dcb0 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -4,13 +4,13 @@ from datetime import date, datetime # noqa: F401 import inspect +import io import os import pprint import re import tempfile from dateutil.parser import parse -import six from {{packageName}}.exceptions import ( ApiKeyError, @@ -20,20 +20,7 @@ from {{packageName}}.exceptions import ( ) none_type = type(None) -if six.PY3: - import io - file_type = io.IOBase - # these are needed for when other modules import str and int from here - str = str - int = int -else: - file_type = file # noqa: F821 - str_py2 = str - unicode_py2 = unicode # noqa: F821 - long_py2 = long # noqa: F821 - int_py2 = int - # this requires that the future library is installed - from builtins import int, str +file_type = io.IOBase class cached_property(object): @@ -380,8 +367,6 @@ def get_simple_class(input_value): # isinstance(True, int) == True return bool elif isinstance(input_value, int): - # for python2 input_value==long_instance -> return int - # where int is the python3 int backport return int elif isinstance(input_value, datetime): # this must be higher than the date check because @@ -389,8 +374,7 @@ def get_simple_class(input_value): return datetime elif isinstance(input_value, date): return date - elif (six.PY2 and isinstance(input_value, (str_py2, unicode_py2, str)) or - isinstance(input_value, str)): + elif isinstance(input_value, str): return str return type(input_value) @@ -835,12 +819,12 @@ def deserialize_primitive(data, klass, path_to_item): return converted_value except (OverflowError, ValueError) as ex: # parse can raise OverflowError - six.raise_from(ApiValueError( + raise ApiValueError( "{0}Failed to parse {1} as {2}".format( - additional_message, repr(data), get_py3_class_name(klass) + additional_message, repr(data), klass.__name__ ), path_to_item=path_to_item - ), ex) + ) from ex def get_discriminator_class(model_class, @@ -964,8 +948,8 @@ def deserialize_file(response_data, configuration, content_disposition=None): path = os.path.join(os.path.dirname(path), filename) with open(path, "wb") as f: - if six.PY3 and isinstance(response_data, str): - # in python3 change str to bytes so we can write it + if isinstance(response_data, str): + # change str to bytes so we can write it response_data = response_data.encode('utf-8') f.write(response_data) @@ -1184,7 +1168,7 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, if input_value == {}: # allow an empty dict return input_value - for inner_key, inner_val in six.iteritems(input_value): + for inner_key, inner_val in input_value.items(): inner_path = list(path_to_item) inner_path.append(inner_key) if get_simple_class(inner_key) != str: @@ -1218,7 +1202,7 @@ def model_to_dict(model_instance, serialize=True): if model_instance._composed_schemas: model_instances.extend(model_instance._composed_instances) for model_instance in model_instances: - for attr, value in six.iteritems(model_instance._data_store): + for attr, value in model_instance._data_store.items(): if serialize: # we use get here because additional property key names do not # exist in attribute_map @@ -1275,13 +1259,8 @@ def type_error_message(var_value=None, var_name=None, valid_classes=None, def get_valid_classes_phrase(input_classes): """Returns a string phrase describing what types are allowed - Note: Adds the extra valid classes in python2 """ all_classes = list(input_classes) - if six.PY2 and str in input_classes: - all_classes.extend([str_py2, unicode_py2]) - if six.PY2 and int in input_classes: - all_classes.extend([int_py2, long_py2]) all_classes = sorted(all_classes, key=lambda cls: cls.__name__) all_class_names = [cls.__name__ for cls in all_classes] if len(all_class_names) == 1: @@ -1289,15 +1268,6 @@ def get_valid_classes_phrase(input_classes): return "is one of [{0}]".format(", ".join(all_class_names)) -def get_py3_class_name(input_class): - if six.PY2: - if input_class == str: - return 'str' - elif input_class == int: - return 'int' - return input_class.__name__ - - def convert_js_args_to_python_args(fn): from functools import wraps @wraps(fn) @@ -1340,7 +1310,7 @@ def get_allof_instances(self, model_args, constant_args): allof_instance = allof_class(**kwargs) composed_instances.append(allof_instance) except Exception as ex: - six.raise_from(ApiValueError( + raise ApiValueError( "Invalid inputs given to generate an instance of '%s'. The " "input data was invalid for the allOf schema '%s' in the composed " "schema '%s'. Error=%s" % ( @@ -1349,7 +1319,7 @@ def get_allof_instances(self, model_args, constant_args): self.__class__.__name__, str(ex) ) - ), ex) + ) from ex return composed_instances diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache index a56bedffbf..2c2f00fcb2 100644 --- a/python-experimental/requirements.mustache +++ b/python-experimental/requirements.mustache @@ -1,7 +1,5 @@ nulltype certifi >= 14.05.14 -future; python_version<="2.7" -six >= 1.10 python_dateutil >= 2.5.3 setuptools >= 21.0.0 urllib3 >= 1.15.1 diff --git a/python-experimental/rest.mustache b/python-experimental/rest.mustache new file mode 100644 index 0000000000..d5edf9535d --- /dev/null +++ b/python-experimental/rest.mustache @@ -0,0 +1,279 @@ +# coding: utf-8 + +{{>partial_header}} + +import io +import json +import logging +import re +import ssl +from urllib.parse import urlencode + +import certifi +import urllib3 + +from {{packageName}}.exceptions import ApiException, ApiValueError + + +logger = logging.getLogger(__name__) + + +class RESTResponse(io.IOBase): + + def __init__(self, resp): + self.urllib3_response = resp + self.status = resp.status + self.reason = resp.reason + self.data = resp.data + + def getheaders(self): + """Returns a dictionary of the response headers.""" + return self.urllib3_response.getheaders() + + def getheader(self, name, default=None): + """Returns a given response header.""" + return self.urllib3_response.getheader(name, default) + + +class RESTClientObject(object): + + def __init__(self, configuration, pools_size=4, maxsize=None): + # urllib3.PoolManager will pass all kw parameters to connectionpool + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 + # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 + # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 + # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 + + # cert_reqs + if configuration.verify_ssl: + cert_reqs = ssl.CERT_REQUIRED + else: + cert_reqs = ssl.CERT_NONE + + # ca_certs + if configuration.ssl_ca_cert: + ca_certs = configuration.ssl_ca_cert + else: + # if not set certificate file, use Mozilla's root certificates. + ca_certs = certifi.where() + + addition_pool_args = {} + if configuration.assert_hostname is not None: + addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 + + if configuration.retries is not None: + addition_pool_args['retries'] = configuration.retries + + if maxsize is None: + if configuration.connection_pool_maxsize is not None: + maxsize = configuration.connection_pool_maxsize + else: + maxsize = 4 + + # https pool manager + if configuration.proxy: + self.pool_manager = urllib3.ProxyManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + proxy_url=configuration.proxy, + proxy_headers=configuration.proxy_headers, + **addition_pool_args + ) + else: + self.pool_manager = urllib3.PoolManager( + num_pools=pools_size, + maxsize=maxsize, + cert_reqs=cert_reqs, + ca_certs=ca_certs, + cert_file=configuration.cert_file, + key_file=configuration.key_file, + **addition_pool_args + ) + + def request(self, method, url, query_params=None, headers=None, + body=None, post_params=None, _preload_content=True, + _request_timeout=None): + """Perform requests. + + :param method: http request method + :param url: http request url + :param query_params: query parameters in the url + :param headers: http request headers + :param body: request json body, for `application/json` + :param post_params: request post parameters, + `application/x-www-form-urlencoded` + and `multipart/form-data` + :param _preload_content: if False, the urllib3.HTTPResponse object will + be returned without reading/decoding response + data. Default is True. + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + """ + method = method.upper() + assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', + 'PATCH', 'OPTIONS'] + + if post_params and body: + raise ApiValueError( + "body parameter cannot be used with post_params parameter." + ) + + post_params = post_params or {} + headers = headers or {} + + timeout = None + if _request_timeout: + if isinstance(_request_timeout, int): # noqa: E501,F821 + timeout = urllib3.Timeout(total=_request_timeout) + elif (isinstance(_request_timeout, tuple) and + len(_request_timeout) == 2): + timeout = urllib3.Timeout( + connect=_request_timeout[0], read=_request_timeout[1]) + + if 'Content-Type' not in headers: + headers['Content-Type'] = 'application/json' + + try: + # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` + if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: + if query_params: + url += '?' + urlencode(query_params) + if re.search('json', headers['Content-Type'], re.IGNORECASE): + request_body = None + if body is not None: + request_body = json.dumps(body) + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=False, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + elif headers['Content-Type'] == 'multipart/form-data': + # must del headers['Content-Type'], or the correct + # Content-Type which generated by urllib3 will be + # overwritten. + del headers['Content-Type'] + r = self.pool_manager.request( + method, url, + fields=post_params, + encode_multipart=True, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + # Pass a `string` parameter directly in the body to support + # other content types than Json when `body` argument is + # provided in serialized form + elif isinstance(body, str) or isinstance(body, bytes): + request_body = body + r = self.pool_manager.request( + method, url, + body=request_body, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + else: + # Cannot generate the request from given parameters + msg = """Cannot prepare a request message for provided + arguments. Please check that your arguments match + declared content type.""" + raise ApiException(status=0, reason=msg) + # For `GET`, `HEAD` + else: + r = self.pool_manager.request(method, url, + fields=query_params, + preload_content=_preload_content, + timeout=timeout, + headers=headers) + except urllib3.exceptions.SSLError as e: + msg = "{0}\n{1}".format(type(e).__name__, str(e)) + raise ApiException(status=0, reason=msg) + + if _preload_content: + r = RESTResponse(r) + + # log response body + logger.debug("response body: %s", r.data) + + if not 200 <= r.status <= 299: + raise ApiException(http_resp=r) + + return r + + def GET(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("GET", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def HEAD(self, url, headers=None, query_params=None, _preload_content=True, + _request_timeout=None): + return self.request("HEAD", url, + headers=headers, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + query_params=query_params) + + def OPTIONS(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("OPTIONS", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def DELETE(self, url, headers=None, query_params=None, body=None, + _preload_content=True, _request_timeout=None): + return self.request("DELETE", url, + headers=headers, + query_params=query_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def POST(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("POST", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PUT(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PUT", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) + + def PATCH(self, url, headers=None, query_params=None, post_params=None, + body=None, _preload_content=True, _request_timeout=None): + return self.request("PATCH", url, + headers=headers, + query_params=query_params, + post_params=post_params, + _preload_content=_preload_content, + _request_timeout=_request_timeout, + body=body) diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 796475c456..b3c89f621e 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -18,7 +18,6 @@ VERSION = "{{packageVersion}}" REQUIRES = [ "urllib3 >= 1.15", - "six >= 1.10", "certifi", "python-dateutil", "nulltype", @@ -33,7 +32,6 @@ REQUIRES = [ "pycryptodome>=3.9.0", {{/hasHttpSignatureMethods}} ] -EXTRAS = {':python_version <= "2.7"': ['future']} setup( name=NAME, @@ -43,8 +41,8 @@ setup( author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], + python_requires=">=3.3", install_requires=REQUIRES, - extras_require=EXTRAS, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, {{#licenseInfo}}license="{{licenseInfo}}", diff --git a/python-experimental/signing.mustache b/python-experimental/signing.mustache index 0be0e1c467..26d2b8cb37 100644 --- a/python-experimental/signing.mustache +++ b/python-experimental/signing.mustache @@ -1,6 +1,5 @@ # coding: utf-8 {{>partial_header}} -from __future__ import absolute_import from base64 import b64encode from Crypto.IO import PEM, PKCS8 @@ -11,8 +10,8 @@ from email.utils import formatdate import json import os import re -from six.moves.urllib.parse import urlencode, urlparse from time import time +from urllib.parse import urlencode, urlparse # The constants below define a subset of HTTP headers that can be included in the # HTTP signature scheme. Additional headers may be included in the signature. diff --git a/python-experimental/test-requirements.mustache b/python-experimental/test-requirements.mustache index ebdee3392e..cc68f6484f 100644 --- a/python-experimental/test-requirements.mustache +++ b/python-experimental/test-requirements.mustache @@ -6,11 +6,10 @@ py>=1.4.31 randomize>=0.13 {{/useNose}} {{^useNose}} -pytest~=4.6.7 # needed for python 2.7+3.4 +pytest~=4.6.7 # needed for python 3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 +pytest-randomly==1.2.3 # needed for python 3.4 {{/useNose}} {{#hasHttpSignatureMethods}} pycryptodome>=3.9.0 -{{/hasHttpSignatureMethods}} -mock; python_version<="2.7" \ No newline at end of file +{{/hasHttpSignatureMethods}} \ No newline at end of file diff --git a/python-experimental/tox.mustache b/python-experimental/tox.mustache new file mode 100644 index 0000000000..4c771c472b --- /dev/null +++ b/python-experimental/tox.mustache @@ -0,0 +1,9 @@ +[tox] +envlist = py3 + +[testenv] +deps=-r{toxinidir}/requirements.txt + -r{toxinidir}/test-requirements.txt + +commands= + {{^useNose}}pytest --cov={{{packageName}}}{{/useNose}}{{#useNose}}nosetests{{/useNose}} diff --git a/python-experimental/travis.mustache b/python-experimental/travis.mustache new file mode 100644 index 0000000000..77f7289f97 --- /dev/null +++ b/python-experimental/travis.mustache @@ -0,0 +1,21 @@ +# ref: https://docs.travis-ci.com/user/languages/python +language: python +python: + - "3.2" + - "3.3" + - "3.4" + - "3.5" + - "3.6" + - "3.7" + - "3.8" +# command to install dependencies +install: + - "pip install -r requirements.txt" + - "pip install -r test-requirements.txt" +# command to run tests +{{#useNose}} +script: nosetests +{{/useNose}} +{{^useNose}} +script: pytest --cov={{{packageName}}} +{{/useNose}} From 8d442c92ae1cb651e009af90e97bdd60079b6200 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 27 Jul 2020 18:35:41 -0700 Subject: [PATCH 132/180] Python-exp clean up model classnames (#7054) * Adds lazy_import, removes python-exp java class renaming code, partial removal of getPythonClassName call sites Fixes PythonClientExperimentalTest.java Python-exp smaples regeneration Revers makefile Reverst pom.xml Fixes model imports in models.__init__ Updates docstring, omits lazy import in additional properties if we dont need it Improves additional_properties_type assignment if None Removes getPythonClassName Fixes python-exp tests * Removes unused makefiles --- python-experimental/README_common.mustache | 2 +- python-experimental/__init__models.mustache | 2 +- python-experimental/model.mustache | 6 ++- .../model_templates/classvars.mustache | 42 +++++++++++++++++-- .../model_templates/model_composed.mustache | 7 +++- .../model_templates/model_normal.mustache | 2 +- .../model_templates/model_simple.mustache | 2 +- python-experimental/model_utils.mustache | 4 +- 8 files changed, 55 insertions(+), 12 deletions(-) diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index b996e676d1..d3844fd15f 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -47,7 +47,7 @@ Class | Method | HTTP request | Description ## Documentation For Models -{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{unescapedDescription}}}.md) +{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) {{/model}}{{/models}} ## Documentation For Authorization diff --git a/python-experimental/__init__models.mustache b/python-experimental/__init__models.mustache index abe69dc035..5a2f25f875 100644 --- a/python-experimental/__init__models.mustache +++ b/python-experimental/__init__models.mustache @@ -13,6 +13,6 @@ {{#models}} {{#model}} -from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} +from {{modelPackage}}.{{classFilename}} import {{classname}} {{/model}} {{/models}} diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index ad7d5ddb31..1a181b824d 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -24,7 +24,11 @@ from {{packageName}}.model_utils import ( # noqa: F401 {{#models}} {{#model}} {{#imports}} -{{{.}}} +{{#-first}} + +def lazy_import(): +{{/-first}} + {{{.}}} {{/imports}} diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 5186e6621f..ed121c5bfe 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -64,20 +64,41 @@ {{/optionalVars}} } - additional_properties_type = {{#additionalPropertiesType}}({{{additionalPropertiesType}}},) # noqa: E501{{/additionalPropertiesType}}{{^additionalPropertiesType}}None{{/additionalPropertiesType}} +{{#additionalPropertiesType}} + @cached_property + def additional_properties_type(): + """ + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded + """ +{{#imports}} +{{#-first}} + lazy_import() +{{/-first}} +{{/imports}} + return ({{{additionalPropertiesType}}},) # noqa: E501 +{{/additionalPropertiesType}} +{{^additionalPropertiesType}} + additional_properties_type = None +{{/additionalPropertiesType}} _nullable = {{#isNullable}}True{{/isNullable}}{{^isNullable}}False{{/isNullable}} @cached_property def openapi_types(): """ - This must be a class method so a model may have properties that are - of type self, this ensures that we don't create a cyclic import + This must be a method because a model may have properties that are + of type self, this must run after the class is loaded Returns openapi_types (dict): The key is attribute name and the value is attribute type. """ +{{#imports}} +{{#-first}} + lazy_import() +{{/-first}} +{{/imports}} return { {{#isAlias}} 'value': ({{{dataType}}},), @@ -98,7 +119,20 @@ @cached_property def discriminator(): - {{^discriminator}}return None{{/discriminator}}{{#discriminator}}val = { +{{^discriminator}} + return None +{{/discriminator}} +{{#discriminator}} +{{#mappedModels}} +{{#-first}} +{{#imports}} +{{#-first}} + lazy_import() +{{/-first}} +{{/imports}} +{{/-first}} +{{/mappedModels}} + val = { {{#mappedModels}} '{{mappingName}}': {{{modelName}}}, {{/mappedModels}} diff --git a/python-experimental/model_templates/model_composed.mustache b/python-experimental/model_templates/model_composed.mustache index 7e9e86cbfc..dd61b23c79 100644 --- a/python-experimental/model_templates/model_composed.mustache +++ b/python-experimental/model_templates/model_composed.mustache @@ -1,4 +1,4 @@ -class {{unescapedDescription}}(ModelComposed): +class {{classname}}(ModelComposed): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech @@ -35,6 +35,11 @@ class {{unescapedDescription}}(ModelComposed): # code would be run when this module is imported, and these composed # classes don't exist yet because their module has not finished # loading +{{#imports}} +{{#-first}} + lazy_import() +{{/-first}} +{{/imports}} return { 'anyOf': [ {{#anyOf}} diff --git a/python-experimental/model_templates/model_normal.mustache b/python-experimental/model_templates/model_normal.mustache index 21254c55d1..af130c66a7 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/python-experimental/model_templates/model_normal.mustache @@ -1,4 +1,4 @@ -class {{unescapedDescription}}(ModelNormal): +class {{classname}}(ModelNormal): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech diff --git a/python-experimental/model_templates/model_simple.mustache b/python-experimental/model_templates/model_simple.mustache index 1623ca5f6e..0b7d1860dd 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/python-experimental/model_templates/model_simple.mustache @@ -1,4 +1,4 @@ -class {{unescapedDescription}}(ModelSimple): +class {{classname}}(ModelSimple): """NOTE: This class is auto generated by OpenAPI Generator. Ref: https://openapi-generator.tech diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index ab30c2dcb0..400cfe3509 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -33,9 +33,9 @@ class cached_property(object): self._fn = fn def __get__(self, instance, cls=None): - try: + if self.result_key in vars(self): return vars(self)[self.result_key] - except KeyError: + else: result = self._fn() setattr(self, self.result_key, result) return result From 9302ebe9e82aa06392aa3f56bbcebe1559db515d Mon Sep 17 00:00:00 2001 From: Justin Black Date: Tue, 28 Jul 2020 08:16:19 -0700 Subject: [PATCH 133/180] [python-experimental] simplifies json serialization (#7061) * Requires python >= 3.5, adds type hints to call_api method * Adds type hints to files_parameters and __call_api * Adds and uses a new json encoded to prepare data before it is sent * Removes nose name from gitlab testing invocations * Also updates travis to py>=3.5 * Collapses encoder back into sanitize_for_serialization --- python-experimental/README.mustache | 2 +- .../README_onlypackage.mustache | 2 +- python-experimental/api_client.mustache | 97 +++++++++++-------- python-experimental/gitlab-ci.mustache | 24 ++--- python-experimental/setup.mustache | 2 +- python-experimental/travis.mustache | 3 - 6 files changed, 67 insertions(+), 63 deletions(-) diff --git a/python-experimental/README.mustache b/python-experimental/README.mustache index 3fb507c574..7368913ef8 100644 --- a/python-experimental/README.mustache +++ b/python-experimental/README.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python 3.4+ +Python >= 3.5 ## Installation & Usage ### pip install diff --git a/python-experimental/README_onlypackage.mustache b/python-experimental/README_onlypackage.mustache index ee90ce7903..3ef048b67a 100644 --- a/python-experimental/README_onlypackage.mustache +++ b/python-experimental/README_onlypackage.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python 2.7 and 3.4+ +Python >= 3.5 ## Installation & Usage diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index b7112d202b..de4e2d478e 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -5,8 +5,10 @@ import json import atexit import mimetypes from multiprocessing.pool import ThreadPool +import io import os import re +import typing from urllib.parse import quote {{#tornado}} @@ -54,9 +56,6 @@ class ApiClient(object): to the API. More threads means more concurrent API requests. """ - PRIMITIVE_TYPES = ( - float, bool, bytes, str, int - ) _pool = None def __init__(self, configuration=None, header_name=None, header_value=None, @@ -114,12 +113,24 @@ class ApiClient(object): @tornado.gen.coroutine {{/tornado}} {{#asyncio}}async {{/asyncio}}def __call_api( - self, resource_path, method, path_params=None, - query_params=None, header_params=None, body=None, post_params=None, - files=None, response_type=None, auth_settings=None, - _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None, - _check_type=None): + self, + resource_path: str, + method: str, + path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + body: typing.Optional[typing.Any] = None, + post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, + response_type: typing.Optional[typing.Tuple[typing.Any]] = None, + auth_settings: typing.Optional[typing.List[str]] = None, + _return_http_data_only: typing.Optional[bool] = None, + collection_formats: typing.Optional[typing.Dict[str, str]] = None, + _preload_content: bool = True, + _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, + _host: typing.Optional[str] = None, + _check_type: typing.Optional[bool] = None + ): config = self.configuration @@ -232,9 +243,9 @@ class ApiClient(object): response_data.getheaders())) {{/tornado}} - def sanitize_for_serialization(self, obj): + @classmethod + def sanitize_for_serialization(cls, obj): """Builds a JSON POST object. - If obj is None, return None. If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date @@ -242,35 +253,24 @@ class ApiClient(object): If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. - :param obj: The data to serialize. :return: The serialized form of data. """ - if obj is None: - return None - elif isinstance(obj, self.PRIMITIVE_TYPES): + if isinstance(obj, (ModelNormal, ModelComposed)): + return { + key: cls.sanitize_for_serialization(val) for key, val in model_to_dict(obj, serialize=True).items() + } + elif isinstance(obj, (str, int, float, none_type, bool)): return obj - elif isinstance(obj, list): - return [self.sanitize_for_serialization(sub_obj) - for sub_obj in obj] - elif isinstance(obj, tuple): - return tuple(self.sanitize_for_serialization(sub_obj) - for sub_obj in obj) elif isinstance(obj, (datetime, date)): return obj.isoformat() - - if isinstance(obj, dict): - obj_dict = obj - elif isinstance(obj, ModelNormal) or isinstance(obj, ModelComposed): - # Convert model obj to dict - # Convert attribute name to json key in - # model definition for request - obj_dict = model_to_dict(obj, serialize=True) elif isinstance(obj, ModelSimple): - return self.sanitize_for_serialization(obj.value) - - return {key: self.sanitize_for_serialization(val) - for key, val in obj_dict.items()} + return cls.sanitize_for_serialization(obj.value) + elif isinstance(obj, (list, tuple)): + return [cls.sanitize_for_serialization(item) for item in obj] + if isinstance(obj, dict): + return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} + raise ApiValueError('Unable to prepare type {} for serialization'.format(obj.__class__.__name__)) def deserialize(self, response, response_type, _check_type): """Deserializes response into an object. @@ -317,13 +317,26 @@ class ApiClient(object): ) return deserialized_data - def call_api(self, resource_path, method, - path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, - response_type=None, auth_settings=None, async_req=None, - _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None, - _check_type=None): + def call_api( + self, + resource_path: str, + method: str, + path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + body: typing.Optional[typing.Any] = None, + post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, + response_type: typing.Optional[typing.Tuple[typing.Any]] = None, + auth_settings: typing.Optional[typing.List[str]] = None, + async_req: typing.Optional[bool] = None, + _return_http_data_only: typing.Optional[bool] = None, + collection_formats: typing.Optional[typing.Dict[str, str]] = None, + _preload_content: bool = True, + _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, + _host: typing.Optional[str] = None, + _check_type: typing.Optional[bool] = None + ): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -490,7 +503,7 @@ class ApiClient(object): new_params.append((k, v)) return new_params - def files_parameters(self, files=None): + def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None): """Builds form parameters. :param files: None or a dict with key=param_name and @@ -566,7 +579,7 @@ class ApiClient(object): :param resource_path: A string representation of the HTTP request resource path. :param method: A string representation of the HTTP request method. :param body: A object representing the body of the HTTP request. - The object type is the return value of sanitize_for_serialization(). + The object type is the return value of _encoder.default(). """ if not auth_settings: return diff --git a/python-experimental/gitlab-ci.mustache b/python-experimental/gitlab-ci.mustache index a626e9c084..60c4b37893 100644 --- a/python-experimental/gitlab-ci.mustache +++ b/python-experimental/gitlab-ci.mustache @@ -3,7 +3,7 @@ stages: - test -.nosetest: +.tests: stage: test script: - pip install -r requirements.txt @@ -15,21 +15,15 @@ stages: - pytest --cov={{{packageName}}} {{/useNose}} -nosetest-3.3: - extends: .nosetest - image: python:3.3-alpine -nosetest-3.4: - extends: .nosetest - image: python:3.4-alpine -nosetest-3.5: - extends: .nosetest +test-3.5: + extends: .tests image: python:3.5-alpine -nosetest-3.6: - extends: .nosetest +test-3.6: + extends: .tests image: python:3.6-alpine -nosetest-3.7: - extends: .nosetest +test-3.7: + extends: .tests image: python:3.7-alpine -nosetest-3.8: - extends: .nosetest +test-3.8: + extends: .tests image: python:3.8-alpine diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index b3c89f621e..4c3e32ef7d 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -41,7 +41,7 @@ setup( author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], - python_requires=">=3.3", + python_requires=">=3.5", install_requires=REQUIRES, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, diff --git a/python-experimental/travis.mustache b/python-experimental/travis.mustache index 77f7289f97..3c255f64e9 100644 --- a/python-experimental/travis.mustache +++ b/python-experimental/travis.mustache @@ -1,9 +1,6 @@ # ref: https://docs.travis-ci.com/user/languages/python language: python python: - - "3.2" - - "3.3" - - "3.4" - "3.5" - "3.6" - "3.7" From bb80c9c79229b110305935a9d8d65cfced2d07a9 Mon Sep 17 00:00:00 2001 From: Christian Gibson Date: Mon, 10 Aug 2020 13:11:29 -0700 Subject: [PATCH 134/180] [python{,-experimental}] Obey floating point timeouts provided to RESTClientObject.request(...) (#7154) * [fix] support floating point timeout durations * [lint] generate samples, rebuild project --- python-experimental/rest.mustache | 2 +- rest.mustache | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python-experimental/rest.mustache b/python-experimental/rest.mustache index d5edf9535d..746f984434 100644 --- a/python-experimental/rest.mustache +++ b/python-experimental/rest.mustache @@ -129,7 +129,7 @@ class RESTClientObject(object): timeout = None if _request_timeout: - if isinstance(_request_timeout, int): # noqa: E501,F821 + if isinstance(_request_timeout, (int, float)): # noqa: E501,F821 timeout = urllib3.Timeout(total=_request_timeout) elif (isinstance(_request_timeout, tuple) and len(_request_timeout) == 2): diff --git a/rest.mustache b/rest.mustache index fe7abfdfc0..51f72f6e1f 100644 --- a/rest.mustache +++ b/rest.mustache @@ -133,7 +133,7 @@ class RESTClientObject(object): timeout = None if _request_timeout: - if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)): # noqa: E501,F821 + if isinstance(_request_timeout, six.integer_types + (float, )): # noqa: E501,F821 timeout = urllib3.Timeout(total=_request_timeout) elif (isinstance(_request_timeout, tuple) and len(_request_timeout) == 2): From a5e3e523ea6955e35681dd5e6265bdaec5c0ef40 Mon Sep 17 00:00:00 2001 From: TIm Clark Date: Tue, 11 Aug 2020 21:38:58 -0400 Subject: [PATCH 135/180] [python-experimental] Fix model tests (#7139) * [python-experimental] Fix model tests * Fixes model tests to template off the classname instead of the model's description. * Uses python-experimental templates when generating python-experimental samples * Fix sample file manifest * Restore remaining tests --- python-experimental/model_test.mustache | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python-experimental/model_test.mustache b/python-experimental/model_test.mustache index c5ffe2c255..669cc12185 100644 --- a/python-experimental/model_test.mustache +++ b/python-experimental/model_test.mustache @@ -11,11 +11,11 @@ import {{packageName}} {{#imports}} {{{.}}} {{/imports}} -from {{modelPackage}}.{{classFilename}} import {{unescapedDescription}} +from {{modelPackage}}.{{classFilename}} import {{classname}} -class Test{{unescapedDescription}}(unittest.TestCase): - """{{unescapedDescription}} unit test stubs""" +class Test{{classname}}(unittest.TestCase): + """{{classname}} unit test stubs""" def setUp(self): pass @@ -23,10 +23,10 @@ class Test{{unescapedDescription}}(unittest.TestCase): def tearDown(self): pass - def test{{unescapedDescription}}(self): - """Test {{unescapedDescription}}""" + def test{{classname}}(self): + """Test {{classname}}""" # FIXME: construct object with mandatory attributes with example values - # model = {{unescapedDescription}}() # noqa: E501 + # model = {{classname}}() # noqa: E501 pass {{/model}} From 12266062043bf9b30392c31ae8f832e6042cb899 Mon Sep 17 00:00:00 2001 From: spacether Date: Wed, 19 Aug 2020 21:27:31 -0700 Subject: [PATCH 136/180] [python-exp] simplify examples (#7157) * Adds example setting code in python-experimental with one fn setting example values Fixes sample indentations Handles composed schema models, object model and arraymodels Adds brackets in arraymodel input Sets modelName with map schemas Removes included_schemas arguments, dicriminator examples do not include property examples Refactors modelName into toExampleValueRecursive argument Fixes bug where example models contained themselves Stops using model ExampleGenerator examples because they are inconsistent with the ones in python-experimental Uses example values if they exist Removes single quotes from enum examples Fixes password example Adds commented our regex handling, commented out because it breaks Handles AnyType schema examples Adds x_example values for simple string properties, uses toExampleValue for all example generation Adds examples for simple string parameters Updates comments in toExampleValueBase Fixes the double nested bug for AdditionalPropertiesWithArrayOfEnums Fixes bug where NumberWithValidations had double nesting Updates simple string examples in arrays Fixes array string examples Fixes example for string endpoint body example Adds exampleFromStringOrArraySchema Adds regex examples, pegs slf4j-version to v1.7.29 for rgxgen Adds comment about regex seed Updates pattern matcher to not handle ^ and $ Updates used sample values Adds ensureQuotes Adds ensureQuotes Fixes double quote bug Updates mustache file Adds ensureQuotes to key handling Adds modelNameToSchema map, reduces run time by using it Fixes java tests Regenerates python-experimental samples Fixes python test * Rebased on master * Adds getModelNameToSchemaCache * Updates toDefaultValue to not mutate schemas * Has all dates and datetimes default and example setting use the same helper function * Samples regenerated * indentation tweak, removes txt from sample file --- python-experimental/api_doc_example.mustache | 65 ++++++++++++-------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index b7bbc009f5..38d50dbd7c 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -16,44 +16,61 @@ with {{{packageName}}}.ApiClient() as api_client: {{/hasAuthMethods}} # Create an instance of the API class api_instance = {{classVarName}}.{{{classname}}}(api_client) - {{#requiredParams}}{{^defaultValue}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} - {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} - {{/optionalParams}} - {{#requiredParams}} - {{^hasMore}} +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} +{{/defaultValue}} +{{/requiredParams}} +{{#optionalParams}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} +{{/optionalParams}} +{{#requiredParams}} +{{^hasMore}} # example passing only required values which don't have defaults set try: - {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}){{#returnType}} - pprint(api_response){{/returnType}} +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}) +{{#returnType}} + pprint(api_response) +{{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) - {{/hasMore}} - {{/requiredParams}} - {{#optionalParams}} - {{^hasMore}} +{{/hasMore}} +{{/requiredParams}} +{{#optionalParams}} +{{^hasMore}} # example passing only required values which don't have defaults set # and optional values try: - {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}){{#returnType}} - pprint(api_response){{/returnType}} +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}) +{{#returnType}} + pprint(api_response) +{{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) - {{/hasMore}} - {{/optionalParams}} - {{^requiredParams}} - {{^optionalParams}} +{{/hasMore}} +{{/optionalParams}} +{{^requiredParams}} +{{^optionalParams}} # example, this endpoint has no required or optional parameters try: - {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}(){{#returnType}} - pprint(api_response){{/returnType}} +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}() +{{#returnType}} + pprint(api_response) +{{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) - {{/optionalParams}} - {{/requiredParams}} +{{/optionalParams}} +{{/requiredParams}} ``` From 97671b53ae76a092a81196a7d602c254579ba465 Mon Sep 17 00:00:00 2001 From: Ryan Rishi Date: Sat, 5 Sep 2020 11:22:04 -0600 Subject: [PATCH 137/180] Subclass Python exceptions (#7321) * Subclass Python exceptions: - UnauthorizedException (401) - ForbiddenException (403) - NotFoundException (404) - ServiceException [500 - 599] Fixes #2151 * add generated sample code * use Python 2 flavor inheritance * regenerate samples --- exceptions.mustache | 24 ++++++++++++++++++++++++ rest.mustache | 14 +++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/exceptions.mustache b/exceptions.mustache index b187ee9d47..6c77269533 100644 --- a/exceptions.mustache +++ b/exceptions.mustache @@ -120,6 +120,30 @@ class ApiException(OpenApiException): return error_message +class NotFoundException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(NotFoundException, self).__init__(status, reason, http_resp) + + +class UnauthorizedException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(UnauthorizedException, self).__init__(status, reason, http_resp) + + +class ForbiddenException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ForbiddenException, self).__init__(status, reason, http_resp) + + +class ServiceException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ServiceException, self).__init__(status, reason, http_resp) + + def render_path(path_to_item): """Returns a string representation of a path""" result = "" diff --git a/rest.mustache b/rest.mustache index 51f72f6e1f..05b46dadc1 100644 --- a/rest.mustache +++ b/rest.mustache @@ -16,7 +16,7 @@ import six from six.moves.urllib.parse import urlencode import urllib3 -from {{packageName}}.exceptions import ApiException, ApiValueError +from {{packageName}}.exceptions import ApiException, UnauthorizedException, ForbiddenException, NotFoundException, ServiceException, ApiValueError logger = logging.getLogger(__name__) @@ -213,6 +213,18 @@ class RESTClientObject(object): logger.debug("response body: %s", r.data) if not 200 <= r.status <= 299: + if r.status == 401: + raise UnauthorizedException(http_resp=r) + + if r.status == 403: + raise ForbiddenException(http_resp=r) + + if r.status == 404: + raise NotFoundException(http_resp=r) + + if 500 <= r.status <= 599: + raise ServiceException(http_resp=r) + raise ApiException(http_resp=r) return r From 24be170e9d5606ea595fc1351c733ce6fdf6c9c8 Mon Sep 17 00:00:00 2001 From: Nicholas Muesch Date: Tue, 15 Sep 2020 16:40:48 -0400 Subject: [PATCH 138/180] Support multiple api keys in python example documentation (#7417) * Support multiple api keys in config option * Regenerate samples * Update rest of examples --- python_doc_auth_partial.mustache | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/python_doc_auth_partial.mustache b/python_doc_auth_partial.mustache index 460c2df938..5106632d21 100644 --- a/python_doc_auth_partial.mustache +++ b/python_doc_auth_partial.mustache @@ -92,12 +92,8 @@ configuration = {{{packageName}}}.Configuration( {{#isApiKey}} # Configure API key authorization: {{{name}}} -configuration = {{{packageName}}}.Configuration( - host = "{{{basePath}}}", - api_key = { - '{{name}}': 'YOUR_API_KEY' - } -) +configuration.api_key['{{{name}}}'] = 'YOUR_API_KEY' + # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['{{name}}'] = 'Bearer' {{/isApiKey}} From fcdfa84252f85b7d88f1b76a44228987ebff0d09 Mon Sep 17 00:00:00 2001 From: spacether Date: Sun, 20 Sep 2020 10:55:54 -0700 Subject: [PATCH 139/180] Adds free form model generation in python-experimental (#7373) * Adds free form model generation in python-experimental * Adds hasValidation property to codegenModel * Adds separate variable val * Samples regenerated * Updates test_some_object.py * Adds two more boolean conditions * Runs ensure up to date * Updates tests to check that models are or are not generated * Removes unused import * Updates model names in java test * Removes unneeded test * Cleans up tests --- python-experimental/model_templates/classvars.mustache | 8 ++------ python-experimental/model_templates/validations.mustache | 6 ++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index ed121c5bfe..3a78919948 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -42,14 +42,10 @@ } validations = { -{{#isAlias}} -{{^isEnum}} -{{^isArrayModel}} +{{#hasValidation}} ('value',): { {{> python-experimental/model_templates/validations }} -{{/isArrayModel}} -{{/isEnum}} -{{/isAlias}} +{{/hasValidation}} {{#requiredVars}} {{#hasValidation}} ('{{name}}',): { diff --git a/python-experimental/model_templates/validations.mustache b/python-experimental/model_templates/validations.mustache index 6b91bffe22..9e26146d83 100644 --- a/python-experimental/model_templates/validations.mustache +++ b/python-experimental/model_templates/validations.mustache @@ -7,6 +7,12 @@ {{#maxItems}} 'max_items': {{maxItems}}, {{/maxItems}} +{{#minProperties}} + 'min_properties': {{minProperties}}, +{{/minProperties}} +{{#maxProperties}} + 'max_properties': {{maxProperties}}, +{{/maxProperties}} {{#minItems}} 'min_items': {{minItems}}, {{/minItems}} From 6f4f7383441ef3968af9319464f6331e8b30b3d1 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 23 Sep 2020 02:45:29 +0800 Subject: [PATCH 140/180] remove hardcoded PetApi (#7483) --- python-experimental/__init__api.mustache | 8 +++++++- python-experimental/__init__apis.mustache | 8 +++++--- python-experimental/api_client.mustache | 10 ++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/python-experimental/__init__api.mustache b/python-experimental/__init__api.mustache index 1d37d33951..8a9e6b91b9 100644 --- a/python-experimental/__init__api.mustache +++ b/python-experimental/__init__api.mustache @@ -1,3 +1,9 @@ +{{#apiInfo}} +{{#apis}} +{{#-first}} # do not import all apis into this module because that uses a lot of memory and stack frames # if you need the ability to import all apis from one package, import them with -# from {{packageName}.apis import DefaultApi, PetApi \ No newline at end of file +# from {{packageName}}.apis import {{classname}} +{{/-first}} +{{/apis}} +{{/apiInfo}} diff --git a/python-experimental/__init__apis.mustache b/python-experimental/__init__apis.mustache index da3937f8c5..32d101a97d 100644 --- a/python-experimental/__init__apis.mustache +++ b/python-experimental/__init__apis.mustache @@ -1,3 +1,6 @@ +{{#apiInfo}} +{{#apis}} +{{#-first}} # coding: utf-8 # flake8: noqa @@ -7,7 +10,7 @@ # raise a `RecursionError`. # In order to avoid this, import only the API that you directly need like: # -# from {{packagename}}.api.pet_api import PetApi +# from {{packagename}}.api.{{classVarName}} import {{classname}} # # or import this package, but before doing it, use: # @@ -15,8 +18,7 @@ # sys.setrecursionlimit(n) # Import APIs into API package: -{{#apiInfo}} -{{#apis}} +{{/-first}} from {{apiPackage}}.{{classVarName}} import {{classname}} {{/apis}} {{/apiInfo}} diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache index de4e2d478e..fd3d0b8a20 100644 --- a/python-experimental/api_client.mustache +++ b/python-experimental/api_client.mustache @@ -750,11 +750,13 @@ class Endpoint(object): def __call__(self, *args, **kwargs): """ This method is invoked when endpoints are called Example: - pet_api = PetApi() - pet_api.add_pet # this is an instance of the class Endpoint - pet_api.add_pet() # this invokes pet_api.add_pet.__call__() +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} + api_instance = {{classname}}() + api_instance.{{operationId}} # this is an instance of the class Endpoint + api_instance.{{operationId}}() # this invokes api_instance.{{operationId}}.__call__() which then invokes the callable functions stored in that endpoint at - pet_api.add_pet.callable or self.callable in this class + api_instance.{{operationId}}.callable or self.callable in this class +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} """ return self.callable(self, *args, **kwargs) From 6f0478fedcb637e22c028e9da5f2cee37a94f4db Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 25 Sep 2020 02:47:22 +0800 Subject: [PATCH 141/180] Add option to set recursion limit (#7491) * add option to set recursion limit * fix test failure * update doc * add tests * add missing import * rename option to recursionLimit --- __init__package.mustache | 4 ++++ python-experimental/__init__package.mustache | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/__init__package.mustache b/__init__package.mustache index aee16448ad..f81dd5735f 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -23,3 +23,7 @@ from {{packageName}}.exceptions import ApiException # import models into sdk package {{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} {{/model}}{{/models}} +{{#recursionLimit}} + +__import__('sys').setrecursionlimit({{{.}}}) +{{/recursionLimit}} diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache index d0746d3aa6..d7ff5b8260 100644 --- a/python-experimental/__init__package.mustache +++ b/python-experimental/__init__package.mustache @@ -21,4 +21,8 @@ from {{packageName}}.exceptions import ApiAttributeError from {{packageName}}.exceptions import ApiTypeError from {{packageName}}.exceptions import ApiValueError from {{packageName}}.exceptions import ApiKeyError -from {{packageName}}.exceptions import ApiException \ No newline at end of file +from {{packageName}}.exceptions import ApiException +{{#recursionLimit}} + +__import__('sys').setrecursionlimit({{{.}}}) +{{/recursionLimit}} From 20972a83eb0cc9bf0e99adb17d5063084deca711 Mon Sep 17 00:00:00 2001 From: Slavek Kabrda Date: Tue, 29 Sep 2020 19:56:52 +0200 Subject: [PATCH 142/180] [Python-experimental] Don't mandate passing in required value as argument (#7424) * [Python-experimental] Don't mandate passing in required value as argument * Remove usage of have_value * Address additional review comments * Fix tests according to the code change * Does not set None as value initial value, removes hasRequired tag usage, updates docstring Co-authored-by: Justin Black --- .../method_init_simple.mustache | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/python-experimental/model_templates/method_init_simple.mustache b/python-experimental/model_templates/method_init_simple.mustache index 9d59b7ba09..b71b80667c 100644 --- a/python-experimental/model_templates/method_init_simple.mustache +++ b/python-experimental/model_templates/method_init_simple.mustache @@ -8,30 +8,37 @@ ]) @convert_js_args_to_python_args - def __init__(self{{#hasRequired}}, value{{/hasRequired}}, *args, **kwargs): + def __init__(self, *args, **kwargs): """{{classname}} - a model defined in OpenAPI -{{#hasRequired}} + Note that value can be passed either in args or in kwargs, but not in both. + Args: - value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 + args[0] ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 -{{/hasRequired}} Keyword Args: -{{^hasRequired}} - value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 -{{/hasRequired}} + value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{> python-experimental/model_templates/docstring_init_required_kwargs }} """ -{{^hasRequired}} if 'value' in kwargs: value = kwargs.pop('value') elif args: args = list(args) value = args.pop(0) +{{#defaultValue}} else: value = {{{defaultValue}}} -{{/hasRequired}} +{{/defaultValue}} +{{^defaultValue}} + else: + raise ApiTypeError( + "value is required, but not passed in args or kwargs and doesn't have default", + path_to_item=_path_to_item, + valid_classes=(self.__class__,), + ) +{{/defaultValue}} + _check_type = kwargs.pop('_check_type', True) _spec_property_naming = kwargs.pop('_spec_property_naming', False) _path_to_item = kwargs.pop('_path_to_item', ()) From 92d76f470d94e7a014b766c6e051b27485f394d0 Mon Sep 17 00:00:00 2001 From: Kuzma <57258237+ksvirkou-hubspot@users.noreply.github.com> Date: Sat, 3 Oct 2020 18:37:08 +0300 Subject: [PATCH 143/180] [Python] correct return types if multiple responses are defined (#7427) * update python mustache templates * bug fix * rm response_type * generated samples * resolve conflict * samples * set None if a type is empty * regenerated samples --- api.mustache | 19 ++++++++++++++++++- api_client.mustache | 17 ++++++++++------- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/api.mustache b/api.mustache index 1dcbb86078..7cbea8a8bd 100644 --- a/api.mustache +++ b/api.mustache @@ -253,6 +253,23 @@ class {{classname}}(object): {{/hasConsumes}} # Authentication setting auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + + {{#returnType}} + {{#responses}} + {{#-first}} + response_types_map = { + {{/-first}} + {{^isWildcard}} + {{code}}: {{#dataType}}"{{dataType}}"{{/dataType}}{{^dataType}}None{{/dataType}}, + {{/isWildcard}} + {{#-last}} + } + {{/-last}} + {{/responses}} + {{/returnType}} + {{^returnType}} + response_types_map = {} + {{/returnType}} return self.api_client.call_api( '{{{path}}}', '{{httpMethod}}', @@ -262,7 +279,7 @@ class {{classname}}(object): body=body_params, post_params=form_params, files=local_var_files, - response_type={{#returnType}}'{{returnType}}'{{/returnType}}{{^returnType}}None{{/returnType}}, # noqa: E501 + response_types_map=response_types_map, auth_settings=auth_settings, async_req=local_var_params.get('async_req'), _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 diff --git a/api_client.mustache b/api_client.mustache index 7eb04b6943..a3e6eba30d 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -130,7 +130,7 @@ class ApiClient(object): {{#asyncio}}async {{/asyncio}}def __call_api( self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, - files=None, response_type=None, auth_settings=None, + files=None, response_types_map=None, auth_settings=None, _return_http_data_only=None, collection_formats=None, _preload_content=True, _request_timeout=None, _host=None, _request_auth=None): @@ -213,6 +213,8 @@ class ApiClient(object): {{#tornado}} raise tornado.gen.Return(return_data) {{/tornado}} + + response_type = response_types_map.get(response_data.status, None) if six.PY3 and response_type not in ["file", "bytes"]: match = None @@ -222,6 +224,7 @@ class ApiClient(object): response_data.data = response_data.data.decode(encoding) # deserialize response data + if response_type: return_data = self.deserialize(response_data, response_type) else: @@ -348,10 +351,10 @@ class ApiClient(object): def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, - response_type=None, auth_settings=None, async_req=None, - _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None, - _request_auth=None): + response_types_map=None, auth_settings=None, + async_req=None, _return_http_data_only=None, + collection_formats=None,_preload_content=True, + _request_timeout=None, _host=None, _request_auth=None): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -396,7 +399,7 @@ class ApiClient(object): return self.__call_api(resource_path, method, path_params, query_params, header_params, body, post_params, files, - response_type, auth_settings, + response_types_map, auth_settings, _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host, _request_auth) @@ -406,7 +409,7 @@ class ApiClient(object): query_params, header_params, body, post_params, files, - response_type, + response_types_map, auth_settings, _return_http_data_only, collection_formats, From 65ca911bcc9ebbefa5f298a1153d6241ea0e3df3 Mon Sep 17 00:00:00 2001 From: Maksym Melnychok Date: Fri, 9 Oct 2020 19:38:15 +0200 Subject: [PATCH 144/180] [python-experimental] implement `in` operator for model classes (#7637) * implement operator for model classes * refresh samples --- .../methods_setattr_getattr_composed.mustache | 18 +++++++++++++++++- .../methods_setattr_getattr_normal.mustache | 9 ++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index dd118d30f9..1a01fc472c 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -68,4 +68,20 @@ "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), path_to_item - ) \ No newline at end of file + ) + + def __contains__(self, name): + """this allows us to use `in` operator: `'attr' in instance`""" + + if name in self.required_properties: + return name in self.__dict__ + + model_instances = self._var_name_to_model_instances.get( + name, self._additional_properties_model_instances) + + if model_instances: + for model_instance in model_instances: + if name in model_instance._data_store: + return True + + return False diff --git a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache index 9fc6344908..32566dc684 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache @@ -22,4 +22,11 @@ "{0} has no attribute '{1}'".format( type(self).__name__, name), [name] - ) \ No newline at end of file + ) + + def __contains__(self, name): + """this allows us to use `in` operator: `'attr' in instance`""" + if name in self.required_properties: + return name in self.__dict__ + + return name in self.__dict__['_data_store'] From 68ee3ae9e5d9534cf968aff57f84ce1b7ab7d853 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Mon, 12 Oct 2020 09:12:37 -0700 Subject: [PATCH 145/180] Unifies naming for isMap in Schema class properties (#7640) * Updates isMapModel + isMapContainer -> isMap * Removes git conflict characters --- model.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/model.mustache b/model.mustache index 2b3299a6f2..1696dc55ba 100644 --- a/model.mustache +++ b/model.mustache @@ -127,7 +127,7 @@ class {{classname}}(object): ", ".join(map(str, allowed_values))) ) {{/isListContainer}} -{{#isMapContainer}} +{{#isMap}} if (self.local_vars_configuration.client_side_validation and not set({{{name}}}.keys()).issubset(set(allowed_values))): # noqa: E501 raise ValueError( @@ -135,7 +135,7 @@ class {{classname}}(object): .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 ", ".join(map(str, allowed_values))) ) -{{/isMapContainer}} +{{/isMap}} {{/isContainer}} {{^isContainer}} allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 From 4f22c218c107afb4c80315b185f5b43ccdda2d95 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Sun, 18 Oct 2020 21:58:59 -0700 Subject: [PATCH 146/180] Unifies naming for isArray in Schema class properties (#7691) * Updates key java files * Adds all lingering isArray fixes * Adds two files * Reverts two cs files * Fixes lingering isListContainer + isArrayModel references * Some ensure up to date updates --- api.mustache | 16 ++++++++-------- model.mustache | 4 ++-- python-experimental/model.mustache | 8 ++++---- python-experimental/model_doc.mustache | 4 ++-- .../model_templates/classvars.mustache | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/api.mustache b/api.mustache index 7cbea8a8bd..513738359c 100644 --- a/api.mustache +++ b/api.mustache @@ -208,30 +208,30 @@ class {{classname}}(object): path_params = {} {{#pathParams}} if '{{paramName}}' in local_var_params: - path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 + path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isArray}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 {{/pathParams}} query_params = [] {{#queryParams}} if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] is not None: # noqa: E501 - query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 + query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isArray}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 {{/queryParams}} header_params = {} {{#headerParams}} if '{{paramName}}' in local_var_params: - header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 + header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isArray}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 {{/headerParams}} form_params = [] local_var_files = {} {{#formParams}} if '{{paramName}}' in local_var_params: - {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isListContainer}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isListContainer}} # noqa: E501 + {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isArray}} # noqa: E501 + collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 {{/formParams}} body_params = None diff --git a/model.mustache b/model.mustache index 1696dc55ba..9760e7d5e8 100644 --- a/model.mustache +++ b/model.mustache @@ -118,7 +118,7 @@ class {{classname}}(object): {{#isEnum}} {{#isContainer}} allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 -{{#isListContainer}} +{{#isArray}} if (self.local_vars_configuration.client_side_validation and not set({{{name}}}).issubset(set(allowed_values))): # noqa: E501 raise ValueError( @@ -126,7 +126,7 @@ class {{classname}}(object): .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 ", ".join(map(str, allowed_values))) ) -{{/isListContainer}} +{{/isArray}} {{#isMap}} if (self.local_vars_configuration.client_side_validation and not set({{{name}}}.keys()).issubset(set(allowed_values))): # noqa: E501 diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache index 1a181b824d..1fc47d9056 100644 --- a/python-experimental/model.mustache +++ b/python-experimental/model.mustache @@ -33,22 +33,22 @@ def lazy_import(): {{^interfaces}} -{{#isArrayModel}} +{{#isArray}} {{> python-experimental/model_templates/model_simple }} -{{/isArrayModel}} +{{/isArray}} {{#isEnum}} {{> python-experimental/model_templates/model_simple }} {{/isEnum}} {{#isAlias}} {{> python-experimental/model_templates/model_simple }} {{/isAlias}} -{{^isArrayModel}} +{{^isArray}} {{^isEnum}} {{^isAlias}} {{> python-experimental/model_templates/model_normal }} {{/isAlias}} {{/isEnum}} -{{/isArrayModel}} +{{/isArray}} {{/interfaces}} {{#interfaces}} {{#-last}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache index b5aa50c432..7971d6c85f 100644 --- a/python-experimental/model_doc.mustache +++ b/python-experimental/model_doc.mustache @@ -11,9 +11,9 @@ Name | Type | Description | Notes {{#isAlias}} **value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} {{/isAlias}} -{{#isArrayModel}} +{{#isArray}} **value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}.md){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} -{{/isArrayModel}} +{{/isArray}} {{#requiredVars}} {{^defaultValue}} **{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} diff --git a/python-experimental/model_templates/classvars.mustache b/python-experimental/model_templates/classvars.mustache index 3a78919948..f2ea42679a 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/python-experimental/model_templates/classvars.mustache @@ -102,9 +102,9 @@ {{#isEnum}} 'value': ({{{dataType}}},), {{/isEnum}} -{{#isArrayModel}} +{{#isArray}} 'value': ({{{dataType}}},), -{{/isArrayModel}} +{{/isArray}} {{#requiredVars}} '{{name}}': ({{{dataType}}},), # noqa: E501 {{/requiredVars}} From e0c8b11fdf8cdfb9c5c119b9c728f8e4b9884ae8 Mon Sep 17 00:00:00 2001 From: Maksym Melnychok Date: Sun, 25 Oct 2020 17:13:22 +0100 Subject: [PATCH 147/180] [python] Add option to return None instead of raising exception when accessing unset attribute (#7784) * add option to return None instead of raising exception when accessing unset attribute * update python samples * reimplement getattr using getitem or get depending on attrNoneIfUnset * move getattr and setattr to respective templates * update docstrings, def get/setattr methods to have docstrings in them, use __dict__ to avoid recursion issues * revert required_properties change * add manual tests for .get method --- .../methods_setattr_getattr_composed.mustache | 43 ++++++++++--------- .../methods_setattr_getattr_normal.mustache | 26 +++++------ .../model_templates/methods_shared.mustache | 18 ++++---- 3 files changed, 44 insertions(+), 43 deletions(-) diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache index 1a01fc472c..6b1013ca99 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_composed.mustache @@ -1,5 +1,5 @@ - def __setattr__(self, name, value): - """this allows us to set a value with instance.field_name = val""" + def __setitem__(self, name, value): + """set the value of an attribute using square-bracket notation: `instance[attr] = val`""" if name in self.required_properties: self.__dict__[name] = value return @@ -20,28 +20,22 @@ ) return None - path_to_item = [] - if self._path_to_item: - path_to_item.extend(self._path_to_item) - path_to_item.append(name) raise ApiAttributeError( "{0} has no attribute '{1}'".format( type(self).__name__, name), - path_to_item + [e for e in [self._path_to_item, name] if e] ) - def __getattr__(self, name): - """this allows us to get a value with val = instance.field_name""" + __unset_attribute_value__ = object() + + def get(self, name, default=None): + """returns the value of an attribute or some default value if the attribute was not set""" if name in self.required_properties: return self.__dict__[name] # get the attribute from the correct instance model_instances = self._var_name_to_model_instances.get( name, self._additional_properties_model_instances) - path_to_item = [] - if self._path_to_item: - path_to_item.extend(self._path_to_item) - path_to_item.append(name) values = [] # A composed model stores child (oneof/anyOf/allOf) models under # self._var_name_to_model_instances. A named property can exist in @@ -55,11 +49,7 @@ values.append(v) len_values = len(values) if len_values == 0: - raise ApiAttributeError( - "{0} has no attribute '{1}'".format( - type(self).__name__, name), - path_to_item - ) + return default elif len_values == 1: return values[0] elif len_values > 1: @@ -67,11 +57,22 @@ "Values stored for property {0} in {1} differ when looking " "at self and self's composed instances. All values must be " "the same".format(name, type(self).__name__), - path_to_item + [e for e in [self._path_to_item, name] if e] + ) + + def __getitem__(self, name): + """get the value of an attribute using square-bracket notation: `instance[attr]`""" + value = self.get(name, self.__unset_attribute_value__) + if value is self.__unset_attribute_value__: + raise ApiAttributeError( + "{0} has no attribute '{1}'".format( + type(self).__name__, name), + [e for e in [self._path_to_item, name] if e] ) + return value def __contains__(self, name): - """this allows us to use `in` operator: `'attr' in instance`""" + """used by `in` operator to check if an attrbute value was set in an instance: `'attr' in instance`""" if name in self.required_properties: return name in self.__dict__ @@ -84,4 +85,4 @@ if name in model_instance._data_store: return True - return False + return False \ No newline at end of file diff --git a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache index 32566dc684..e700dad953 100644 --- a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache +++ b/python-experimental/model_templates/methods_setattr_getattr_normal.mustache @@ -1,32 +1,32 @@ - def __setattr__(self, name, value): - """this allows us to set a value with instance.field_name = val""" + def __setitem__(self, name, value): + """set the value of an attribute using square-bracket notation: `instance[attr] = val`""" if name in self.required_properties: self.__dict__[name] = value return self.set_attribute(name, value) - def __getattr__(self, name): - """this allows us to get a value with val = instance.field_name""" + def get(self, name, default=None): + """returns the value of an attribute or some default value if the attribute was not set""" if name in self.required_properties: return self.__dict__[name] - if name in self.__dict__['_data_store']: - return self.__dict__['_data_store'][name] + return self.__dict__['_data_store'].get(name, default) + + def __getitem__(self, name): + """get the value of an attribute using square-bracket notation: `instance[attr]`""" + if name in self: + return self.get(name) - path_to_item = [] - if self._path_to_item: - path_to_item.extend(self._path_to_item) - path_to_item.append(name) raise ApiAttributeError( "{0} has no attribute '{1}'".format( type(self).__name__, name), - [name] + [e for e in [self._path_to_item, name] if e] ) def __contains__(self, name): - """this allows us to use `in` operator: `'attr' in instance`""" + """used by `in` operator to check if an attrbute value was set in an instance: `'attr' in instance`""" if name in self.required_properties: return name in self.__dict__ - return name in self.__dict__['_data_store'] + return name in self.__dict__['_data_store'] \ No newline at end of file diff --git a/python-experimental/model_templates/methods_shared.mustache b/python-experimental/model_templates/methods_shared.mustache index d3cf66e41b..43bcf6fd0d 100644 --- a/python-experimental/model_templates/methods_shared.mustache +++ b/python-experimental/model_templates/methods_shared.mustache @@ -1,15 +1,15 @@ - def __setitem__(self, name, value): - """this allows us to set values with instance[field_name] = val""" - self.__setattr__(name, value) - - def __getitem__(self, name): - """this allows us to get a value with val = instance[field_name]""" - return self.__getattr__(name) - def __repr__(self): """For `print` and `pprint`""" return self.to_str() def __ne__(self, other): """Returns true if both objects are not equal""" - return not self == other \ No newline at end of file + return not self == other + + def __setattr__(self, attr, value): + """set the value of an attribute using dot notation: `instance.attr = val`""" + self[attr] = value + + def __getattr__(self, attr): + """get the value of an attribute using dot notation: `instance.attr`""" + return self.{{#attrNoneIfUnset}}get{{/attrNoneIfUnset}}{{^attrNoneIfUnset}}__getitem__{{/attrNoneIfUnset}}(attr) \ No newline at end of file From 9fcef2bf13775b012be35479fc0797380156d947 Mon Sep 17 00:00:00 2001 From: Steve B Date: Wed, 28 Oct 2020 02:22:28 +0100 Subject: [PATCH 148/180] [python] add socket_options to configuration for the rest client (#7795) * [python] add socket_options to configuration for the rest client * (python-experimental) add socket_options to configuration for the rest client This mirrors work done on the python generator * (python-experimental) add test to cover socket_options is passed on from configuration Co-authored-by: steve brazier --- configuration.mustache | 4 ++++ python-experimental/configuration.mustache | 3 +++ python-experimental/rest.mustache | 3 +++ rest.mustache | 3 +++ 4 files changed, 13 insertions(+) diff --git a/configuration.mustache b/configuration.mustache index 8025a1b655..9f2542f5a9 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -302,6 +302,10 @@ conf = {{{packageName}}}.Configuration( # Enable client side validation self.client_side_validation = True + self.socket_options = None + """Options to pass down to the underlying urllib3 socket + """ + def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) diff --git a/python-experimental/configuration.mustache b/python-experimental/configuration.mustache index 8b911bdddd..ca6fc37747 100644 --- a/python-experimental/configuration.mustache +++ b/python-experimental/configuration.mustache @@ -299,6 +299,9 @@ conf = {{{packageName}}}.Configuration( # Enable client side validation self.client_side_validation = True + # Options to pass down to the underlying urllib3 socket + self.socket_options = None + def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) diff --git a/python-experimental/rest.mustache b/python-experimental/rest.mustache index 746f984434..5fb2da0af2 100644 --- a/python-experimental/rest.mustache +++ b/python-experimental/rest.mustache @@ -64,6 +64,9 @@ class RESTClientObject(object): if configuration.retries is not None: addition_pool_args['retries'] = configuration.retries + if configuration.socket_options is not None: + addition_pool_args['socket_options'] = configuration.socket_options + if maxsize is None: if configuration.connection_pool_maxsize is not None: maxsize = configuration.connection_pool_maxsize diff --git a/rest.mustache b/rest.mustache index 05b46dadc1..3916878624 100644 --- a/rest.mustache +++ b/rest.mustache @@ -68,6 +68,9 @@ class RESTClientObject(object): if configuration.retries is not None: addition_pool_args['retries'] = configuration.retries + if configuration.socket_options is not None: + addition_pool_args['socket_options'] = configuration.socket_options + if maxsize is None: if configuration.connection_pool_maxsize is not None: maxsize = configuration.connection_pool_maxsize From aabb60701610eadb9d61eb68db77861c5acdafab Mon Sep 17 00:00:00 2001 From: Tomasz Prus Date: Wed, 4 Nov 2020 17:41:00 +0100 Subject: [PATCH 149/180] [python] check output content-type only if preload_content is set (#7847) --- api_client.mustache | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index a3e6eba30d..4f230dff62 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -200,8 +200,6 @@ class ApiClient(object): e.body = e.body.decode('utf-8') if six.PY3 else e.body raise e - content_type = response_data.getheader('content-type') - self.last_response = response_data return_data = response_data @@ -218,6 +216,7 @@ class ApiClient(object): if six.PY3 and response_type not in ["file", "bytes"]: match = None + content_type = response_data.getheader('content-type') if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) encoding = match.group(1) if match else "utf-8" From 997f98c0ae0c70a4cd22ca73473da2ccd4db8d1f Mon Sep 17 00:00:00 2001 From: debugman Date: Fri, 6 Nov 2020 01:42:35 +0800 Subject: [PATCH 150/180] added serialize option in to_dict function in python generated model (#7555) * added to_json_dict in python generated model * update to_dict * updated to_dict Co-authored-by: sunkaicheng --- model.mustache | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/model.mustache b/model.mustache index 9760e7d5e8..99820290f2 100644 --- a/model.mustache +++ b/model.mustache @@ -2,9 +2,9 @@ {{>partial_header}} +import inspect import pprint import re # noqa: F401 - import six from {{packageName}}.configuration import Configuration @@ -197,27 +197,35 @@ class {{classname}}(object): return self.discriminator_value_class_map.get(discriminator_value) {{/discriminator}} - def to_dict(self): + def to_dict(self, serialize=False): """Returns the model properties as a dict""" result = {} + def convert(x): + if hasattr(x, "to_dict"): + args = inspect.getargspec(x.to_dict).args + if len(args) == 1: + return x.to_dict() + else: + return x.to_dict(serialize) + else: + return x + for attr, _ in six.iteritems(self.openapi_types): value = getattr(self, attr) + attr = self.attribute_map.get(attr, attr) if serialize else attr if isinstance(value, list): result[attr] = list(map( - lambda x: x.to_dict() if hasattr(x, "to_dict") else x, + lambda x: convert(x), value )) - elif hasattr(value, "to_dict"): - result[attr] = value.to_dict() elif isinstance(value, dict): result[attr] = dict(map( - lambda item: (item[0], item[1].to_dict()) - if hasattr(item[1], "to_dict") else item, + lambda item: (item[0], convert(item[1])), value.items() )) else: - result[attr] = value + result[attr] = convert(value) return result From 29f961aa103b901039d5fbe045d26c815e8d5657 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 6 Nov 2020 19:04:12 -0800 Subject: [PATCH 151/180] Removes secondaryParam and hasMore (#7882) * Removes secondaryParam and hasMore * Fixes tests * Only uses bodyParam in groovy template --- api.mustache | 8 ++++---- api_doc.mustache | 6 +++--- api_doc_example.mustache | 2 +- common_README.mustache | 8 ++++---- model.mustache | 4 ++-- model_test.mustache | 2 +- python-experimental/README_common.mustache | 8 ++++---- python-experimental/api.mustache | 10 +++++----- python-experimental/api_doc.mustache | 6 +++--- python-experimental/api_doc_example.mustache | 12 ++++++------ python-experimental/setup.mustache | 4 ++-- setup.mustache | 4 ++-- 12 files changed, 37 insertions(+), 37 deletions(-) diff --git a/api.mustache b/api.mustache index 513738359c..38d137c3c4 100644 --- a/api.mustache +++ b/api.mustache @@ -133,7 +133,7 @@ class {{classname}}(object): all_params = [ {{#allParams}} - '{{paramName}}'{{#hasMore}},{{/hasMore}} + '{{paramName}}'{{^-last}},{{/-last}} {{/allParams}} ] all_params.extend( @@ -242,17 +242,17 @@ class {{classname}}(object): {{#hasProduces}} # HTTP header `Accept` header_params['Accept'] = self.api_client.select_header_accept( - [{{#produces}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/produces}}]) # noqa: E501 + [{{#produces}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/produces}}]) # noqa: E501 {{/hasProduces}} {{#hasConsumes}} # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 - [{{#consumes}}'{{{mediaType}}}'{{#hasMore}}, {{/hasMore}}{{/consumes}}]) # noqa: E501 + [{{#consumes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/consumes}}]) # noqa: E501 {{/hasConsumes}} # Authentication setting - auth_settings = [{{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}] # noqa: E501 + auth_settings = [{{#authMethods}}'{{name}}'{{^-last}}, {{/-last}}{{/authMethods}}] # noqa: E501 {{#returnType}} {{#responses}} diff --git a/api_doc.mustache b/api_doc.mustache index fb537ad30b..dddec91719 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -11,7 +11,7 @@ Method | HTTP request | Description {{#operations}} {{#operation}} # **{{{operationId}}}** -> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{paramName}}}{{/required}}{{^required}}{{{paramName}}}={{{paramName}}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{paramName}}}{{/required}}{{^required}}{{{paramName}}}={{{paramName}}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) {{{summary}}}{{#notes}} @@ -58,8 +58,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/api_doc_example.mustache b/api_doc_example.mustache index dadb8f6a96..526c5950a0 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -19,7 +19,7 @@ with {{{packageName}}}.ApiClient() as api_client: try: {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}} pprint(api_response){{/returnType}} except ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) diff --git a/common_README.mustache b/common_README.mustache index 37060d6d1f..12fa1322a7 100644 --- a/common_README.mustache +++ b/common_README.mustache @@ -1,6 +1,6 @@ ```python from __future__ import print_function -{{#apiInfo}}{{#apis}}{{^hasMore}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/-last}}{{/apis}}{{/apiInfo}} import time import {{{packageName}}} from {{{packageName}}}.rest import ApiException @@ -17,7 +17,7 @@ with {{{packageName}}}.ApiClient(configuration) as api_client: try: {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}} pprint(api_response){{/returnType}} except ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) @@ -73,5 +73,5 @@ Class | Method | HTTP request | Description ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/model.mustache b/model.mustache index 99820290f2..857a3e48fb 100644 --- a/model.mustache +++ b/model.mustache @@ -40,13 +40,13 @@ class {{classname}}(object): """ openapi_types = { {{#vars}} - '{{name}}': '{{{dataType}}}'{{#hasMore}},{{/hasMore}} + '{{name}}': '{{{dataType}}}'{{^-last}},{{/-last}} {{/vars}} } attribute_map = { {{#vars}} - '{{name}}': '{{baseName}}'{{#hasMore}},{{/hasMore}} + '{{name}}': '{{baseName}}'{{^-last}},{{/-last}} {{/vars}} } {{#discriminator}} diff --git a/model_test.mustache b/model_test.mustache index b69f13f744..cd55662e10 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -31,7 +31,7 @@ class Test{{classname}}(unittest.TestCase): if include_optional : return {{classname}}( {{#vars}} - {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}{{#hasMore}}, {{/hasMore}} + {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}{{^-last}}, {{/-last}} {{/vars}} ) else : diff --git a/python-experimental/README_common.mustache b/python-experimental/README_common.mustache index d3844fd15f..ec525d175b 100644 --- a/python-experimental/README_common.mustache +++ b/python-experimental/README_common.mustache @@ -1,5 +1,5 @@ ```python -{{#apiInfo}}{{#apis}}{{^hasMore}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/-last}}{{/apis}}{{/apiInfo}} import time import {{{packageName}}} from pprint import pprint @@ -24,7 +24,7 @@ with {{{packageName}}}.ApiClient(configuration) as api_client: try: {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}}){{#returnType}} + {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}} pprint(api_response){{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) @@ -88,8 +88,8 @@ Class | Method | HTTP request | Description ## Author -{{#apiInfo}}{{#apis}}{{^hasMore}}{{infoEmail}} -{{/hasMore}}{{/apis}}{{/apiInfo}} +{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} +{{/-last}}{{/apis}}{{/apiInfo}} ## Notes for Large OpenAPI documents If the OpenAPI document is large, imports in {{{packageName}}}.apis and {{{packageName}}}.models may fail with a diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache index 776acbf5ec..0e76b3f29f 100644 --- a/python-experimental/api.mustache +++ b/python-experimental/api.mustache @@ -60,9 +60,9 @@ class {{classname}}(object): >>> result = thread.get() {{#requiredParams}} -{{^hasMore}} +{{#-last}} Args: -{{/hasMore}} +{{/-last}} {{/requiredParams}} {{#requiredParams}} {{^defaultValue}} @@ -134,7 +134,7 @@ class {{classname}}(object): {{#-first}} 'auth': [ {{/-first}} - '{{name}}'{{#hasMore}},{{/hasMore}} + '{{name}}'{{^-last}},{{/-last}} {{#-last}} ], {{/-last}} @@ -283,7 +283,7 @@ class {{classname}}(object): {{#hasProduces}} 'accept': [ {{#produces}} - '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} + '{{{mediaType}}}'{{^-last}},{{/-last}} {{/produces}} ], {{/hasProduces}} @@ -293,7 +293,7 @@ class {{classname}}(object): {{#hasConsumes}} 'content_type': [ {{#consumes}} - '{{{mediaType}}}'{{#hasMore}},{{/hasMore}} + '{{{mediaType}}}'{{^-last}},{{/-last}} {{/consumes}} ] {{/hasConsumes}} diff --git a/python-experimental/api_doc.mustache b/python-experimental/api_doc.mustache index 10317b4b48..f9dac707f7 100644 --- a/python-experimental/api_doc.mustache +++ b/python-experimental/api_doc.mustache @@ -11,7 +11,7 @@ Method | HTTP request | Description {{#operations}} {{#operation}} # **{{{operationId}}}** -> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}) +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) {{{summary}}}{{#notes}} @@ -57,8 +57,8 @@ Name | Type | Description | Notes ### HTTP request headers - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{#hasMore}}, {{/hasMore}}{{/produces}}{{^produces}}Not defined{{/produces}} + - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} + - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} ### HTTP response details diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache index 38d50dbd7c..bf989ae430 100644 --- a/python-experimental/api_doc_example.mustache +++ b/python-experimental/api_doc_example.mustache @@ -25,23 +25,23 @@ with {{{packageName}}}.ApiClient() as api_client: {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} {{#requiredParams}} -{{^hasMore}} +{{#-last}} # example passing only required values which don't have defaults set try: {{#summary}} # {{{.}}} {{/summary}} - {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/defaultValue}}{{/requiredParams}}) + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) {{#returnType}} pprint(api_response) {{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/hasMore}} +{{/-last}} {{/requiredParams}} {{#optionalParams}} -{{^hasMore}} +{{#-last}} # example passing only required values which don't have defaults set # and optional values @@ -49,13 +49,13 @@ with {{{packageName}}}.ApiClient() as api_client: {{#summary}} # {{{.}}} {{/summary}} - {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{#hasMore}}, {{/hasMore}}{{/optionalParams}}) + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{^-last}}, {{/-last}}{{/optionalParams}}) {{#returnType}} pprint(api_response) {{/returnType}} except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/hasMore}} +{{/-last}} {{/optionalParams}} {{^requiredParams}} {{^optionalParams}} diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache index 4c3e32ef7d..632584a592 100644 --- a/python-experimental/setup.mustache +++ b/python-experimental/setup.mustache @@ -8,7 +8,7 @@ NAME = "{{{projectName}}}" VERSION = "{{packageVersion}}" {{#apiInfo}} {{#apis}} -{{^hasMore}} +{{#-last}} # To install the library, run the following # # python setup.py install @@ -50,6 +50,6 @@ setup( {{appDescription}} # noqa: E501 """ ) -{{/hasMore}} +{{/-last}} {{/apis}} {{/apiInfo}} diff --git a/setup.mustache b/setup.mustache index a41fee1467..a14de4016f 100644 --- a/setup.mustache +++ b/setup.mustache @@ -8,7 +8,7 @@ NAME = "{{{projectName}}}" VERSION = "{{packageVersion}}" {{#apiInfo}} {{#apis}} -{{^hasMore}} +{{#-last}} # To install the library, run the following # # python setup.py install @@ -40,6 +40,6 @@ setup( {{appDescription}} # noqa: E501 """ ) -{{/hasMore}} +{{/-last}} {{/apis}} {{/apiInfo}} From 29501553532dbd0cce57ed37b58bde4795f4371c Mon Sep 17 00:00:00 2001 From: Nicholas Muesch Date: Sun, 8 Nov 2020 15:27:58 -0500 Subject: [PATCH 152/180] Skip validation if input_value is None (#7845) --- python-experimental/model_utils.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python-experimental/model_utils.mustache b/python-experimental/model_utils.mustache index 400cfe3509..72a5cbe429 100644 --- a/python-experimental/model_utils.mustache +++ b/python-experimental/model_utils.mustache @@ -455,6 +455,9 @@ def check_validations( configuration (Configuration): the configuration class. """ + if input_values is None: + return + current_validations = validations[input_variable_path] if (is_json_validation_enabled('multipleOf', configuration) and 'multiple_of' in current_validations and From 1699424e0ffb793814dffae64e7d6fb30c57ff6e Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 18 Nov 2020 14:34:00 +0800 Subject: [PATCH 153/180] [python] Renames python generators (#7965) * python->python-legacy, python-experimental->python * test with openjdk8 * test with openjdk11 * comment out rm * move kotlin tests to circleci * move kotlin tests * move tests to circleci * fix circleci * rearrange test * move tests * use wrapper Co-authored-by: Justin Black --- README.mustache | 4 +- ..._common.mustache => README_common.mustache | 0 README_onlypackage.mustache | 5 +- __init__api.mustache | 16 +- ...it__apis.mustache => __init__apis.mustache | 0 __init__model.mustache | 15 +- ...models.mustache => __init__models.mustache | 0 __init__package.mustache | 17 +- api.mustache | 514 +++++------ api_client.mustache | 714 +++++++++------ api_doc.mustache | 11 +- api_doc_example.mustache | 68 +- api_test.mustache | 5 +- common_README.mustache | 77 -- configuration.mustache | 22 +- exceptions.mustache | 28 +- gitlab-ci.mustache | 27 +- model.mustache | 279 +----- model_doc.mustache | 27 +- .../classvars.mustache | 6 +- .../docstring_allowed.mustache | 0 .../docstring_init_required_kwargs.mustache | 0 .../docstring_openapi_validations.mustache | 0 .../method_init_composed.mustache | 2 +- .../method_init_normal.mustache | 2 +- .../method_init_shared.mustache | 2 +- .../method_init_simple.mustache | 2 +- .../method_set_attribute.mustache | 0 .../methods_setattr_getattr_composed.mustache | 0 .../methods_setattr_getattr_normal.mustache | 0 .../methods_shared.mustache | 0 .../methods_todict_tostr_eq_shared.mustache | 0 .../methods_tostr_eq_simple.mustache | 0 .../model_composed.mustache | 8 +- .../model_normal.mustache | 8 +- .../model_simple.mustache | 8 +- .../validations.mustache | 0 model_test.mustache | 39 +- ...del_utils.mustache => model_utils.mustache | 16 +- python-experimental/README.mustache | 55 -- .../README_onlypackage.mustache | 43 - python-experimental/__init__api.mustache | 9 - python-experimental/__init__model.mustache | 5 - python-experimental/__init__package.mustache | 28 - python-experimental/api.mustache | 308 ------- python-experimental/api_client.mustache | 839 ------------------ python-experimental/api_doc.mustache | 75 -- python-experimental/api_doc_example.mustache | 76 -- python-experimental/api_test.mustache | 34 - python-experimental/configuration.mustache | 635 ------------- python-experimental/exceptions.mustache | 129 --- python-experimental/gitlab-ci.mustache | 29 - python-experimental/model.mustache | 59 -- python-experimental/model_doc.mustache | 36 - python-experimental/model_test.mustache | 36 - python-experimental/requirements.mustache | 5 - python-experimental/rest.mustache | 282 ------ python-experimental/setup.mustache | 55 -- .../test-requirements.mustache | 15 - python-experimental/tox.mustache | 9 - python-experimental/travis.mustache | 18 - requirements.mustache | 3 +- rest.mustache | 22 +- setup.mustache | 16 +- .../signing.mustache => signing.mustache | 0 test-requirements.mustache | 9 +- tox.mustache | 5 - travis.mustache | 4 - 68 files changed, 919 insertions(+), 3842 deletions(-) rename python-experimental/README_common.mustache => README_common.mustache (100%) rename python-experimental/__init__apis.mustache => __init__apis.mustache (100%) rename python-experimental/__init__models.mustache => __init__models.mustache (100%) delete mode 100644 common_README.mustache rename {python-experimental/model_templates => model_templates}/classvars.mustache (94%) rename {python-experimental/model_templates => model_templates}/docstring_allowed.mustache (100%) rename {python-experimental/model_templates => model_templates}/docstring_init_required_kwargs.mustache (100%) rename {python-experimental/model_templates => model_templates}/docstring_openapi_validations.mustache (100%) rename {python-experimental/model_templates => model_templates}/method_init_composed.mustache (96%) rename {python-experimental/model_templates => model_templates}/method_init_normal.mustache (92%) rename {python-experimental/model_templates => model_templates}/method_init_shared.mustache (96%) rename {python-experimental/model_templates => model_templates}/method_init_simple.mustache (97%) rename {python-experimental/model_templates => model_templates}/method_set_attribute.mustache (100%) rename {python-experimental/model_templates => model_templates}/methods_setattr_getattr_composed.mustache (100%) rename {python-experimental/model_templates => model_templates}/methods_setattr_getattr_normal.mustache (100%) rename {python-experimental/model_templates => model_templates}/methods_shared.mustache (100%) rename {python-experimental/model_templates => model_templates}/methods_todict_tostr_eq_shared.mustache (100%) rename {python-experimental/model_templates => model_templates}/methods_tostr_eq_simple.mustache (100%) rename {python-experimental/model_templates => model_templates}/model_composed.mustache (85%) rename {python-experimental/model_templates => model_templates}/model_normal.mustache (73%) rename {python-experimental/model_templates => model_templates}/model_simple.mustache (50%) rename {python-experimental/model_templates => model_templates}/validations.mustache (100%) rename python-experimental/model_utils.mustache => model_utils.mustache (99%) delete mode 100644 python-experimental/README.mustache delete mode 100644 python-experimental/README_onlypackage.mustache delete mode 100644 python-experimental/__init__api.mustache delete mode 100644 python-experimental/__init__model.mustache delete mode 100644 python-experimental/__init__package.mustache delete mode 100644 python-experimental/api.mustache delete mode 100644 python-experimental/api_client.mustache delete mode 100644 python-experimental/api_doc.mustache delete mode 100644 python-experimental/api_doc_example.mustache delete mode 100644 python-experimental/api_test.mustache delete mode 100644 python-experimental/configuration.mustache delete mode 100644 python-experimental/exceptions.mustache delete mode 100644 python-experimental/gitlab-ci.mustache delete mode 100644 python-experimental/model.mustache delete mode 100644 python-experimental/model_doc.mustache delete mode 100644 python-experimental/model_test.mustache delete mode 100644 python-experimental/requirements.mustache delete mode 100644 python-experimental/rest.mustache delete mode 100644 python-experimental/setup.mustache delete mode 100644 python-experimental/test-requirements.mustache delete mode 100644 python-experimental/tox.mustache delete mode 100644 python-experimental/travis.mustache rename python-experimental/signing.mustache => signing.mustache (100%) diff --git a/README.mustache b/README.mustache index 9d854a4f1b..463e4e0d56 100644 --- a/README.mustache +++ b/README.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python 2.7 and 3.4+ +Python >= 3.5 ## Installation & Usage ### pip install @@ -52,4 +52,4 @@ import {{{packageName}}} Please follow the [installation procedure](#installation--usage) and then run the following: -{{> common_README }} +{{> README_common }} diff --git a/python-experimental/README_common.mustache b/README_common.mustache similarity index 100% rename from python-experimental/README_common.mustache rename to README_common.mustache diff --git a/README_onlypackage.mustache b/README_onlypackage.mustache index 826454b1ea..40dc242b7b 100644 --- a/README_onlypackage.mustache +++ b/README_onlypackage.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python 2.7 and 3.4+ +Python >= 3.5 ## Installation & Usage @@ -26,7 +26,6 @@ This python library package is generated without supporting files like setup.py To be able to use it, you will need these dependencies in your own package that uses this library: * urllib3 >= 1.15 -* six >= 1.10 * certifi * python-dateutil {{#asyncio}} @@ -41,4 +40,4 @@ To be able to use it, you will need these dependencies in your own package that In your own code, to use this library to connect and interact with {{{projectName}}}, you can run the following: -{{> common_README }} +{{> README_common }} diff --git a/__init__api.mustache b/__init__api.mustache index db658a10fa..8a9e6b91b9 100644 --- a/__init__api.mustache +++ b/__init__api.mustache @@ -1,7 +1,9 @@ -from __future__ import absolute_import - -# flake8: noqa - -# import apis into api package -{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} -{{/apis}}{{/apiInfo}} \ No newline at end of file +{{#apiInfo}} +{{#apis}} +{{#-first}} +# do not import all apis into this module because that uses a lot of memory and stack frames +# if you need the ability to import all apis from one package, import them with +# from {{packageName}}.apis import {{classname}} +{{/-first}} +{{/apis}} +{{/apiInfo}} diff --git a/python-experimental/__init__apis.mustache b/__init__apis.mustache similarity index 100% rename from python-experimental/__init__apis.mustache rename to __init__apis.mustache diff --git a/__init__model.mustache b/__init__model.mustache index 2266b3d17f..cfe32b7849 100644 --- a/__init__model.mustache +++ b/__init__model.mustache @@ -1,10 +1,5 @@ -# coding: utf-8 - -# flake8: noqa -{{>partial_header}} - -from __future__ import absolute_import - -# import models into model package -{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}}{{/model}} -{{/models}} +# we can not import model classes here because that would create a circular +# reference which would not work in python2 +# do not import all models into this module because that uses a lot of memory and stack frames +# if you need the ability to import all models from one package, import them with +# from {{packageName}.models import ModelA, ModelB diff --git a/python-experimental/__init__models.mustache b/__init__models.mustache similarity index 100% rename from python-experimental/__init__models.mustache rename to __init__models.mustache diff --git a/__init__package.mustache b/__init__package.mustache index f81dd5735f..d7ff5b8260 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -4,25 +4,24 @@ {{>partial_header}} -from __future__ import absolute_import - __version__ = "{{packageVersion}}" -# import apis into sdk package -{{#apiInfo}}{{#apis}}from {{apiPackage}}.{{classVarName}} import {{classname}} -{{/apis}}{{/apiInfo}} # import ApiClient from {{packageName}}.api_client import ApiClient + +# import Configuration from {{packageName}}.configuration import Configuration +{{#hasHttpSignatureMethods}} +from {{packageName}}.signing import HttpSigningConfiguration +{{/hasHttpSignatureMethods}} + +# import exceptions from {{packageName}}.exceptions import OpenApiException +from {{packageName}}.exceptions import ApiAttributeError from {{packageName}}.exceptions import ApiTypeError from {{packageName}}.exceptions import ApiValueError from {{packageName}}.exceptions import ApiKeyError -from {{packageName}}.exceptions import ApiAttributeError from {{packageName}}.exceptions import ApiException -# import models into sdk package -{{#models}}{{#model}}from {{modelPackage}}.{{classFilename}} import {{classname}} -{{/model}}{{/models}} {{#recursionLimit}} __import__('sys').setrecursionlimit({{{.}}}) diff --git a/api.mustache b/api.mustache index 38d137c3c4..0e76b3f29f 100644 --- a/api.mustache +++ b/api.mustache @@ -2,18 +2,22 @@ {{>partial_header}} -from __future__ import absolute_import - import re # noqa: F401 +import sys # noqa: F401 -# python 2 and python 3 compatibility library -import six - -from {{packageName}}.api_client import ApiClient -from {{packageName}}.exceptions import ( # noqa: F401 - ApiTypeError, - ApiValueError +from {{packageName}}.api_client import ApiClient, Endpoint +from {{packageName}}.model_utils import ( # noqa: F401 + check_allowed_values, + check_validations, + date, + datetime, + file_type, + none_type, + validate_and_convert_types ) +{{#imports}} +{{{import}}} +{{/imports}} {{#operations}} @@ -30,265 +34,275 @@ class {{classname}}(object): self.api_client = api_client {{#operation}} - def {{operationId}}(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 - """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 + def __{{operationId}}( + self, +{{#requiredParams}} +{{^defaultValue}} + {{paramName}}, +{{/defaultValue}} +{{/requiredParams}} +{{#requiredParams}} +{{#defaultValue}} + {{paramName}}={{{defaultValue}}}, +{{/defaultValue}} +{{/requiredParams}} + **kwargs + ): + """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 {{#notes}} - {{{notes}}} # noqa: E501 + {{{notes}}} # noqa: E501 {{/notes}} - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True + This method makes a synchronous HTTP request by default. To make an + asynchronous HTTP request, please pass async_req=True -{{#sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} -{{^sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} - >>> result = thread.get() + >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) + >>> result = thread.get() -{{#allParams}} - :param {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} - :type {{paramName}}: {{dataType}}{{#optional}}, optional{{/optional}} -{{/allParams}} - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _preload_content: if False, the urllib3.HTTPResponse object will - be returned without reading/decoding response - data. Default is True. - :type _preload_content: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} - """ - kwargs['_return_http_data_only'] = True - return self.{{operationId}}_with_http_info({{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs) # noqa: E501 - - def {{operationId}}_with_http_info(self, {{#sortParamsByRequiredFlag}}{{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}{{/sortParamsByRequiredFlag}}**kwargs): # noqa: E501 - """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 - -{{#notes}} - {{{notes}}} # noqa: E501 -{{/notes}} - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True +{{#requiredParams}} +{{#-last}} + Args: +{{/-last}} +{{/requiredParams}} +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}} +{{/defaultValue}} +{{/requiredParams}} +{{#requiredParams}} +{{#defaultValue}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] +{{/defaultValue}} +{{/requiredParams}} -{{#sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} -{{^sortParamsByRequiredFlag}} - >>> thread = api.{{operationId}}_with_http_info({{#allParams}}{{#required}}{{paramName}}={{paramName}}_value, {{/required}}{{/allParams}}async_req=True) -{{/sortParamsByRequiredFlag}} - >>> result = thread.get() + Keyword Args:{{#optionalParams}} + {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} + _return_http_data_only (bool): response data without head status + code and headers. Default is True. + _preload_content (bool): if False, the urllib3.HTTPResponse object + will be returned without reading/decoding response data. + Default is True. + _request_timeout (float/tuple): timeout setting for this request. If one + number provided, it will be total request timeout. It can also + be a pair (tuple) of (connection, read) timeouts. + Default is None. + _check_input_type (bool): specifies if type checking + should be done one the data sent to the server. + Default is True. + _check_return_type (bool): specifies if type checking + should be done one the data received from the server. + Default is True. + _host_index (int/None): specifies the index of the server + that we want to use. + Default is read from the configuration. + async_req (bool): execute request asynchronously -{{#allParams}} - :param {{paramName}}:{{#description}} {{{description}}}{{/description}}{{#required}} (required){{/required}}{{#optional}}(optional){{/optional}} - :type {{paramName}}: {{dataType}}{{#optional}}, optional{{/optional}} -{{/allParams}} - :param async_req: Whether to execute the request asynchronously. - :type async_req: bool, optional - :param _return_http_data_only: response data without head status code - and headers - :type _return_http_data_only: bool, optional - :param _preload_content: if False, the urllib3.HTTPResponse object will - be returned without reading/decoding response - data. Default is True. - :type _preload_content: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_auth: dict, optional - :return: Returns the result object. - If the method is called asynchronously, - returns the request thread. - :rtype: {{#returnType}}tuple({{returnType}}, status_code(int), headers(HTTPHeaderDict)){{/returnType}}{{^returnType}}None{{/returnType}} - """ + Returns: + {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} + If the method is called asynchronously, returns the request + thread. + """ + kwargs['async_req'] = kwargs.get( + 'async_req', False + ) + kwargs['_return_http_data_only'] = kwargs.get( + '_return_http_data_only', True + ) + kwargs['_preload_content'] = kwargs.get( + '_preload_content', True + ) + kwargs['_request_timeout'] = kwargs.get( + '_request_timeout', None + ) + kwargs['_check_input_type'] = kwargs.get( + '_check_input_type', True + ) + kwargs['_check_return_type'] = kwargs.get( + '_check_return_type', True + ) + kwargs['_host_index'] = kwargs.get('_host_index') +{{#requiredParams}} + kwargs['{{paramName}}'] = \ + {{paramName}} +{{/requiredParams}} + return self.call_with_http_info(**kwargs) - {{#servers.0}} - local_var_hosts = [ + self.{{operationId}} = Endpoint( + settings={ + 'response_type': {{#returnType}}({{{returnType}}},){{/returnType}}{{^returnType}}None{{/returnType}}, +{{#authMethods}} +{{#-first}} + 'auth': [ +{{/-first}} + '{{name}}'{{^-last}},{{/-last}} +{{#-last}} + ], +{{/-last}} +{{/authMethods}} +{{^authMethods}} + 'auth': [], +{{/authMethods}} + 'endpoint_path': '{{{path}}}', + 'operation_id': '{{operationId}}', + 'http_method': '{{httpMethod}}', {{#servers}} - '{{{url}}}'{{^-last}},{{/-last}} +{{#-first}} + 'servers': [ +{{/-first}} + { + 'url': "{{{url}}}", + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + {{#variables}} + {{#-first}} + 'variables': { + {{/-first}} + '{{{name}}}': { + 'description': "{{{description}}}{{^description}}No description provided{{/description}}", + 'default_value': "{{{defaultValue}}}", + {{#enumValues}} + {{#-first}} + 'enum_values': [ + {{/-first}} + "{{{.}}}"{{^-last}},{{/-last}} + {{#-last}} + ] + {{/-last}} + {{/enumValues}} + }{{^-last}},{{/-last}} + {{#-last}} + } + {{/-last}} + {{/variables}} + }, +{{#-last}} + ] +{{/-last}} {{/servers}} - ] - local_var_host = local_var_hosts[0] - if kwargs.get('_host_index'): - _host_index = int(kwargs.get('_host_index')) - if _host_index < 0 or _host_index >= len(local_var_hosts): - raise ApiValueError( - "Invalid host index. Must be 0 <= index < %s" - % len(local_var_host) - ) - local_var_host = local_var_hosts[_host_index] - {{/servers.0}} - local_var_params = locals() - - all_params = [ +{{^servers}} + 'servers': None, +{{/servers}} + }, + params_map={ + 'all': [ {{#allParams}} - '{{paramName}}'{{^-last}},{{/-last}} + '{{paramName}}', {{/allParams}} - ] - all_params.extend( - [ - 'async_req', - '_return_http_data_only', - '_preload_content', - '_request_timeout', - '_request_auth' - ] - ) - - for key, val in six.iteritems(local_var_params['kwargs']): - if key not in all_params{{#servers.0}} and key != "_host_index"{{/servers.0}}: - raise ApiTypeError( - "Got an unexpected keyword argument '%s'" - " to method {{operationId}}" % key - ) - local_var_params[key] = val - del local_var_params['kwargs'] + ], +{{#requiredParams}} +{{#-first}} + 'required': [ +{{/-first}} + '{{paramName}}', +{{#-last}} + ], +{{/-last}} +{{/requiredParams}} +{{^requiredParams}} + 'required': [], +{{/requiredParams}} + 'nullable': [ {{#allParams}} -{{^isNullable}} -{{#required}} - # verify the required parameter '{{paramName}}' is set - if self.api_client.client_side_validation and ('{{paramName}}' not in local_var_params or # noqa: E501 - local_var_params['{{paramName}}'] is None): # noqa: E501 - raise ApiValueError("Missing the required parameter `{{paramName}}` when calling `{{operationId}}`") # noqa: E501 -{{/required}} +{{#isNullable}} + '{{paramName}}', {{/isNullable}} {{/allParams}} - + ], + 'enum': [ +{{#allParams}} +{{#isEnum}} + '{{paramName}}', +{{/isEnum}} +{{/allParams}} + ], + 'validation': [ {{#allParams}} {{#hasValidation}} - {{#maxLength}} - if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 - len(local_var_params['{{paramName}}']) > {{maxLength}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 - {{/maxLength}} - {{#minLength}} - if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 - len(local_var_params['{{paramName}}']) < {{minLength}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 - {{/minLength}} - {{#maximum}} - if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}: # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 - {{/maximum}} - {{#minimum}} - if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}: # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 - {{/minimum}} - {{#pattern}} - if self.api_client.client_side_validation and '{{paramName}}' in local_var_params and not re.search(r'{{{vendorExtensions.x-regex}}}', local_var_params['{{paramName}}']{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, must conform to the pattern `{{{pattern}}}`") # noqa: E501 - {{/pattern}} - {{#maxItems}} - if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 - len(local_var_params['{{paramName}}']) > {{maxItems}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 - {{/maxItems}} - {{#minItems}} - if self.api_client.client_side_validation and ('{{paramName}}' in local_var_params and # noqa: E501 - len(local_var_params['{{paramName}}']) < {{minItems}}): # noqa: E501 - raise ApiValueError("Invalid value for parameter `{{paramName}}` when calling `{{operationId}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 - {{/minItems}} + '{{paramName}}', {{/hasValidation}} -{{#-last}} -{{/-last}} {{/allParams}} - collection_formats = {} - - path_params = {} -{{#pathParams}} - if '{{paramName}}' in local_var_params: - path_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isArray}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 -{{/pathParams}} - - query_params = [] -{{#queryParams}} - if '{{paramName}}' in local_var_params and local_var_params['{{paramName}}'] is not None: # noqa: E501 - query_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{#isArray}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 -{{/queryParams}} - - header_params = {} -{{#headerParams}} - if '{{paramName}}' in local_var_params: - header_params['{{baseName}}'] = local_var_params['{{paramName}}']{{#isArray}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 -{{/headerParams}} - - form_params = [] - local_var_files = {} -{{#formParams}} - if '{{paramName}}' in local_var_params: - {{^isFile}}form_params.append(('{{baseName}}', local_var_params['{{paramName}}'])){{/isFile}}{{#isFile}}local_var_files['{{baseName}}'] = local_var_params['{{paramName}}']{{/isFile}}{{#isArray}} # noqa: E501 - collection_formats['{{baseName}}'] = '{{collectionFormat}}'{{/isArray}} # noqa: E501 -{{/formParams}} - - body_params = None -{{#bodyParam}} - if '{{paramName}}' in local_var_params: - body_params = local_var_params['{{paramName}}'] -{{/bodyParam}} - {{#hasProduces}} - # HTTP header `Accept` - header_params['Accept'] = self.api_client.select_header_accept( - [{{#produces}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/produces}}]) # noqa: E501 - - {{/hasProduces}} - {{#hasConsumes}} - # HTTP header `Content-Type` - header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 - [{{#consumes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/consumes}}]) # noqa: E501 - - {{/hasConsumes}} - # Authentication setting - auth_settings = [{{#authMethods}}'{{name}}'{{^-last}}, {{/-last}}{{/authMethods}}] # noqa: E501 - - {{#returnType}} - {{#responses}} - {{#-first}} - response_types_map = { - {{/-first}} - {{^isWildcard}} - {{code}}: {{#dataType}}"{{dataType}}"{{/dataType}}{{^dataType}}None{{/dataType}}, - {{/isWildcard}} - {{#-last}} - } - {{/-last}} - {{/responses}} - {{/returnType}} - {{^returnType}} - response_types_map = {} - {{/returnType}} - - return self.api_client.call_api( - '{{{path}}}', '{{httpMethod}}', - path_params, - query_params, - header_params, - body=body_params, - post_params=form_params, - files=local_var_files, - response_types_map=response_types_map, - auth_settings=auth_settings, - async_req=local_var_params.get('async_req'), - _return_http_data_only=local_var_params.get('_return_http_data_only'), # noqa: E501 - _preload_content=local_var_params.get('_preload_content', True), - _request_timeout=local_var_params.get('_request_timeout'), - {{#servers.0}} - _host=local_var_host, - {{/servers.0}} - collection_formats=collection_formats, - _request_auth=local_var_params.get('_request_auth')) + ] + }, + root_map={ + 'validations': { +{{#allParams}} +{{#hasValidation}} + ('{{paramName}}',): { +{{#maxLength}} + 'max_length': {{maxLength}},{{/maxLength}}{{#minLength}} + 'min_length': {{minLength}},{{/minLength}}{{#maxItems}} + 'max_items': {{maxItems}},{{/maxItems}}{{#minItems}} + 'min_items': {{minItems}},{{/minItems}}{{#maximum}} + {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}} + {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}} + 'regex': { + 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} + {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} + },{{/pattern}} + }, +{{/hasValidation}} +{{/allParams}} + }, + 'allowed_values': { +{{#allParams}} +{{#isEnum}} + ('{{paramName}}',): { +{{#isNullable}} + 'None': None,{{/isNullable}}{{#allowableValues}}{{#enumVars}} + "{{name}}": {{{value}}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} + }, +{{/isEnum}} +{{/allParams}} + }, + 'openapi_types': { +{{#allParams}} + '{{paramName}}': + ({{{dataType}}},), +{{/allParams}} + }, + 'attribute_map': { +{{#allParams}} +{{^isBodyParam}} + '{{paramName}}': '{{baseName}}', +{{/isBodyParam}} +{{/allParams}} + }, + 'location_map': { +{{#allParams}} + '{{paramName}}': '{{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isCookieParam}}cookie{{/isCookieParam}}{{#isBodyParam}}body{{/isBodyParam}}', +{{/allParams}} + }, + 'collection_format_map': { +{{#allParams}} +{{#collectionFormat}} + '{{paramName}}': '{{collectionFormat}}', +{{/collectionFormat}} +{{/allParams}} + } + }, + headers_map={ +{{#hasProduces}} + 'accept': [ +{{#produces}} + '{{{mediaType}}}'{{^-last}},{{/-last}} +{{/produces}} + ], +{{/hasProduces}} +{{^hasProduces}} + 'accept': [], +{{/hasProduces}} +{{#hasConsumes}} + 'content_type': [ +{{#consumes}} + '{{{mediaType}}}'{{^-last}},{{/-last}} +{{/consumes}} + ] +{{/hasConsumes}} +{{^hasConsumes}} + 'content_type': [], +{{/hasConsumes}} + }, + api_client=api_client, + callable=__{{operationId}} + ) {{/operation}} {{/operations}} diff --git a/api_client.mustache b/api_client.mustache index 4f230dff62..fd3d0b8a20 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -1,28 +1,37 @@ # coding: utf-8 {{>partial_header}} -from __future__ import absolute_import -import atexit -import datetime -from dateutil.parser import parse import json +import atexit import mimetypes from multiprocessing.pool import ThreadPool +import io import os import re -import tempfile +import typing +from urllib.parse import quote -# python 2 and python 3 compatibility library -import six -from six.moves.urllib.parse import quote {{#tornado}} import tornado.gen {{/tornado}} -from {{packageName}}.configuration import Configuration -import {{modelPackage}} from {{packageName}} import rest -from {{packageName}}.exceptions import ApiValueError, ApiException +from {{packageName}}.configuration import Configuration +from {{packageName}}.exceptions import ApiTypeError, ApiValueError, ApiException +from {{packageName}}.model_utils import ( + ModelNormal, + ModelSimple, + ModelComposed, + check_allowed_values, + check_validations, + date, + datetime, + deserialize_file, + file_type, + model_to_dict, + none_type, + validate_and_convert_types +) class ApiClient(object): @@ -47,23 +56,12 @@ class ApiClient(object): to the API. More threads means more concurrent API requests. """ - PRIMITIVE_TYPES = (float, bool, bytes, six.text_type) + six.integer_types - NATIVE_TYPES_MAPPING = { - 'int': int, - 'long': int if six.PY3 else long, # noqa: F821 - 'float': float, - 'str': str, - 'bool': bool, - 'date': datetime.date, - 'datetime': datetime.datetime, - 'object': object, - } _pool = None def __init__(self, configuration=None, header_name=None, header_value=None, cookie=None, pool_threads=1): if configuration is None: - configuration = Configuration.get_default_copy() + configuration = Configuration() self.configuration = configuration self.pool_threads = pool_threads @@ -74,27 +72,14 @@ class ApiClient(object): self.cookie = cookie # Set default User-Agent. self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' - self.client_side_validation = configuration.client_side_validation - {{#asyncio}} - async def __aenter__(self): - return self - - async def __aexit__(self, exc_type, exc_value, traceback): - await self.close() - {{/asyncio}} - {{^asyncio}} def __enter__(self): return self def __exit__(self, exc_type, exc_value, traceback): self.close() - {{/asyncio}} - {{#asyncio}}async {{/asyncio}}def close(self): - {{#asyncio}} - await self.rest_client.close() - {{/asyncio}} + def close(self): if self._pool: self._pool.close() self._pool.join() @@ -128,12 +113,24 @@ class ApiClient(object): @tornado.gen.coroutine {{/tornado}} {{#asyncio}}async {{/asyncio}}def __call_api( - self, resource_path, method, path_params=None, - query_params=None, header_params=None, body=None, post_params=None, - files=None, response_types_map=None, auth_settings=None, - _return_http_data_only=None, collection_formats=None, - _preload_content=True, _request_timeout=None, _host=None, - _request_auth=None): + self, + resource_path: str, + method: str, + path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + body: typing.Optional[typing.Any] = None, + post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, + response_type: typing.Optional[typing.Tuple[typing.Any]] = None, + auth_settings: typing.Optional[typing.List[str]] = None, + _return_http_data_only: typing.Optional[bool] = None, + collection_formats: typing.Optional[typing.Dict[str, str]] = None, + _preload_content: bool = True, + _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, + _host: typing.Optional[str] = None, + _check_type: typing.Optional[bool] = None + ): config = self.configuration @@ -173,15 +170,14 @@ class ApiClient(object): collection_formats) post_params.extend(self.files_parameters(files)) - # auth setting - self.update_params_for_auth( - header_params, query_params, auth_settings, - request_auth=_request_auth) - # body if body: body = self.sanitize_for_serialization(body) + # auth setting + self.update_params_for_auth(header_params, query_params, + auth_settings, resource_path, method, body) + # request url if _host is None: url = self.configuration.host + resource_path @@ -197,35 +193,38 @@ class ApiClient(object): _preload_content=_preload_content, _request_timeout=_request_timeout) except ApiException as e: - e.body = e.body.decode('utf-8') if six.PY3 else e.body + e.body = e.body.decode('utf-8') raise e + content_type = response_data.getheader('content-type') + self.last_response = response_data return_data = response_data if not _preload_content: {{^tornado}} - return return_data + return (return_data) {{/tornado}} {{#tornado}} raise tornado.gen.Return(return_data) {{/tornado}} - - response_type = response_types_map.get(response_data.status, None) + return return_data - if six.PY3 and response_type not in ["file", "bytes"]: + if response_type not in ["file", "bytes"]: match = None - content_type = response_data.getheader('content-type') if content_type is not None: match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) encoding = match.group(1) if match else "utf-8" response_data.data = response_data.data.decode(encoding) # deserialize response data - if response_type: - return_data = self.deserialize(response_data, response_type) + return_data = self.deserialize( + response_data, + response_type, + _check_type + ) else: return_data = None @@ -244,9 +243,9 @@ class ApiClient(object): response_data.getheaders())) {{/tornado}} - def sanitize_for_serialization(self, obj): + @classmethod + def sanitize_for_serialization(cls, obj): """Builds a JSON POST object. - If obj is None, return None. If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date @@ -254,106 +253,90 @@ class ApiClient(object): If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. - :param obj: The data to serialize. :return: The serialized form of data. """ - if obj is None: - return None - elif isinstance(obj, self.PRIMITIVE_TYPES): + if isinstance(obj, (ModelNormal, ModelComposed)): + return { + key: cls.sanitize_for_serialization(val) for key, val in model_to_dict(obj, serialize=True).items() + } + elif isinstance(obj, (str, int, float, none_type, bool)): return obj - elif isinstance(obj, list): - return [self.sanitize_for_serialization(sub_obj) - for sub_obj in obj] - elif isinstance(obj, tuple): - return tuple(self.sanitize_for_serialization(sub_obj) - for sub_obj in obj) - elif isinstance(obj, (datetime.datetime, datetime.date)): + elif isinstance(obj, (datetime, date)): return obj.isoformat() - + elif isinstance(obj, ModelSimple): + return cls.sanitize_for_serialization(obj.value) + elif isinstance(obj, (list, tuple)): + return [cls.sanitize_for_serialization(item) for item in obj] if isinstance(obj, dict): - obj_dict = obj - else: - # Convert model obj to dict except - # attributes `openapi_types`, `attribute_map` - # and attributes which value is not None. - # Convert attribute name to json key in - # model definition for request. - obj_dict = {obj.attribute_map[attr]: getattr(obj, attr) - for attr, _ in six.iteritems(obj.openapi_types) - if getattr(obj, attr) is not None} - - return {key: self.sanitize_for_serialization(val) - for key, val in six.iteritems(obj_dict)} - - def deserialize(self, response, response_type): + return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} + raise ApiValueError('Unable to prepare type {} for serialization'.format(obj.__class__.__name__)) + + def deserialize(self, response, response_type, _check_type): """Deserializes response into an object. :param response: RESTResponse object to be deserialized. - :param response_type: class literal for - deserialized object, or string of class name. + :param response_type: For the response, a tuple containing: + valid classes + a list containing valid classes (for list schemas) + a dict containing a tuple of valid classes as the value + Example values: + (str,) + (Pet,) + (float, none_type) + ([int, none_type],) + ({str: (bool, str, int, float, date, datetime, str, none_type)},) + :param _check_type: boolean, whether to check the types of the data + received from the server + :type _check_type: bool :return: deserialized object. """ # handle file downloading # save response body into a tmp file and return the instance - if response_type == "file": - return self.__deserialize_file(response) + if response_type == (file_type,): + content_disposition = response.getheader("Content-Disposition") + return deserialize_file(response.data, self.configuration, + content_disposition=content_disposition) # fetch data from response object try: - data = json.loads(response.data) + received_data = json.loads(response.data) except ValueError: - data = response.data - - return self.__deserialize(data, response_type) - - def __deserialize(self, data, klass): - """Deserializes dict, list, str into an object. - - :param data: dict, list or str. - :param klass: class literal, or string of class name. - - :return: object. - """ - if data is None: - return None - - if type(klass) == str: - if klass.startswith('list['): - sub_kls = re.match(r'list\[(.*)\]', klass).group(1) - return [self.__deserialize(sub_data, sub_kls) - for sub_data in data] - - if klass.startswith('dict('): - sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2) - return {k: self.__deserialize(v, sub_kls) - for k, v in six.iteritems(data)} - - # convert str to class - if klass in self.NATIVE_TYPES_MAPPING: - klass = self.NATIVE_TYPES_MAPPING[klass] - else: - klass = getattr({{modelPackage}}, klass) - - if klass in self.PRIMITIVE_TYPES: - return self.__deserialize_primitive(data, klass) - elif klass == object: - return self.__deserialize_object(data) - elif klass == datetime.date: - return self.__deserialize_date(data) - elif klass == datetime.datetime: - return self.__deserialize_datetime(data) - else: - return self.__deserialize_model(data, klass) - - def call_api(self, resource_path, method, - path_params=None, query_params=None, header_params=None, - body=None, post_params=None, files=None, - response_types_map=None, auth_settings=None, - async_req=None, _return_http_data_only=None, - collection_formats=None,_preload_content=True, - _request_timeout=None, _host=None, _request_auth=None): + received_data = response.data + + # store our data under the key of 'received_data' so users have some + # context if they are deserializing a string and the data type is wrong + deserialized_data = validate_and_convert_types( + received_data, + response_type, + ['received_data'], + True, + _check_type, + configuration=self.configuration + ) + return deserialized_data + + def call_api( + self, + resource_path: str, + method: str, + path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, + body: typing.Optional[typing.Any] = None, + post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, + files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, + response_type: typing.Optional[typing.Tuple[typing.Any]] = None, + auth_settings: typing.Optional[typing.List[str]] = None, + async_req: typing.Optional[bool] = None, + _return_http_data_only: typing.Optional[bool] = None, + collection_formats: typing.Optional[typing.Dict[str, str]] = None, + _preload_content: bool = True, + _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, + _host: typing.Optional[str] = None, + _check_type: typing.Optional[bool] = None + ): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async_req request, set the async_req parameter. @@ -368,25 +351,38 @@ class ApiClient(object): :param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`. :param auth_settings list: Auth Settings names for the request. - :param response: Response data type. - :param files dict: key -> filename, value -> filepath, - for `multipart/form-data`. + :param response_type: For the response, a tuple containing: + valid classes + a list containing valid classes (for list schemas) + a dict containing a tuple of valid classes as the value + Example values: + (str,) + (Pet,) + (float, none_type) + ([int, none_type],) + ({str: (bool, str, int, float, date, datetime, str, none_type)},) + :param files: key -> field name, value -> a list of open file + objects for `multipart/form-data`. + :type files: dict :param async_req bool: execute request asynchronously + :type async_req: bool, optional :param _return_http_data_only: response data without head status code and headers + :type _return_http_data_only: bool, optional :param collection_formats: dict of collection formats for path, query, header, and post parameters. + :type collection_formats: dict, optional :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. + :type _preload_content: bool, optional :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. - :param _request_auth: set to override the auth_settings for an a single - request; this effectively ignores the authentication - in the spec for a single request. - :type _request_token: dict, optional + :param _check_type: boolean describing if the data back from the server + should have its type checked. + :type _check_type: bool, optional :return: If async_req parameter is True, the request will be called asynchronously. @@ -398,23 +394,23 @@ class ApiClient(object): return self.__call_api(resource_path, method, path_params, query_params, header_params, body, post_params, files, - response_types_map, auth_settings, + response_type, auth_settings, _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host, - _request_auth) + _check_type) return self.pool.apply_async(self.__call_api, (resource_path, method, path_params, query_params, header_params, body, post_params, files, - response_types_map, + response_type, auth_settings, _return_http_data_only, collection_formats, _preload_content, _request_timeout, - _host, _request_auth)) + _host, _check_type)) def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, _preload_content=True, @@ -436,8 +432,10 @@ class ApiClient(object): return self.rest_client.OPTIONS(url, query_params=query_params, headers=headers, + post_params=post_params, _preload_content=_preload_content, - _request_timeout=_request_timeout) + _request_timeout=_request_timeout, + body=body) elif method == "POST": return self.rest_client.POST(url, query_params=query_params, @@ -485,7 +483,7 @@ class ApiClient(object): new_params = [] if collection_formats is None: collection_formats = {} - for k, v in six.iteritems(params) if isinstance(params, dict) else params: # noqa: E501 + for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 if k in collection_formats: collection_format = collection_formats[k] if collection_format == 'multi': @@ -505,27 +503,37 @@ class ApiClient(object): new_params.append((k, v)) return new_params - def files_parameters(self, files=None): + def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None): """Builds form parameters. - :param files: File parameters. - :return: Form parameters with files. + :param files: None or a dict with key=param_name and + value is a list of open file objects + :return: List of tuples of form parameters with file data """ - params = [] + if files is None: + return [] - if files: - for k, v in six.iteritems(files): - if not v: + params = [] + for param_name, file_instances in files.items(): + if file_instances is None: + # if the file field is nullable, skip None values + continue + for file_instance in file_instances: + if file_instance is None: + # if the file field is nullable, skip None values continue - file_names = v if type(v) is list else [v] - for n in file_names: - with open(n, 'rb') as f: - filename = os.path.basename(f.name) - filedata = f.read() - mimetype = (mimetypes.guess_type(filename)[0] or - 'application/octet-stream') - params.append( - tuple([k, tuple([filename, filedata, mimetype])])) + if file_instance.closed is True: + raise ApiValueError( + "Cannot read a closed file. The passed in file_type " + "for %s must be open." % param_name + ) + filename = os.path.basename(file_instance.name) + filedata = file_instance.read() + mimetype = (mimetypes.guess_type(filename)[0] or + 'application/octet-stream') + params.append( + tuple([param_name, tuple([filename, filedata, mimetype])])) + file_instance.close() return params @@ -562,156 +570,270 @@ class ApiClient(object): return content_types[0] def update_params_for_auth(self, headers, querys, auth_settings, - request_auth=None): + resource_path, method, body): """Updates header and query params based on authentication setting. :param headers: Header parameters dict to be updated. :param querys: Query parameters tuple list to be updated. :param auth_settings: Authentication setting identifiers list. - :param request_auth: if set, the provided settings will - override the token in the configuration. + :param resource_path: A string representation of the HTTP request resource path. + :param method: A string representation of the HTTP request method. + :param body: A object representing the body of the HTTP request. + The object type is the return value of _encoder.default(). """ if not auth_settings: return - if request_auth: - self._apply_auth_params(headers, querys, request_auth) - return - for auth in auth_settings: auth_setting = self.configuration.auth_settings().get(auth) if auth_setting: - self._apply_auth_params(headers, querys, auth_setting) - - def _apply_auth_params(self, headers, querys, auth_setting): - """Updates the request parameters based on a single auth_setting - - :param headers: Header parameters dict to be updated. - :param querys: Query parameters tuple list to be updated. - :param auth_setting: auth settings for the endpoint - """ - if auth_setting['in'] == 'cookie': - headers['Cookie'] = auth_setting['value'] - elif auth_setting['in'] == 'header': - headers[auth_setting['key']] = auth_setting['value'] - elif auth_setting['in'] == 'query': - querys.append((auth_setting['key'], auth_setting['value'])) - else: - raise ApiValueError( - 'Authentication token must be in `query` or `header`' - ) - - def __deserialize_file(self, response): - """Deserializes body to file - - Saves response body into a file in a temporary folder, - using the filename from the `Content-Disposition` header if provided. - - :param response: RESTResponse. - :return: file path. + if auth_setting['in'] == 'cookie': + headers['Cookie'] = auth_setting['value'] + elif auth_setting['in'] == 'header': + if auth_setting['type'] != 'http-signature': + headers[auth_setting['key']] = auth_setting['value'] +{{#hasHttpSignatureMethods}} + else: + # The HTTP signature scheme requires multiple HTTP headers + # that are calculated dynamically. + signing_info = self.configuration.signing_info + auth_headers = signing_info.get_http_signature_headers( + resource_path, method, headers, body, querys) + headers.update(auth_headers) +{{/hasHttpSignatureMethods}} + elif auth_setting['in'] == 'query': + querys.append((auth_setting['key'], auth_setting['value'])) + else: + raise ApiValueError( + 'Authentication token must be in `query` or `header`' + ) + + +class Endpoint(object): + def __init__(self, settings=None, params_map=None, root_map=None, + headers_map=None, api_client=None, callable=None): + """Creates an endpoint + + Args: + settings (dict): see below key value pairs + 'response_type' (tuple/None): response type + 'auth' (list): a list of auth type keys + 'endpoint_path' (str): the endpoint path + 'operation_id' (str): endpoint string identifier + 'http_method' (str): POST/PUT/PATCH/GET etc + 'servers' (list): list of str servers that this endpoint is at + params_map (dict): see below key value pairs + 'all' (list): list of str endpoint parameter names + 'required' (list): list of required parameter names + 'nullable' (list): list of nullable parameter names + 'enum' (list): list of parameters with enum values + 'validation' (list): list of parameters with validations + root_map + 'validations' (dict): the dict mapping endpoint parameter tuple + paths to their validation dictionaries + 'allowed_values' (dict): the dict mapping endpoint parameter + tuple paths to their allowed_values (enum) dictionaries + 'openapi_types' (dict): param_name to openapi type + 'attribute_map' (dict): param_name to camelCase name + 'location_map' (dict): param_name to 'body', 'file', 'form', + 'header', 'path', 'query' + collection_format_map (dict): param_name to `csv` etc. + headers_map (dict): see below key value pairs + 'accept' (list): list of Accept header strings + 'content_type' (list): list of Content-Type header strings + api_client (ApiClient) api client instance + callable (function): the function which is invoked when the + Endpoint is called """ - fd, path = tempfile.mkstemp(dir=self.configuration.temp_folder_path) - os.close(fd) - os.remove(path) - - content_disposition = response.getheader("Content-Disposition") - if content_disposition: - filename = re.search(r'filename=[\'"]?([^\'"\s]+)[\'"]?', - content_disposition).group(1) - path = os.path.join(os.path.dirname(path), filename) - - with open(path, "wb") as f: - f.write(response.data) - - return path + self.settings = settings + self.params_map = params_map + self.params_map['all'].extend([ + 'async_req', + '_host_index', + '_preload_content', + '_request_timeout', + '_return_http_data_only', + '_check_input_type', + '_check_return_type' + ]) + self.params_map['nullable'].extend(['_request_timeout']) + self.validations = root_map['validations'] + self.allowed_values = root_map['allowed_values'] + self.openapi_types = root_map['openapi_types'] + extra_types = { + 'async_req': (bool,), + '_host_index': (none_type, int), + '_preload_content': (bool,), + '_request_timeout': (none_type, int, (int,), [int]), + '_return_http_data_only': (bool,), + '_check_input_type': (bool,), + '_check_return_type': (bool,) + } + self.openapi_types.update(extra_types) + self.attribute_map = root_map['attribute_map'] + self.location_map = root_map['location_map'] + self.collection_format_map = root_map['collection_format_map'] + self.headers_map = headers_map + self.api_client = api_client + self.callable = callable + + def __validate_inputs(self, kwargs): + for param in self.params_map['enum']: + if param in kwargs: + check_allowed_values( + self.allowed_values, + (param,), + kwargs[param] + ) - def __deserialize_primitive(self, data, klass): - """Deserializes string to primitive type. + for param in self.params_map['validation']: + if param in kwargs: + check_validations( + self.validations, + (param,), + kwargs[param], + configuration=self.api_client.configuration + ) - :param data: str. - :param klass: class literal. + if kwargs['_check_input_type'] is False: + return - :return: int, long, float, str, bool. - """ - try: - return klass(data) - except UnicodeEncodeError: - return six.text_type(data) - except TypeError: - return data + for key, value in kwargs.items(): + fixed_val = validate_and_convert_types( + value, + self.openapi_types[key], + [key], + False, + kwargs['_check_input_type'], + configuration=self.api_client.configuration + ) + kwargs[key] = fixed_val + + def __gather_params(self, kwargs): + params = { + 'body': None, + 'collection_format': {}, + 'file': {}, + 'form': [], + 'header': {}, + 'path': {}, + 'query': [] + } + + for param_name, param_value in kwargs.items(): + param_location = self.location_map.get(param_name) + if param_location is None: + continue + if param_location: + if param_location == 'body': + params['body'] = param_value + continue + base_name = self.attribute_map[param_name] + if (param_location == 'form' and + self.openapi_types[param_name] == (file_type,)): + params['file'][param_name] = [param_value] + elif (param_location == 'form' and + self.openapi_types[param_name] == ([file_type],)): + # param_value is already a list + params['file'][param_name] = param_value + elif param_location in {'form', 'query'}: + param_value_full = (base_name, param_value) + params[param_location].append(param_value_full) + if param_location not in {'form', 'query'}: + params[param_location][base_name] = param_value + collection_format = self.collection_format_map.get(param_name) + if collection_format: + params['collection_format'][base_name] = collection_format - def __deserialize_object(self, value): - """Return an original value. + return params - :return: object. + def __call__(self, *args, **kwargs): + """ This method is invoked when endpoints are called + Example: +{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} + api_instance = {{classname}}() + api_instance.{{operationId}} # this is an instance of the class Endpoint + api_instance.{{operationId}}() # this invokes api_instance.{{operationId}}.__call__() + which then invokes the callable functions stored in that endpoint at + api_instance.{{operationId}}.callable or self.callable in this class +{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} """ - return value + return self.callable(self, *args, **kwargs) - def __deserialize_date(self, string): - """Deserializes string to date. + def call_with_http_info(self, **kwargs): - :param string: str. - :return: date. - """ try: - return parse(string).date() - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason="Failed to parse `{0}` as date object".format(string) + index = self.api_client.configuration.server_operation_index.get( + self.settings['operation_id'], self.api_client.configuration.server_index + ) if kwargs['_host_index'] is None else kwargs['_host_index'] + server_variables = self.api_client.configuration.server_operation_variables.get( + self.settings['operation_id'], self.api_client.configuration.server_variables ) - - def __deserialize_datetime(self, string): - """Deserializes string to datetime. - - The string should be in iso8601 datetime format. - - :param string: str. - :return: datetime. - """ - try: - return parse(string) - except ImportError: - return string - except ValueError: - raise rest.ApiException( - status=0, - reason=( - "Failed to parse `{0}` as datetime object" - .format(string) - ) + _host = self.api_client.configuration.get_host_from_settings( + index, variables=server_variables, servers=self.settings['servers'] ) + except IndexError: + if self.settings['servers']: + raise ApiValueError( + "Invalid host index. Must be 0 <= index < %s" % + len(self.settings['servers']) + ) + _host = None + + for key, value in kwargs.items(): + if key not in self.params_map['all']: + raise ApiTypeError( + "Got an unexpected parameter '%s'" + " to method `%s`" % + (key, self.settings['operation_id']) + ) + # only throw this nullable ApiValueError if _check_input_type + # is False, if _check_input_type==True we catch this case + # in self.__validate_inputs + if (key not in self.params_map['nullable'] and value is None + and kwargs['_check_input_type'] is False): + raise ApiValueError( + "Value may not be None for non-nullable parameter `%s`" + " when calling `%s`" % + (key, self.settings['operation_id']) + ) - def __deserialize_model(self, data, klass): - """Deserializes list or dict to model. + for key in self.params_map['required']: + if key not in kwargs.keys(): + raise ApiValueError( + "Missing the required parameter `%s` when calling " + "`%s`" % (key, self.settings['operation_id']) + ) - :param data: dict, list. - :param klass: class literal. - :return: model object. - """ - has_discriminator = False - if (hasattr(klass, 'get_real_child_model') - and klass.discriminator_value_class_map): - has_discriminator = True - - if not klass.openapi_types and has_discriminator is False: - return data - - kwargs = {} - if (data is not None and - klass.openapi_types is not None and - isinstance(data, (list, dict))): - for attr, attr_type in six.iteritems(klass.openapi_types): - if klass.attribute_map[attr] in data: - value = data[klass.attribute_map[attr]] - kwargs[attr] = self.__deserialize(value, attr_type) - - instance = klass(**kwargs) - - if has_discriminator: - klass_name = instance.get_real_child_model(data) - if klass_name: - instance = self.__deserialize(data, klass_name) - return instance + self.__validate_inputs(kwargs) + + params = self.__gather_params(kwargs) + + accept_headers_list = self.headers_map['accept'] + if accept_headers_list: + params['header']['Accept'] = self.api_client.select_header_accept( + accept_headers_list) + + content_type_headers_list = self.headers_map['content_type'] + if content_type_headers_list: + header_list = self.api_client.select_header_content_type( + content_type_headers_list) + params['header']['Content-Type'] = header_list + + return self.api_client.call_api( + self.settings['endpoint_path'], self.settings['http_method'], + params['path'], + params['query'], + params['header'], + body=params['body'], + post_params=params['form'], + files=params['file'], + response_type=self.settings['response_type'], + auth_settings=self.settings['auth'], + async_req=kwargs['async_req'], + _check_type=kwargs['_check_return_type'], + _return_http_data_only=kwargs['_return_http_data_only'], + _preload_content=kwargs['_preload_content'], + _request_timeout=kwargs['_request_timeout'], + _host=_host, + collection_formats=params['collection_format']) diff --git a/api_doc.mustache b/api_doc.mustache index dddec91719..36eac3ca91 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -11,7 +11,7 @@ Method | HTTP request | Description {{#operations}} {{#operation}} # **{{{operationId}}}** -> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#allParams}}{{#required}}{{{paramName}}}{{/required}}{{^required}}{{{paramName}}}={{{paramName}}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) +> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) {{{summary}}}{{#notes}} @@ -35,18 +35,17 @@ Method | HTTP request | Description {{#isOAuth}} * OAuth Authentication ({{name}}): {{/isOAuth }} -{{> api_doc_example }} {{/authMethods}} {{/hasAuthMethods}} -{{^hasAuthMethods}} {{> api_doc_example }} -{{/hasAuthMethods}} ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes ------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#allParams}} **{{paramName}}** | {{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{baseType}}.md){{/isPrimitiveType}}{{/isFile}}| {{description}} | {{^required}}[optional] {{/required}}{{#defaultValue}}[default to {{defaultValue}}]{{/defaultValue}} -{{/allParams}} +{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | +{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | defaults to {{{.}}} +{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{/optionalParams}} ### Return type diff --git a/api_doc_example.mustache b/api_doc_example.mustache index 526c5950a0..bf989ae430 100644 --- a/api_doc_example.mustache +++ b/api_doc_example.mustache @@ -1,8 +1,10 @@ ```python -from __future__ import print_function import time import {{{packageName}}} -from {{{packageName}}}.rest import ApiException +from {{apiPackage}} import {{classVarName}} +{{#imports}} +{{{.}}} +{{/imports}} from pprint import pprint {{> python_doc_auth_partial}} # Enter a context with an instance of the API client @@ -13,14 +15,62 @@ with {{{packageName}}}.ApiClient(configuration) as api_client: with {{{packageName}}}.ApiClient() as api_client: {{/hasAuthMethods}} # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) - {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} - {{/allParams}} + api_instance = {{classVarName}}.{{{classname}}}(api_client) +{{#requiredParams}} +{{^defaultValue}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} +{{/defaultValue}} +{{/requiredParams}} +{{#optionalParams}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} +{{/optionalParams}} +{{#requiredParams}} +{{#-last}} + # example passing only required values which don't have defaults set try: - {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} - except ApiException as e: +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) +{{#returnType}} + pprint(api_response) +{{/returnType}} + except {{{packageName}}}.ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-last}} +{{/requiredParams}} +{{#optionalParams}} +{{#-last}} + + # example passing only required values which don't have defaults set + # and optional values + try: +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{^-last}}, {{/-last}}{{/optionalParams}}) +{{#returnType}} + pprint(api_response) +{{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/-last}} +{{/optionalParams}} +{{^requiredParams}} +{{^optionalParams}} + + # example, this endpoint has no required or optional parameters + try: +{{#summary}} + # {{{.}}} +{{/summary}} + {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}() +{{#returnType}} + pprint(api_response) +{{/returnType}} + except {{{packageName}}}.ApiException as e: + print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) +{{/optionalParams}} +{{/requiredParams}} ``` diff --git a/api_test.mustache b/api_test.mustache index 90fafc15f3..f9276b443c 100644 --- a/api_test.mustache +++ b/api_test.mustache @@ -2,20 +2,17 @@ {{>partial_header}} -from __future__ import absolute_import - import unittest import {{packageName}} from {{apiPackage}}.{{classVarName}} import {{classname}} # noqa: E501 -from {{packageName}}.rest import ApiException class {{#operations}}Test{{classname}}(unittest.TestCase): """{{classname}} unit test stubs""" def setUp(self): - self.api = {{apiPackage}}.{{classVarName}}.{{classname}}() # noqa: E501 + self.api = {{classname}}() # noqa: E501 def tearDown(self): pass diff --git a/common_README.mustache b/common_README.mustache deleted file mode 100644 index 12fa1322a7..0000000000 --- a/common_README.mustache +++ /dev/null @@ -1,77 +0,0 @@ -```python -from __future__ import print_function -{{#apiInfo}}{{#apis}}{{#-last}}{{#hasHttpSignatureMethods}}import datetime{{/hasHttpSignatureMethods}}{{/-last}}{{/apis}}{{/apiInfo}} -import time -import {{{packageName}}} -from {{{packageName}}}.rest import ApiException -from pprint import pprint -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} -{{> python_doc_auth_partial}} - -# Enter a context with an instance of the API client -with {{{packageName}}}.ApiClient(configuration) as api_client: - # Create an instance of the API class - api_instance = {{{packageName}}}.{{{classname}}}(api_client) - {{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}} - {{/allParams}} - - try: - {{#summary}} # {{{.}}} - {{/summary}} {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#allParams}}{{#required}}{{paramName}}{{/required}}{{^required}}{{paramName}}={{paramName}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}} - pprint(api_response){{/returnType}} - except ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) - {{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} -``` - -## Documentation for API Endpoints - -All URIs are relative to *{{basePath}}* - -Class | Method | HTTP request | Description ------------- | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} - -## Documentation For Models - -{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) -{{/model}}{{/models}} - -## Documentation For Authorization - -{{^authMethods}} - All endpoints do not require authorization. -{{/authMethods}} -{{#authMethods}} -{{#last}} Authentication schemes defined for the API:{{/last}} -## {{{name}}} - -{{#isApiKey}} -- **Type**: API key -- **API key parameter name**: {{{keyParamName}}} -- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}} -{{/isApiKey}} -{{#isBasic}} -{{#isBasicBasic}} -- **Type**: HTTP basic authentication -{{/isBasicBasic}} -{{#isBasicBearer}} -- **Type**: Bearer authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} -{{/isBasicBearer}} -{{/isBasic}} -{{#isOAuth}} -- **Type**: OAuth -- **Flow**: {{{flow}}} -- **Authorization URL**: {{{authorizationUrl}}} -- **Scopes**: {{^scopes}}N/A{{/scopes}} -{{#scopes}} - **{{{scope}}}**: {{{description}}} -{{/scopes}} -{{/isOAuth}} - -{{/authMethods}} - -## Author - -{{#apiInfo}}{{#apis}}{{#-last}}{{infoEmail}} -{{/-last}}{{/apis}}{{/apiInfo}} diff --git a/configuration.mustache b/configuration.mustache index 9f2542f5a9..ca6fc37747 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -2,8 +2,6 @@ {{>partial_header}} -from __future__ import absolute_import - import copy import logging {{^asyncio}} @@ -12,8 +10,7 @@ import multiprocessing import sys import urllib3 -import six -from six.moves import http_client as httplib +from http import client as http_client from {{packageName}}.exceptions import ApiValueError @@ -302,9 +299,8 @@ conf = {{{packageName}}}.Configuration( # Enable client side validation self.client_side_validation = True + # Options to pass down to the underlying urllib3 socket self.socket_options = None - """Options to pass down to the underlying urllib3 socket - """ def __deepcopy__(self, memo): cls = self.__class__ @@ -389,7 +385,7 @@ conf = {{{packageName}}}.Configuration( # then add file handler and remove stream handler. self.logger_file_handler = logging.FileHandler(self.__logger_file) self.logger_file_handler.setFormatter(self.logger_formatter) - for _, logger in six.iteritems(self.logger): + for _, logger in self.logger.items(): logger.addHandler(self.logger_file_handler) @property @@ -411,17 +407,17 @@ conf = {{{packageName}}}.Configuration( self.__debug = value if self.__debug: # if debug status is True, turn on debug logging - for _, logger in six.iteritems(self.logger): + for _, logger in self.logger.items(): logger.setLevel(logging.DEBUG) - # turn on httplib debug - httplib.HTTPConnection.debuglevel = 1 + # turn on http_client debug + http_client.HTTPConnection.debuglevel = 1 else: # if debug status is False, turn off debug logging, # setting log level to default `logging.WARNING` - for _, logger in six.iteritems(self.logger): + for _, logger in self.logger.items(): logger.setLevel(logging.WARNING) - # turn off httplib debug - httplib.HTTPConnection.debuglevel = 0 + # turn off http_client debug + http_client.HTTPConnection.debuglevel = 0 @property def logger_format(self): diff --git a/exceptions.mustache b/exceptions.mustache index 6c77269533..8d445c6e24 100644 --- a/exceptions.mustache +++ b/exceptions.mustache @@ -2,8 +2,6 @@ {{>partial_header}} -import six - class OpenApiException(Exception): """The base exception class for all OpenAPIExceptions""" @@ -120,35 +118,11 @@ class ApiException(OpenApiException): return error_message -class NotFoundException(ApiException): - - def __init__(self, status=None, reason=None, http_resp=None): - super(NotFoundException, self).__init__(status, reason, http_resp) - - -class UnauthorizedException(ApiException): - - def __init__(self, status=None, reason=None, http_resp=None): - super(UnauthorizedException, self).__init__(status, reason, http_resp) - - -class ForbiddenException(ApiException): - - def __init__(self, status=None, reason=None, http_resp=None): - super(ForbiddenException, self).__init__(status, reason, http_resp) - - -class ServiceException(ApiException): - - def __init__(self, status=None, reason=None, http_resp=None): - super(ServiceException, self).__init__(status, reason, http_resp) - - def render_path(path_to_item): """Returns a string representation of a path""" result = "" for pth in path_to_item: - if isinstance(pth, six.integer_types): + if isinstance(pth, int): result += "[{0}]".format(pth) else: result += "['{0}']".format(pth) diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache index 2cabff63c7..60c4b37893 100644 --- a/gitlab-ci.mustache +++ b/gitlab-ci.mustache @@ -3,7 +3,7 @@ stages: - test -.nosetest: +.tests: stage: test script: - pip install -r requirements.txt @@ -15,24 +15,15 @@ stages: - pytest --cov={{{packageName}}} {{/useNose}} -nosetest-2.7: - extends: .nosetest - image: python:2.7-alpine -nosetest-3.3: - extends: .nosetest - image: python:3.3-alpine -nosetest-3.4: - extends: .nosetest - image: python:3.4-alpine -nosetest-3.5: - extends: .nosetest +test-3.5: + extends: .tests image: python:3.5-alpine -nosetest-3.6: - extends: .nosetest +test-3.6: + extends: .tests image: python:3.6-alpine -nosetest-3.7: - extends: .nosetest +test-3.7: + extends: .tests image: python:3.7-alpine -nosetest-3.8: - extends: .nosetest +test-3.8: + extends: .tests image: python:3.8-alpine diff --git a/model.mustache b/model.mustache index 857a3e48fb..f2cb2368ca 100644 --- a/model.mustache +++ b/model.mustache @@ -1,254 +1,59 @@ # coding: utf-8 -{{>partial_header}} +{{> partial_header }} -import inspect -import pprint import re # noqa: F401 -import six - -from {{packageName}}.configuration import Configuration - - +import sys # noqa: F401 + +import nulltype # noqa: F401 + +from {{packageName}}.model_utils import ( # noqa: F401 + ApiTypeError, + ModelComposed, + ModelNormal, + ModelSimple, + cached_property, + change_keys_js_to_python, + convert_js_args_to_python_args, + date, + datetime, + file_type, + none_type, + validate_get_composed_info, +) {{#models}} {{#model}} -class {{classname}}(object): - """NOTE: This class is auto generated by OpenAPI Generator. - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """{{#allowableValues}} - - """ - allowed enum values - """ -{{#enumVars}} - {{name}} = {{{value}}}{{^-last}} -{{/-last}} -{{/enumVars}}{{/allowableValues}} - -{{#allowableValues}} - allowable_values = [{{#enumVars}}{{name}}{{^-last}}, {{/-last}}{{/enumVars}}] # noqa: E501 - -{{/allowableValues}} - """ - Attributes: - openapi_types (dict): The key is attribute name - and the value is attribute type. - attribute_map (dict): The key is attribute name - and the value is json key in definition. - """ - openapi_types = { -{{#vars}} - '{{name}}': '{{{dataType}}}'{{^-last}},{{/-last}} -{{/vars}} - } +{{#imports}} +{{#-first}} - attribute_map = { -{{#vars}} - '{{name}}': '{{baseName}}'{{^-last}},{{/-last}} -{{/vars}} - } -{{#discriminator}} - - discriminator_value_class_map = { -{{#children}} - '{{^vendorExtensions.x-discriminator-value}}{{name}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}': '{{{classname}}}'{{^-last}},{{/-last}} -{{/children}} - } -{{/discriminator}} - - def __init__(self{{#vars}}, {{name}}={{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}None{{/defaultValue}}{{/vars}}, local_vars_configuration=None): # noqa: E501 - """{{classname}} - a model defined in OpenAPI""" # noqa: E501 - if local_vars_configuration is None: - local_vars_configuration = Configuration() - self.local_vars_configuration = local_vars_configuration -{{#vars}}{{#-first}} +def lazy_import(): {{/-first}} - self._{{name}} = None -{{/vars}} - self.discriminator = {{#discriminator}}'{{{discriminatorName}}}'{{/discriminator}}{{^discriminator}}None{{/discriminator}} -{{#vars}}{{#-first}} -{{/-first}} -{{#required}} - self.{{name}} = {{name}} -{{/required}} -{{^required}} -{{#isNullable}} - self.{{name}} = {{name}} -{{/isNullable}} -{{^isNullable}} - if {{name}} is not None: - self.{{name}} = {{name}} -{{/isNullable}} -{{/required}} -{{/vars}} - -{{#vars}} - @property - def {{name}}(self): - """Gets the {{name}} of this {{classname}}. # noqa: E501 + {{{.}}} +{{/imports}} -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - :return: The {{name}} of this {{classname}}. # noqa: E501 - :rtype: {{dataType}} - """ - return self._{{name}} - - @{{name}}.setter - def {{name}}(self, {{name}}): - """Sets the {{name}} of this {{classname}}. - -{{#description}} - {{{description}}} # noqa: E501 -{{/description}} - - :param {{name}}: The {{name}} of this {{classname}}. # noqa: E501 - :type {{name}}: {{dataType}} - """ -{{^isNullable}} -{{#required}} - if self.local_vars_configuration.client_side_validation and {{name}} is None: # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must not be `None`") # noqa: E501 -{{/required}} -{{/isNullable}} -{{#isEnum}} -{{#isContainer}} - allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#items.isString}}"{{/items.isString}}{{{this}}}{{#items.isString}}"{{/items.isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 +{{^interfaces}} {{#isArray}} - if (self.local_vars_configuration.client_side_validation and - not set({{{name}}}).issubset(set(allowed_values))): # noqa: E501 - raise ValueError( - "Invalid values for `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set({{{name}}}) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) +{{> model_templates/model_simple }} {{/isArray}} -{{#isMap}} - if (self.local_vars_configuration.client_side_validation and - not set({{{name}}}.keys()).issubset(set(allowed_values))): # noqa: E501 - raise ValueError( - "Invalid keys in `{{{name}}}` [{0}], must be a subset of [{1}]" # noqa: E501 - .format(", ".join(map(str, set({{{name}}}.keys()) - set(allowed_values))), # noqa: E501 - ", ".join(map(str, allowed_values))) - ) -{{/isMap}} -{{/isContainer}} -{{^isContainer}} - allowed_values = [{{#isNullable}}None,{{/isNullable}}{{#allowableValues}}{{#values}}{{#isString}}"{{/isString}}{{{this}}}{{#isString}}"{{/isString}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}] # noqa: E501 - if self.local_vars_configuration.client_side_validation and {{{name}}} not in allowed_values: # noqa: E501 - raise ValueError( - "Invalid value for `{{{name}}}` ({0}), must be one of {1}" # noqa: E501 - .format({{{name}}}, allowed_values) - ) -{{/isContainer}} +{{#isEnum}} +{{> model_templates/model_simple }} {{/isEnum}} +{{#isAlias}} +{{> model_templates/model_simple }} +{{/isAlias}} +{{^isArray}} {{^isEnum}} -{{#hasValidation}} -{{#maxLength}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and len({{name}}) > {{maxLength}}): - raise ValueError("Invalid value for `{{name}}`, length must be less than or equal to `{{maxLength}}`") # noqa: E501 -{{/maxLength}} -{{#minLength}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and len({{name}}) < {{minLength}}): - raise ValueError("Invalid value for `{{name}}`, length must be greater than or equal to `{{minLength}}`") # noqa: E501 -{{/minLength}} -{{#maximum}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and {{name}} >{{#exclusiveMaximum}}={{/exclusiveMaximum}} {{maximum}}): # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must be a value less than {{^exclusiveMaximum}}or equal to {{/exclusiveMaximum}}`{{maximum}}`") # noqa: E501 -{{/maximum}} -{{#minimum}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and {{name}} <{{#exclusiveMinimum}}={{/exclusiveMinimum}} {{minimum}}): # noqa: E501 - raise ValueError("Invalid value for `{{name}}`, must be a value greater than {{^exclusiveMinimum}}or equal to {{/exclusiveMinimum}}`{{minimum}}`") # noqa: E501 -{{/minimum}} -{{#pattern}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and not re.search(r'{{{vendorExtensions.x-regex}}}', {{name}}{{#vendorExtensions.x-modifiers}}{{#-first}}, flags={{/-first}}re.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}})): # noqa: E501 - raise ValueError(r"Invalid value for `{{name}}`, must be a follow pattern or equal to `{{{pattern}}}`") # noqa: E501 -{{/pattern}} -{{#maxItems}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and len({{name}}) > {{maxItems}}): - raise ValueError("Invalid value for `{{name}}`, number of items must be less than or equal to `{{maxItems}}`") # noqa: E501 -{{/maxItems}} -{{#minItems}} - if (self.local_vars_configuration.client_side_validation and - {{name}} is not None and len({{name}}) < {{minItems}}): - raise ValueError("Invalid value for `{{name}}`, number of items must be greater than or equal to `{{minItems}}`") # noqa: E501 -{{/minItems}} -{{/hasValidation}} +{{^isAlias}} +{{> model_templates/model_normal }} +{{/isAlias}} {{/isEnum}} - - self._{{name}} = {{name}} - -{{/vars}} -{{#discriminator}} - def get_real_child_model(self, data): - """Returns the real base class specified by the discriminator""" - discriminator_key = self.attribute_map[self.discriminator] - discriminator_value = data[discriminator_key] - return self.discriminator_value_class_map.get(discriminator_value) - -{{/discriminator}} - def to_dict(self, serialize=False): - """Returns the model properties as a dict""" - result = {} - - def convert(x): - if hasattr(x, "to_dict"): - args = inspect.getargspec(x.to_dict).args - if len(args) == 1: - return x.to_dict() - else: - return x.to_dict(serialize) - else: - return x - - for attr, _ in six.iteritems(self.openapi_types): - value = getattr(self, attr) - attr = self.attribute_map.get(attr, attr) if serialize else attr - if isinstance(value, list): - result[attr] = list(map( - lambda x: convert(x), - value - )) - elif isinstance(value, dict): - result[attr] = dict(map( - lambda item: (item[0], convert(item[1])), - value.items() - )) - else: - result[attr] = convert(value) - - return result - - def to_str(self): - """Returns the string representation of the model""" - return pprint.pformat(self.to_dict()) - - def __repr__(self): - """For `print` and `pprint`""" - return self.to_str() - - def __eq__(self, other): - """Returns true if both objects are equal""" - if not isinstance(other, {{classname}}): - return False - - return self.to_dict() == other.to_dict() - - def __ne__(self, other): - """Returns true if both objects are not equal""" - if not isinstance(other, {{classname}}): - return True - - return self.to_dict() != other.to_dict() +{{/isArray}} +{{/interfaces}} +{{#interfaces}} +{{#-last}} +{{> model_templates/model_composed }} +{{/-last}} +{{/interfaces}} {{/model}} {{/models}} diff --git a/model_doc.mustache b/model_doc.mustache index fc90a2e0fc..7971d6c85f 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -5,8 +5,31 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -{{#vars}}**{{name}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}} -{{/vars}} +{{#isEnum}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} +{{/isEnum}} +{{#isAlias}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} +{{/isAlias}} +{{#isArray}} +**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}.md){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} +{{/isArray}} +{{#requiredVars}} +{{^defaultValue}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} +{{/defaultValue}} +{{/requiredVars}} +{{#requiredVars}} +{{#defaultValue}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} +{{/defaultValue}} +{{/requiredVars}} +{{#optionalVars}} +**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} +{{/optionalVars}} +{{#additionalPropertiesType}} +**any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional] +{{/additionalPropertiesType}} [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/python-experimental/model_templates/classvars.mustache b/model_templates/classvars.mustache similarity index 94% rename from python-experimental/model_templates/classvars.mustache rename to model_templates/classvars.mustache index f2ea42679a..88ae5df9f1 100644 --- a/python-experimental/model_templates/classvars.mustache +++ b/model_templates/classvars.mustache @@ -44,18 +44,18 @@ validations = { {{#hasValidation}} ('value',): { -{{> python-experimental/model_templates/validations }} +{{> model_templates/validations }} {{/hasValidation}} {{#requiredVars}} {{#hasValidation}} ('{{name}}',): { -{{> python-experimental/model_templates/validations }} +{{> model_templates/validations }} {{/hasValidation}} {{/requiredVars}} {{#optionalVars}} {{#hasValidation}} ('{{name}}',): { -{{> python-experimental/model_templates/validations }} +{{> model_templates/validations }} {{/hasValidation}} {{/optionalVars}} } diff --git a/python-experimental/model_templates/docstring_allowed.mustache b/model_templates/docstring_allowed.mustache similarity index 100% rename from python-experimental/model_templates/docstring_allowed.mustache rename to model_templates/docstring_allowed.mustache diff --git a/python-experimental/model_templates/docstring_init_required_kwargs.mustache b/model_templates/docstring_init_required_kwargs.mustache similarity index 100% rename from python-experimental/model_templates/docstring_init_required_kwargs.mustache rename to model_templates/docstring_init_required_kwargs.mustache diff --git a/python-experimental/model_templates/docstring_openapi_validations.mustache b/model_templates/docstring_openapi_validations.mustache similarity index 100% rename from python-experimental/model_templates/docstring_openapi_validations.mustache rename to model_templates/docstring_openapi_validations.mustache diff --git a/python-experimental/model_templates/method_init_composed.mustache b/model_templates/method_init_composed.mustache similarity index 96% rename from python-experimental/model_templates/method_init_composed.mustache rename to model_templates/method_init_composed.mustache index 7e64549acd..8b3650b33a 100644 --- a/python-experimental/model_templates/method_init_composed.mustache +++ b/model_templates/method_init_composed.mustache @@ -10,7 +10,7 @@ '_additional_properties_model_instances', ]) -{{> python-experimental/model_templates/method_init_shared }} +{{> model_templates/method_init_shared }} constant_args = { '_check_type': _check_type, diff --git a/python-experimental/model_templates/method_init_normal.mustache b/model_templates/method_init_normal.mustache similarity index 92% rename from python-experimental/model_templates/method_init_normal.mustache rename to model_templates/method_init_normal.mustache index 4fee1c8449..e670b4ffb4 100644 --- a/python-experimental/model_templates/method_init_normal.mustache +++ b/model_templates/method_init_normal.mustache @@ -7,7 +7,7 @@ '_visited_composed_classes', ]) -{{> python-experimental/model_templates/method_init_shared }} +{{> model_templates/method_init_shared }} {{#isEnum}} self.value = value diff --git a/python-experimental/model_templates/method_init_shared.mustache b/model_templates/method_init_shared.mustache similarity index 96% rename from python-experimental/model_templates/method_init_shared.mustache rename to model_templates/method_init_shared.mustache index e500b11e70..f3497ef53b 100644 --- a/python-experimental/model_templates/method_init_shared.mustache +++ b/model_templates/method_init_shared.mustache @@ -19,7 +19,7 @@ {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{/defaultValue}} {{/requiredVars}} -{{> python-experimental/model_templates/docstring_init_required_kwargs }} +{{> model_templates/docstring_init_required_kwargs }} {{#optionalVars}} {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 {{/optionalVars}} diff --git a/python-experimental/model_templates/method_init_simple.mustache b/model_templates/method_init_simple.mustache similarity index 97% rename from python-experimental/model_templates/method_init_simple.mustache rename to model_templates/method_init_simple.mustache index b71b80667c..2340cf74ef 100644 --- a/python-experimental/model_templates/method_init_simple.mustache +++ b/model_templates/method_init_simple.mustache @@ -18,7 +18,7 @@ Keyword Args: value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 -{{> python-experimental/model_templates/docstring_init_required_kwargs }} +{{> model_templates/docstring_init_required_kwargs }} """ if 'value' in kwargs: diff --git a/python-experimental/model_templates/method_set_attribute.mustache b/model_templates/method_set_attribute.mustache similarity index 100% rename from python-experimental/model_templates/method_set_attribute.mustache rename to model_templates/method_set_attribute.mustache diff --git a/python-experimental/model_templates/methods_setattr_getattr_composed.mustache b/model_templates/methods_setattr_getattr_composed.mustache similarity index 100% rename from python-experimental/model_templates/methods_setattr_getattr_composed.mustache rename to model_templates/methods_setattr_getattr_composed.mustache diff --git a/python-experimental/model_templates/methods_setattr_getattr_normal.mustache b/model_templates/methods_setattr_getattr_normal.mustache similarity index 100% rename from python-experimental/model_templates/methods_setattr_getattr_normal.mustache rename to model_templates/methods_setattr_getattr_normal.mustache diff --git a/python-experimental/model_templates/methods_shared.mustache b/model_templates/methods_shared.mustache similarity index 100% rename from python-experimental/model_templates/methods_shared.mustache rename to model_templates/methods_shared.mustache diff --git a/python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache b/model_templates/methods_todict_tostr_eq_shared.mustache similarity index 100% rename from python-experimental/model_templates/methods_todict_tostr_eq_shared.mustache rename to model_templates/methods_todict_tostr_eq_shared.mustache diff --git a/python-experimental/model_templates/methods_tostr_eq_simple.mustache b/model_templates/methods_tostr_eq_simple.mustache similarity index 100% rename from python-experimental/model_templates/methods_tostr_eq_simple.mustache rename to model_templates/methods_tostr_eq_simple.mustache diff --git a/python-experimental/model_templates/model_composed.mustache b/model_templates/model_composed.mustache similarity index 85% rename from python-experimental/model_templates/model_composed.mustache rename to model_templates/model_composed.mustache index dd61b23c79..76fe3a8f50 100644 --- a/python-experimental/model_templates/model_composed.mustache +++ b/model_templates/model_composed.mustache @@ -5,15 +5,15 @@ class {{classname}}(ModelComposed): Do not edit the class manually. Attributes: -{{> python-experimental/model_templates/docstring_allowed }} +{{> model_templates/docstring_allowed }} attribute_map (dict): The key is attribute name and the value is json key in definition. discriminator_value_class_map (dict): A dict to go from the discriminator variable value to the discriminator class name. -{{> python-experimental/model_templates/docstring_openapi_validations }} +{{> model_templates/docstring_openapi_validations }} """ -{{> python-experimental/model_templates/classvars }} +{{> model_templates/classvars }} attribute_map = { {{#requiredVars}} @@ -24,7 +24,7 @@ class {{classname}}(ModelComposed): {{/optionalVars}} } -{{> python-experimental/model_templates/method_init_composed }} +{{> model_templates/method_init_composed }} @cached_property def _composed_schemas(): diff --git a/python-experimental/model_templates/model_normal.mustache b/model_templates/model_normal.mustache similarity index 73% rename from python-experimental/model_templates/model_normal.mustache rename to model_templates/model_normal.mustache index af130c66a7..9aada8f5a0 100644 --- a/python-experimental/model_templates/model_normal.mustache +++ b/model_templates/model_normal.mustache @@ -5,15 +5,15 @@ class {{classname}}(ModelNormal): Do not edit the class manually. Attributes: -{{> python-experimental/model_templates/docstring_allowed }} +{{> model_templates/docstring_allowed }} attribute_map (dict): The key is attribute name and the value is json key in definition. discriminator_value_class_map (dict): A dict to go from the discriminator variable value to the discriminator class name. -{{> python-experimental/model_templates/docstring_openapi_validations }} +{{> model_templates/docstring_openapi_validations }} """ -{{> python-experimental/model_templates/classvars }} +{{> model_templates/classvars }} attribute_map = { {{#requiredVars}} @@ -26,4 +26,4 @@ class {{classname}}(ModelNormal): _composed_schemas = {} -{{> python-experimental/model_templates/method_init_normal}} \ No newline at end of file +{{> model_templates/method_init_normal}} \ No newline at end of file diff --git a/python-experimental/model_templates/model_simple.mustache b/model_templates/model_simple.mustache similarity index 50% rename from python-experimental/model_templates/model_simple.mustache rename to model_templates/model_simple.mustache index 0b7d1860dd..a4055af756 100644 --- a/python-experimental/model_templates/model_simple.mustache +++ b/model_templates/model_simple.mustache @@ -5,14 +5,14 @@ class {{classname}}(ModelSimple): Do not edit the class manually. Attributes: -{{> python-experimental/model_templates/docstring_allowed }} -{{> python-experimental/model_templates/docstring_openapi_validations }} +{{> model_templates/docstring_allowed }} +{{> model_templates/docstring_openapi_validations }} """ -{{> python-experimental/model_templates/classvars }} +{{> model_templates/classvars }} attribute_map = {} _composed_schemas = None -{{> python-experimental/model_templates/method_init_simple}} \ No newline at end of file +{{> model_templates/method_init_simple}} \ No newline at end of file diff --git a/python-experimental/model_templates/validations.mustache b/model_templates/validations.mustache similarity index 100% rename from python-experimental/model_templates/validations.mustache rename to model_templates/validations.mustache diff --git a/model_test.mustache b/model_test.mustache index cd55662e10..669cc12185 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -2,16 +2,17 @@ {{>partial_header}} -from __future__ import absolute_import - +import sys import unittest -import datetime +import {{packageName}} {{#models}} {{#model}} -import {{packageName}} -from {{modelPackage}}.{{classFilename}} import {{classname}} # noqa: E501 -from {{packageName}}.rest import ApiException +{{#imports}} +{{{.}}} +{{/imports}} +from {{modelPackage}}.{{classFilename}} import {{classname}} + class Test{{classname}}(unittest.TestCase): """{{classname}} unit test stubs""" @@ -22,31 +23,11 @@ class Test{{classname}}(unittest.TestCase): def tearDown(self): pass - def make_instance(self, include_optional): - """Test {{classname}} - include_option is a boolean, when False only required - params are included, when True both required and - optional params are included """ - # model = {{packageName}}.models.{{classFilename}}.{{classname}}() # noqa: E501 - if include_optional : - return {{classname}}( -{{#vars}} - {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}{{^-last}}, {{/-last}} -{{/vars}} - ) - else : - return {{classname}}( -{{#vars}} -{{#required}} - {{name}} = {{#example}}{{{.}}}{{/example}}{{^example}}None{{/example}}, -{{/required}} -{{/vars}} - ) - def test{{classname}}(self): """Test {{classname}}""" - inst_req_only = self.make_instance(include_optional=False) - inst_req_and_optional = self.make_instance(include_optional=True) + # FIXME: construct object with mandatory attributes with example values + # model = {{classname}}() # noqa: E501 + pass {{/model}} {{/models}} diff --git a/python-experimental/model_utils.mustache b/model_utils.mustache similarity index 99% rename from python-experimental/model_utils.mustache rename to model_utils.mustache index 72a5cbe429..1523dbc2d7 100644 --- a/python-experimental/model_utils.mustache +++ b/model_utils.mustache @@ -96,9 +96,9 @@ def composed_model_input_classes(cls): class OpenApiModel(object): """The base class for all OpenAPIModels""" -{{> python-experimental/model_templates/method_set_attribute }} +{{> model_templates/method_set_attribute }} -{{> python-experimental/model_templates/methods_shared }} +{{> model_templates/methods_shared }} def __new__(cls, *args, **kwargs): # this function uses the discriminator to @@ -218,18 +218,18 @@ class ModelSimple(OpenApiModel): """the parent class of models whose type != object in their swagger/openapi""" -{{> python-experimental/model_templates/methods_setattr_getattr_normal }} +{{> model_templates/methods_setattr_getattr_normal }} -{{> python-experimental/model_templates/methods_tostr_eq_simple }} +{{> model_templates/methods_tostr_eq_simple }} class ModelNormal(OpenApiModel): """the parent class of models whose type == object in their swagger/openapi""" -{{> python-experimental/model_templates/methods_setattr_getattr_normal }} +{{> model_templates/methods_setattr_getattr_normal }} -{{> python-experimental/model_templates/methods_todict_tostr_eq_shared}} +{{> model_templates/methods_todict_tostr_eq_shared}} class ModelComposed(OpenApiModel): @@ -258,9 +258,9 @@ class ModelComposed(OpenApiModel): which contain the value that the key is referring to. """ -{{> python-experimental/model_templates/methods_setattr_getattr_composed }} +{{> model_templates/methods_setattr_getattr_composed }} -{{> python-experimental/model_templates/methods_todict_tostr_eq_shared}} +{{> model_templates/methods_todict_tostr_eq_shared}} COERCION_INDEX_BY_TYPE = { diff --git a/python-experimental/README.mustache b/python-experimental/README.mustache deleted file mode 100644 index 7368913ef8..0000000000 --- a/python-experimental/README.mustache +++ /dev/null @@ -1,55 +0,0 @@ -# {{{projectName}}} -{{#appDescriptionWithNewLines}} -{{{appDescriptionWithNewLines}}} -{{/appDescriptionWithNewLines}} - -This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - -- API version: {{appVersion}} -- Package version: {{packageVersion}} -{{^hideGenerationTimestamp}} -- Build date: {{generatedDate}} -{{/hideGenerationTimestamp}} -- Build package: {{generatorClass}} -{{#infoUrl}} -For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) -{{/infoUrl}} - -## Requirements. - -Python >= 3.5 - -## Installation & Usage -### pip install - -If the python package is hosted on a repository, you can install directly using: - -```sh -pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git -``` -(you may need to run `pip` with root permission: `sudo pip install git+https://{{gitHost}}/{{{gitUserId}}}/{{{gitRepoId}}}.git`) - -Then import the package: -```python -import {{{packageName}}} -``` - -### Setuptools - -Install via [Setuptools](http://pypi.python.org/pypi/setuptools). - -```sh -python setup.py install --user -``` -(or `sudo python setup.py install` to install the package for all users) - -Then import the package: -```python -import {{{packageName}}} -``` - -## Getting Started - -Please follow the [installation procedure](#installation--usage) and then run the following: - -{{> python-experimental/README_common }} diff --git a/python-experimental/README_onlypackage.mustache b/python-experimental/README_onlypackage.mustache deleted file mode 100644 index 3ef048b67a..0000000000 --- a/python-experimental/README_onlypackage.mustache +++ /dev/null @@ -1,43 +0,0 @@ -# {{{projectName}}} -{{#appDescription}} -{{{appDescription}}} -{{/appDescription}} - -The `{{packageName}}` package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: - -- API version: {{appVersion}} -- Package version: {{packageVersion}} -{{^hideGenerationTimestamp}} -- Build date: {{generatedDate}} -{{/hideGenerationTimestamp}} -- Build package: {{generatorClass}} -{{#infoUrl}} -For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) -{{/infoUrl}} - -## Requirements. - -Python >= 3.5 - -## Installation & Usage - -This python library package is generated without supporting files like setup.py or requirements files - -To be able to use it, you will need these dependencies in your own package that uses this library: - -* urllib3 >= 1.15 -* certifi -* python-dateutil -{{#asyncio}} -* aiohttp -{{/asyncio}} -{{#tornado}} -* tornado>=4.2,<5 -{{/tornado}} - -## Getting Started - -In your own code, to use this library to connect and interact with {{{projectName}}}, -you can run the following: - -{{> python-experimental/README_common }} diff --git a/python-experimental/__init__api.mustache b/python-experimental/__init__api.mustache deleted file mode 100644 index 8a9e6b91b9..0000000000 --- a/python-experimental/__init__api.mustache +++ /dev/null @@ -1,9 +0,0 @@ -{{#apiInfo}} -{{#apis}} -{{#-first}} -# do not import all apis into this module because that uses a lot of memory and stack frames -# if you need the ability to import all apis from one package, import them with -# from {{packageName}}.apis import {{classname}} -{{/-first}} -{{/apis}} -{{/apiInfo}} diff --git a/python-experimental/__init__model.mustache b/python-experimental/__init__model.mustache deleted file mode 100644 index cfe32b7849..0000000000 --- a/python-experimental/__init__model.mustache +++ /dev/null @@ -1,5 +0,0 @@ -# we can not import model classes here because that would create a circular -# reference which would not work in python2 -# do not import all models into this module because that uses a lot of memory and stack frames -# if you need the ability to import all models from one package, import them with -# from {{packageName}.models import ModelA, ModelB diff --git a/python-experimental/__init__package.mustache b/python-experimental/__init__package.mustache deleted file mode 100644 index d7ff5b8260..0000000000 --- a/python-experimental/__init__package.mustache +++ /dev/null @@ -1,28 +0,0 @@ -# coding: utf-8 - -# flake8: noqa - -{{>partial_header}} - -__version__ = "{{packageVersion}}" - -# import ApiClient -from {{packageName}}.api_client import ApiClient - -# import Configuration -from {{packageName}}.configuration import Configuration -{{#hasHttpSignatureMethods}} -from {{packageName}}.signing import HttpSigningConfiguration -{{/hasHttpSignatureMethods}} - -# import exceptions -from {{packageName}}.exceptions import OpenApiException -from {{packageName}}.exceptions import ApiAttributeError -from {{packageName}}.exceptions import ApiTypeError -from {{packageName}}.exceptions import ApiValueError -from {{packageName}}.exceptions import ApiKeyError -from {{packageName}}.exceptions import ApiException -{{#recursionLimit}} - -__import__('sys').setrecursionlimit({{{.}}}) -{{/recursionLimit}} diff --git a/python-experimental/api.mustache b/python-experimental/api.mustache deleted file mode 100644 index 0e76b3f29f..0000000000 --- a/python-experimental/api.mustache +++ /dev/null @@ -1,308 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import re # noqa: F401 -import sys # noqa: F401 - -from {{packageName}}.api_client import ApiClient, Endpoint -from {{packageName}}.model_utils import ( # noqa: F401 - check_allowed_values, - check_validations, - date, - datetime, - file_type, - none_type, - validate_and_convert_types -) -{{#imports}} -{{{import}}} -{{/imports}} - - -{{#operations}} -class {{classname}}(object): - """NOTE: This class is auto generated by OpenAPI Generator - Ref: https://openapi-generator.tech - - Do not edit the class manually. - """ - - def __init__(self, api_client=None): - if api_client is None: - api_client = ApiClient() - self.api_client = api_client -{{#operation}} - - def __{{operationId}}( - self, -{{#requiredParams}} -{{^defaultValue}} - {{paramName}}, -{{/defaultValue}} -{{/requiredParams}} -{{#requiredParams}} -{{#defaultValue}} - {{paramName}}={{{defaultValue}}}, -{{/defaultValue}} -{{/requiredParams}} - **kwargs - ): - """{{#summary}}{{{.}}}{{/summary}}{{^summary}}{{operationId}}{{/summary}} # noqa: E501 - -{{#notes}} - {{{notes}}} # noqa: E501 -{{/notes}} - This method makes a synchronous HTTP request by default. To make an - asynchronous HTTP request, please pass async_req=True - - >>> thread = api.{{operationId}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}}{{paramName}}={{{defaultValue}}}, {{/defaultValue}}{{/requiredParams}}async_req=True) - >>> result = thread.get() - -{{#requiredParams}} -{{#-last}} - Args: -{{/-last}} -{{/requiredParams}} -{{#requiredParams}} -{{^defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}} -{{/defaultValue}} -{{/requiredParams}} -{{#requiredParams}} -{{#defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] -{{/defaultValue}} -{{/requiredParams}} - - Keyword Args:{{#optionalParams}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} - _return_http_data_only (bool): response data without head status - code and headers. Default is True. - _preload_content (bool): if False, the urllib3.HTTPResponse object - will be returned without reading/decoding response data. - Default is True. - _request_timeout (float/tuple): timeout setting for this request. If one - number provided, it will be total request timeout. It can also - be a pair (tuple) of (connection, read) timeouts. - Default is None. - _check_input_type (bool): specifies if type checking - should be done one the data sent to the server. - Default is True. - _check_return_type (bool): specifies if type checking - should be done one the data received from the server. - Default is True. - _host_index (int/None): specifies the index of the server - that we want to use. - Default is read from the configuration. - async_req (bool): execute request asynchronously - - Returns: - {{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}None{{/returnType}} - If the method is called asynchronously, returns the request - thread. - """ - kwargs['async_req'] = kwargs.get( - 'async_req', False - ) - kwargs['_return_http_data_only'] = kwargs.get( - '_return_http_data_only', True - ) - kwargs['_preload_content'] = kwargs.get( - '_preload_content', True - ) - kwargs['_request_timeout'] = kwargs.get( - '_request_timeout', None - ) - kwargs['_check_input_type'] = kwargs.get( - '_check_input_type', True - ) - kwargs['_check_return_type'] = kwargs.get( - '_check_return_type', True - ) - kwargs['_host_index'] = kwargs.get('_host_index') -{{#requiredParams}} - kwargs['{{paramName}}'] = \ - {{paramName}} -{{/requiredParams}} - return self.call_with_http_info(**kwargs) - - self.{{operationId}} = Endpoint( - settings={ - 'response_type': {{#returnType}}({{{returnType}}},){{/returnType}}{{^returnType}}None{{/returnType}}, -{{#authMethods}} -{{#-first}} - 'auth': [ -{{/-first}} - '{{name}}'{{^-last}},{{/-last}} -{{#-last}} - ], -{{/-last}} -{{/authMethods}} -{{^authMethods}} - 'auth': [], -{{/authMethods}} - 'endpoint_path': '{{{path}}}', - 'operation_id': '{{operationId}}', - 'http_method': '{{httpMethod}}', -{{#servers}} -{{#-first}} - 'servers': [ -{{/-first}} - { - 'url': "{{{url}}}", - 'description': "{{{description}}}{{^description}}No description provided{{/description}}", - {{#variables}} - {{#-first}} - 'variables': { - {{/-first}} - '{{{name}}}': { - 'description': "{{{description}}}{{^description}}No description provided{{/description}}", - 'default_value': "{{{defaultValue}}}", - {{#enumValues}} - {{#-first}} - 'enum_values': [ - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ] - {{/-last}} - {{/enumValues}} - }{{^-last}},{{/-last}} - {{#-last}} - } - {{/-last}} - {{/variables}} - }, -{{#-last}} - ] -{{/-last}} -{{/servers}} -{{^servers}} - 'servers': None, -{{/servers}} - }, - params_map={ - 'all': [ -{{#allParams}} - '{{paramName}}', -{{/allParams}} - ], -{{#requiredParams}} -{{#-first}} - 'required': [ -{{/-first}} - '{{paramName}}', -{{#-last}} - ], -{{/-last}} -{{/requiredParams}} -{{^requiredParams}} - 'required': [], -{{/requiredParams}} - 'nullable': [ -{{#allParams}} -{{#isNullable}} - '{{paramName}}', -{{/isNullable}} -{{/allParams}} - ], - 'enum': [ -{{#allParams}} -{{#isEnum}} - '{{paramName}}', -{{/isEnum}} -{{/allParams}} - ], - 'validation': [ -{{#allParams}} -{{#hasValidation}} - '{{paramName}}', -{{/hasValidation}} -{{/allParams}} - ] - }, - root_map={ - 'validations': { -{{#allParams}} -{{#hasValidation}} - ('{{paramName}}',): { -{{#maxLength}} - 'max_length': {{maxLength}},{{/maxLength}}{{#minLength}} - 'min_length': {{minLength}},{{/minLength}}{{#maxItems}} - 'max_items': {{maxItems}},{{/maxItems}}{{#minItems}} - 'min_items': {{minItems}},{{/minItems}}{{#maximum}} - {{#exclusiveMaximum}}'exclusive_maximum'{{/exclusiveMaximum}}'inclusive_maximum'{{^exclusiveMaximum}}{{/exclusiveMaximum}}: {{maximum}},{{/maximum}}{{#minimum}} - {{#exclusiveMinimum}}'exclusive_minimum'{{/exclusiveMinimum}}'inclusive_minimum'{{^exclusiveMinimum}}{{/exclusiveMinimum}}: {{minimum}},{{/minimum}}{{#pattern}} - 'regex': { - 'pattern': r'{{{vendorExtensions.x-regex}}}', # noqa: E501{{#vendorExtensions.x-modifiers}} - {{#-first}}'flags': (re.{{.}}{{/-first}}{{^-first}} re.{{.}}{{/-first}}{{^-last}} | {{/-last}}{{#-last}}){{/-last}}{{/vendorExtensions.x-modifiers}} - },{{/pattern}} - }, -{{/hasValidation}} -{{/allParams}} - }, - 'allowed_values': { -{{#allParams}} -{{#isEnum}} - ('{{paramName}}',): { -{{#isNullable}} - 'None': None,{{/isNullable}}{{#allowableValues}}{{#enumVars}} - "{{name}}": {{{value}}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} - }, -{{/isEnum}} -{{/allParams}} - }, - 'openapi_types': { -{{#allParams}} - '{{paramName}}': - ({{{dataType}}},), -{{/allParams}} - }, - 'attribute_map': { -{{#allParams}} -{{^isBodyParam}} - '{{paramName}}': '{{baseName}}', -{{/isBodyParam}} -{{/allParams}} - }, - 'location_map': { -{{#allParams}} - '{{paramName}}': '{{#isFormParam}}form{{/isFormParam}}{{#isQueryParam}}query{{/isQueryParam}}{{#isPathParam}}path{{/isPathParam}}{{#isHeaderParam}}header{{/isHeaderParam}}{{#isCookieParam}}cookie{{/isCookieParam}}{{#isBodyParam}}body{{/isBodyParam}}', -{{/allParams}} - }, - 'collection_format_map': { -{{#allParams}} -{{#collectionFormat}} - '{{paramName}}': '{{collectionFormat}}', -{{/collectionFormat}} -{{/allParams}} - } - }, - headers_map={ -{{#hasProduces}} - 'accept': [ -{{#produces}} - '{{{mediaType}}}'{{^-last}},{{/-last}} -{{/produces}} - ], -{{/hasProduces}} -{{^hasProduces}} - 'accept': [], -{{/hasProduces}} -{{#hasConsumes}} - 'content_type': [ -{{#consumes}} - '{{{mediaType}}}'{{^-last}},{{/-last}} -{{/consumes}} - ] -{{/hasConsumes}} -{{^hasConsumes}} - 'content_type': [], -{{/hasConsumes}} - }, - api_client=api_client, - callable=__{{operationId}} - ) -{{/operation}} -{{/operations}} diff --git a/python-experimental/api_client.mustache b/python-experimental/api_client.mustache deleted file mode 100644 index fd3d0b8a20..0000000000 --- a/python-experimental/api_client.mustache +++ /dev/null @@ -1,839 +0,0 @@ -# coding: utf-8 -{{>partial_header}} - -import json -import atexit -import mimetypes -from multiprocessing.pool import ThreadPool -import io -import os -import re -import typing -from urllib.parse import quote - -{{#tornado}} -import tornado.gen -{{/tornado}} - -from {{packageName}} import rest -from {{packageName}}.configuration import Configuration -from {{packageName}}.exceptions import ApiTypeError, ApiValueError, ApiException -from {{packageName}}.model_utils import ( - ModelNormal, - ModelSimple, - ModelComposed, - check_allowed_values, - check_validations, - date, - datetime, - deserialize_file, - file_type, - model_to_dict, - none_type, - validate_and_convert_types -) - - -class ApiClient(object): - """Generic API client for OpenAPI client library builds. - - OpenAPI generic API client. This client handles the client- - server communication, and is invariant across implementations. Specifics of - the methods and models for each application are generated from the OpenAPI - templates. - - NOTE: This class is auto generated by OpenAPI Generator. - Ref: https://openapi-generator.tech - Do not edit the class manually. - - :param configuration: .Configuration object for this client - :param header_name: a header to pass when making calls to the API. - :param header_value: a header value to pass when making calls to - the API. - :param cookie: a cookie to include in the header when making calls - to the API - :param pool_threads: The number of threads to use for async requests - to the API. More threads means more concurrent API requests. - """ - - _pool = None - - def __init__(self, configuration=None, header_name=None, header_value=None, - cookie=None, pool_threads=1): - if configuration is None: - configuration = Configuration() - self.configuration = configuration - self.pool_threads = pool_threads - - self.rest_client = rest.RESTClientObject(configuration) - self.default_headers = {} - if header_name is not None: - self.default_headers[header_name] = header_value - self.cookie = cookie - # Set default User-Agent. - self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def close(self): - if self._pool: - self._pool.close() - self._pool.join() - self._pool = None - if hasattr(atexit, 'unregister'): - atexit.unregister(self.close) - - @property - def pool(self): - """Create thread pool on first request - avoids instantiating unused threadpool for blocking clients. - """ - if self._pool is None: - atexit.register(self.close) - self._pool = ThreadPool(self.pool_threads) - return self._pool - - @property - def user_agent(self): - """User agent for this API client""" - return self.default_headers['User-Agent'] - - @user_agent.setter - def user_agent(self, value): - self.default_headers['User-Agent'] = value - - def set_default_header(self, header_name, header_value): - self.default_headers[header_name] = header_value - - {{#tornado}} - @tornado.gen.coroutine - {{/tornado}} - {{#asyncio}}async {{/asyncio}}def __call_api( - self, - resource_path: str, - method: str, - path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, - query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, - header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Any] = None, - post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, - files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, - response_type: typing.Optional[typing.Tuple[typing.Any]] = None, - auth_settings: typing.Optional[typing.List[str]] = None, - _return_http_data_only: typing.Optional[bool] = None, - collection_formats: typing.Optional[typing.Dict[str, str]] = None, - _preload_content: bool = True, - _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, - _host: typing.Optional[str] = None, - _check_type: typing.Optional[bool] = None - ): - - config = self.configuration - - # header parameters - header_params = header_params or {} - header_params.update(self.default_headers) - if self.cookie: - header_params['Cookie'] = self.cookie - if header_params: - header_params = self.sanitize_for_serialization(header_params) - header_params = dict(self.parameters_to_tuples(header_params, - collection_formats)) - - # path parameters - if path_params: - path_params = self.sanitize_for_serialization(path_params) - path_params = self.parameters_to_tuples(path_params, - collection_formats) - for k, v in path_params: - # specified safe chars, encode everything - resource_path = resource_path.replace( - '{%s}' % k, - quote(str(v), safe=config.safe_chars_for_path_param) - ) - - # query parameters - if query_params: - query_params = self.sanitize_for_serialization(query_params) - query_params = self.parameters_to_tuples(query_params, - collection_formats) - - # post parameters - if post_params or files: - post_params = post_params if post_params else [] - post_params = self.sanitize_for_serialization(post_params) - post_params = self.parameters_to_tuples(post_params, - collection_formats) - post_params.extend(self.files_parameters(files)) - - # body - if body: - body = self.sanitize_for_serialization(body) - - # auth setting - self.update_params_for_auth(header_params, query_params, - auth_settings, resource_path, method, body) - - # request url - if _host is None: - url = self.configuration.host + resource_path - else: - # use server/host defined in path or operation instead - url = _host + resource_path - - try: - # perform request and return response - response_data = {{#asyncio}}await {{/asyncio}}{{#tornado}}yield {{/tornado}}self.request( - method, url, query_params=query_params, headers=header_params, - post_params=post_params, body=body, - _preload_content=_preload_content, - _request_timeout=_request_timeout) - except ApiException as e: - e.body = e.body.decode('utf-8') - raise e - - content_type = response_data.getheader('content-type') - - self.last_response = response_data - - return_data = response_data - - if not _preload_content: - {{^tornado}} - return (return_data) - {{/tornado}} - {{#tornado}} - raise tornado.gen.Return(return_data) - {{/tornado}} - return return_data - - if response_type not in ["file", "bytes"]: - match = None - if content_type is not None: - match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) - encoding = match.group(1) if match else "utf-8" - response_data.data = response_data.data.decode(encoding) - - # deserialize response data - if response_type: - return_data = self.deserialize( - response_data, - response_type, - _check_type - ) - else: - return_data = None - -{{^tornado}} - if _return_http_data_only: - return (return_data) - else: - return (return_data, response_data.status, - response_data.getheaders()) -{{/tornado}} -{{#tornado}} - if _return_http_data_only: - raise tornado.gen.Return(return_data) - else: - raise tornado.gen.Return((return_data, response_data.status, - response_data.getheaders())) -{{/tornado}} - - @classmethod - def sanitize_for_serialization(cls, obj): - """Builds a JSON POST object. - If obj is None, return None. - If obj is str, int, long, float, bool, return directly. - If obj is datetime.datetime, datetime.date - convert to string in iso8601 format. - If obj is list, sanitize each element in the list. - If obj is dict, return the dict. - If obj is OpenAPI model, return the properties dict. - :param obj: The data to serialize. - :return: The serialized form of data. - """ - if isinstance(obj, (ModelNormal, ModelComposed)): - return { - key: cls.sanitize_for_serialization(val) for key, val in model_to_dict(obj, serialize=True).items() - } - elif isinstance(obj, (str, int, float, none_type, bool)): - return obj - elif isinstance(obj, (datetime, date)): - return obj.isoformat() - elif isinstance(obj, ModelSimple): - return cls.sanitize_for_serialization(obj.value) - elif isinstance(obj, (list, tuple)): - return [cls.sanitize_for_serialization(item) for item in obj] - if isinstance(obj, dict): - return {key: cls.sanitize_for_serialization(val) for key, val in obj.items()} - raise ApiValueError('Unable to prepare type {} for serialization'.format(obj.__class__.__name__)) - - def deserialize(self, response, response_type, _check_type): - """Deserializes response into an object. - - :param response: RESTResponse object to be deserialized. - :param response_type: For the response, a tuple containing: - valid classes - a list containing valid classes (for list schemas) - a dict containing a tuple of valid classes as the value - Example values: - (str,) - (Pet,) - (float, none_type) - ([int, none_type],) - ({str: (bool, str, int, float, date, datetime, str, none_type)},) - :param _check_type: boolean, whether to check the types of the data - received from the server - :type _check_type: bool - - :return: deserialized object. - """ - # handle file downloading - # save response body into a tmp file and return the instance - if response_type == (file_type,): - content_disposition = response.getheader("Content-Disposition") - return deserialize_file(response.data, self.configuration, - content_disposition=content_disposition) - - # fetch data from response object - try: - received_data = json.loads(response.data) - except ValueError: - received_data = response.data - - # store our data under the key of 'received_data' so users have some - # context if they are deserializing a string and the data type is wrong - deserialized_data = validate_and_convert_types( - received_data, - response_type, - ['received_data'], - True, - _check_type, - configuration=self.configuration - ) - return deserialized_data - - def call_api( - self, - resource_path: str, - method: str, - path_params: typing.Optional[typing.Dict[str, typing.Any]] = None, - query_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, - header_params: typing.Optional[typing.Dict[str, typing.Any]] = None, - body: typing.Optional[typing.Any] = None, - post_params: typing.Optional[typing.List[typing.Tuple[str, typing.Any]]] = None, - files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None, - response_type: typing.Optional[typing.Tuple[typing.Any]] = None, - auth_settings: typing.Optional[typing.List[str]] = None, - async_req: typing.Optional[bool] = None, - _return_http_data_only: typing.Optional[bool] = None, - collection_formats: typing.Optional[typing.Dict[str, str]] = None, - _preload_content: bool = True, - _request_timeout: typing.Optional[typing.Union[int, typing.Tuple]] = None, - _host: typing.Optional[str] = None, - _check_type: typing.Optional[bool] = None - ): - """Makes the HTTP request (synchronous) and returns deserialized data. - - To make an async_req request, set the async_req parameter. - - :param resource_path: Path to method endpoint. - :param method: Method to call. - :param path_params: Path parameters in the url. - :param query_params: Query parameters in the url. - :param header_params: Header parameters to be - placed in the request header. - :param body: Request body. - :param post_params dict: Request post form parameters, - for `application/x-www-form-urlencoded`, `multipart/form-data`. - :param auth_settings list: Auth Settings names for the request. - :param response_type: For the response, a tuple containing: - valid classes - a list containing valid classes (for list schemas) - a dict containing a tuple of valid classes as the value - Example values: - (str,) - (Pet,) - (float, none_type) - ([int, none_type],) - ({str: (bool, str, int, float, date, datetime, str, none_type)},) - :param files: key -> field name, value -> a list of open file - objects for `multipart/form-data`. - :type files: dict - :param async_req bool: execute request asynchronously - :type async_req: bool, optional - :param _return_http_data_only: response data without head status code - and headers - :type _return_http_data_only: bool, optional - :param collection_formats: dict of collection formats for path, query, - header, and post parameters. - :type collection_formats: dict, optional - :param _preload_content: if False, the urllib3.HTTPResponse object will - be returned without reading/decoding response - data. Default is True. - :type _preload_content: bool, optional - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - :param _check_type: boolean describing if the data back from the server - should have its type checked. - :type _check_type: bool, optional - :return: - If async_req parameter is True, - the request will be called asynchronously. - The method will return the request thread. - If parameter async_req is False or missing, - then the method will return the response directly. - """ - if not async_req: - return self.__call_api(resource_path, method, - path_params, query_params, header_params, - body, post_params, files, - response_type, auth_settings, - _return_http_data_only, collection_formats, - _preload_content, _request_timeout, _host, - _check_type) - - return self.pool.apply_async(self.__call_api, (resource_path, - method, path_params, - query_params, - header_params, body, - post_params, files, - response_type, - auth_settings, - _return_http_data_only, - collection_formats, - _preload_content, - _request_timeout, - _host, _check_type)) - - def request(self, method, url, query_params=None, headers=None, - post_params=None, body=None, _preload_content=True, - _request_timeout=None): - """Makes the HTTP request using RESTClient.""" - if method == "GET": - return self.rest_client.GET(url, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - headers=headers) - elif method == "HEAD": - return self.rest_client.HEAD(url, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - headers=headers) - elif method == "OPTIONS": - return self.rest_client.OPTIONS(url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - elif method == "POST": - return self.rest_client.POST(url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - elif method == "PUT": - return self.rest_client.PUT(url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - elif method == "PATCH": - return self.rest_client.PATCH(url, - query_params=query_params, - headers=headers, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - elif method == "DELETE": - return self.rest_client.DELETE(url, - query_params=query_params, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - else: - raise ApiValueError( - "http method must be `GET`, `HEAD`, `OPTIONS`," - " `POST`, `PATCH`, `PUT` or `DELETE`." - ) - - def parameters_to_tuples(self, params, collection_formats): - """Get parameters as list of tuples, formatting collections. - - :param params: Parameters as dict or list of two-tuples - :param dict collection_formats: Parameter collection formats - :return: Parameters as list of tuples, collections formatted - """ - new_params = [] - if collection_formats is None: - collection_formats = {} - for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 - if k in collection_formats: - collection_format = collection_formats[k] - if collection_format == 'multi': - new_params.extend((k, value) for value in v) - else: - if collection_format == 'ssv': - delimiter = ' ' - elif collection_format == 'tsv': - delimiter = '\t' - elif collection_format == 'pipes': - delimiter = '|' - else: # csv is the default - delimiter = ',' - new_params.append( - (k, delimiter.join(str(value) for value in v))) - else: - new_params.append((k, v)) - return new_params - - def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None): - """Builds form parameters. - - :param files: None or a dict with key=param_name and - value is a list of open file objects - :return: List of tuples of form parameters with file data - """ - if files is None: - return [] - - params = [] - for param_name, file_instances in files.items(): - if file_instances is None: - # if the file field is nullable, skip None values - continue - for file_instance in file_instances: - if file_instance is None: - # if the file field is nullable, skip None values - continue - if file_instance.closed is True: - raise ApiValueError( - "Cannot read a closed file. The passed in file_type " - "for %s must be open." % param_name - ) - filename = os.path.basename(file_instance.name) - filedata = file_instance.read() - mimetype = (mimetypes.guess_type(filename)[0] or - 'application/octet-stream') - params.append( - tuple([param_name, tuple([filename, filedata, mimetype])])) - file_instance.close() - - return params - - def select_header_accept(self, accepts): - """Returns `Accept` based on an array of accepts provided. - - :param accepts: List of headers. - :return: Accept (e.g. application/json). - """ - if not accepts: - return - - accepts = [x.lower() for x in accepts] - - if 'application/json' in accepts: - return 'application/json' - else: - return ', '.join(accepts) - - def select_header_content_type(self, content_types): - """Returns `Content-Type` based on an array of content_types provided. - - :param content_types: List of content-types. - :return: Content-Type (e.g. application/json). - """ - if not content_types: - return 'application/json' - - content_types = [x.lower() for x in content_types] - - if 'application/json' in content_types or '*/*' in content_types: - return 'application/json' - else: - return content_types[0] - - def update_params_for_auth(self, headers, querys, auth_settings, - resource_path, method, body): - """Updates header and query params based on authentication setting. - - :param headers: Header parameters dict to be updated. - :param querys: Query parameters tuple list to be updated. - :param auth_settings: Authentication setting identifiers list. - :param resource_path: A string representation of the HTTP request resource path. - :param method: A string representation of the HTTP request method. - :param body: A object representing the body of the HTTP request. - The object type is the return value of _encoder.default(). - """ - if not auth_settings: - return - - for auth in auth_settings: - auth_setting = self.configuration.auth_settings().get(auth) - if auth_setting: - if auth_setting['in'] == 'cookie': - headers['Cookie'] = auth_setting['value'] - elif auth_setting['in'] == 'header': - if auth_setting['type'] != 'http-signature': - headers[auth_setting['key']] = auth_setting['value'] -{{#hasHttpSignatureMethods}} - else: - # The HTTP signature scheme requires multiple HTTP headers - # that are calculated dynamically. - signing_info = self.configuration.signing_info - auth_headers = signing_info.get_http_signature_headers( - resource_path, method, headers, body, querys) - headers.update(auth_headers) -{{/hasHttpSignatureMethods}} - elif auth_setting['in'] == 'query': - querys.append((auth_setting['key'], auth_setting['value'])) - else: - raise ApiValueError( - 'Authentication token must be in `query` or `header`' - ) - - -class Endpoint(object): - def __init__(self, settings=None, params_map=None, root_map=None, - headers_map=None, api_client=None, callable=None): - """Creates an endpoint - - Args: - settings (dict): see below key value pairs - 'response_type' (tuple/None): response type - 'auth' (list): a list of auth type keys - 'endpoint_path' (str): the endpoint path - 'operation_id' (str): endpoint string identifier - 'http_method' (str): POST/PUT/PATCH/GET etc - 'servers' (list): list of str servers that this endpoint is at - params_map (dict): see below key value pairs - 'all' (list): list of str endpoint parameter names - 'required' (list): list of required parameter names - 'nullable' (list): list of nullable parameter names - 'enum' (list): list of parameters with enum values - 'validation' (list): list of parameters with validations - root_map - 'validations' (dict): the dict mapping endpoint parameter tuple - paths to their validation dictionaries - 'allowed_values' (dict): the dict mapping endpoint parameter - tuple paths to their allowed_values (enum) dictionaries - 'openapi_types' (dict): param_name to openapi type - 'attribute_map' (dict): param_name to camelCase name - 'location_map' (dict): param_name to 'body', 'file', 'form', - 'header', 'path', 'query' - collection_format_map (dict): param_name to `csv` etc. - headers_map (dict): see below key value pairs - 'accept' (list): list of Accept header strings - 'content_type' (list): list of Content-Type header strings - api_client (ApiClient) api client instance - callable (function): the function which is invoked when the - Endpoint is called - """ - self.settings = settings - self.params_map = params_map - self.params_map['all'].extend([ - 'async_req', - '_host_index', - '_preload_content', - '_request_timeout', - '_return_http_data_only', - '_check_input_type', - '_check_return_type' - ]) - self.params_map['nullable'].extend(['_request_timeout']) - self.validations = root_map['validations'] - self.allowed_values = root_map['allowed_values'] - self.openapi_types = root_map['openapi_types'] - extra_types = { - 'async_req': (bool,), - '_host_index': (none_type, int), - '_preload_content': (bool,), - '_request_timeout': (none_type, int, (int,), [int]), - '_return_http_data_only': (bool,), - '_check_input_type': (bool,), - '_check_return_type': (bool,) - } - self.openapi_types.update(extra_types) - self.attribute_map = root_map['attribute_map'] - self.location_map = root_map['location_map'] - self.collection_format_map = root_map['collection_format_map'] - self.headers_map = headers_map - self.api_client = api_client - self.callable = callable - - def __validate_inputs(self, kwargs): - for param in self.params_map['enum']: - if param in kwargs: - check_allowed_values( - self.allowed_values, - (param,), - kwargs[param] - ) - - for param in self.params_map['validation']: - if param in kwargs: - check_validations( - self.validations, - (param,), - kwargs[param], - configuration=self.api_client.configuration - ) - - if kwargs['_check_input_type'] is False: - return - - for key, value in kwargs.items(): - fixed_val = validate_and_convert_types( - value, - self.openapi_types[key], - [key], - False, - kwargs['_check_input_type'], - configuration=self.api_client.configuration - ) - kwargs[key] = fixed_val - - def __gather_params(self, kwargs): - params = { - 'body': None, - 'collection_format': {}, - 'file': {}, - 'form': [], - 'header': {}, - 'path': {}, - 'query': [] - } - - for param_name, param_value in kwargs.items(): - param_location = self.location_map.get(param_name) - if param_location is None: - continue - if param_location: - if param_location == 'body': - params['body'] = param_value - continue - base_name = self.attribute_map[param_name] - if (param_location == 'form' and - self.openapi_types[param_name] == (file_type,)): - params['file'][param_name] = [param_value] - elif (param_location == 'form' and - self.openapi_types[param_name] == ([file_type],)): - # param_value is already a list - params['file'][param_name] = param_value - elif param_location in {'form', 'query'}: - param_value_full = (base_name, param_value) - params[param_location].append(param_value_full) - if param_location not in {'form', 'query'}: - params[param_location][base_name] = param_value - collection_format = self.collection_format_map.get(param_name) - if collection_format: - params['collection_format'][base_name] = collection_format - - return params - - def __call__(self, *args, **kwargs): - """ This method is invoked when endpoints are called - Example: -{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}} - api_instance = {{classname}}() - api_instance.{{operationId}} # this is an instance of the class Endpoint - api_instance.{{operationId}}() # this invokes api_instance.{{operationId}}.__call__() - which then invokes the callable functions stored in that endpoint at - api_instance.{{operationId}}.callable or self.callable in this class -{{/-first}}{{/operation}}{{/operations}}{{/-first}}{{/apis}}{{/apiInfo}} - """ - return self.callable(self, *args, **kwargs) - - def call_with_http_info(self, **kwargs): - - try: - index = self.api_client.configuration.server_operation_index.get( - self.settings['operation_id'], self.api_client.configuration.server_index - ) if kwargs['_host_index'] is None else kwargs['_host_index'] - server_variables = self.api_client.configuration.server_operation_variables.get( - self.settings['operation_id'], self.api_client.configuration.server_variables - ) - _host = self.api_client.configuration.get_host_from_settings( - index, variables=server_variables, servers=self.settings['servers'] - ) - except IndexError: - if self.settings['servers']: - raise ApiValueError( - "Invalid host index. Must be 0 <= index < %s" % - len(self.settings['servers']) - ) - _host = None - - for key, value in kwargs.items(): - if key not in self.params_map['all']: - raise ApiTypeError( - "Got an unexpected parameter '%s'" - " to method `%s`" % - (key, self.settings['operation_id']) - ) - # only throw this nullable ApiValueError if _check_input_type - # is False, if _check_input_type==True we catch this case - # in self.__validate_inputs - if (key not in self.params_map['nullable'] and value is None - and kwargs['_check_input_type'] is False): - raise ApiValueError( - "Value may not be None for non-nullable parameter `%s`" - " when calling `%s`" % - (key, self.settings['operation_id']) - ) - - for key in self.params_map['required']: - if key not in kwargs.keys(): - raise ApiValueError( - "Missing the required parameter `%s` when calling " - "`%s`" % (key, self.settings['operation_id']) - ) - - self.__validate_inputs(kwargs) - - params = self.__gather_params(kwargs) - - accept_headers_list = self.headers_map['accept'] - if accept_headers_list: - params['header']['Accept'] = self.api_client.select_header_accept( - accept_headers_list) - - content_type_headers_list = self.headers_map['content_type'] - if content_type_headers_list: - header_list = self.api_client.select_header_content_type( - content_type_headers_list) - params['header']['Content-Type'] = header_list - - return self.api_client.call_api( - self.settings['endpoint_path'], self.settings['http_method'], - params['path'], - params['query'], - params['header'], - body=params['body'], - post_params=params['form'], - files=params['file'], - response_type=self.settings['response_type'], - auth_settings=self.settings['auth'], - async_req=kwargs['async_req'], - _check_type=kwargs['_check_return_type'], - _return_http_data_only=kwargs['_return_http_data_only'], - _preload_content=kwargs['_preload_content'], - _request_timeout=kwargs['_request_timeout'], - _host=_host, - collection_formats=params['collection_format']) diff --git a/python-experimental/api_doc.mustache b/python-experimental/api_doc.mustache deleted file mode 100644 index f9dac707f7..0000000000 --- a/python-experimental/api_doc.mustache +++ /dev/null @@ -1,75 +0,0 @@ -# {{packageName}}.{{classname}}{{#description}} -{{description}}{{/description}} - -All URIs are relative to *{{basePath}}* - -Method | HTTP request | Description -------------- | ------------- | ------------- -{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} -{{/operation}}{{/operations}} - -{{#operations}} -{{#operation}} -# **{{{operationId}}}** -> {{#returnType}}{{{returnType}}} {{/returnType}}{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) - -{{{summary}}}{{#notes}} - -{{{notes}}}{{/notes}} - -### Example - -{{#hasAuthMethods}} -{{#authMethods}} -{{#isBasic}} -{{#isBasicBasic}} -* Basic Authentication ({{name}}): -{{/isBasicBasic}} -{{#isBasicBearer}} -* Bearer{{#bearerFormat}} ({{{.}}}){{/bearerFormat}} Authentication ({{name}}): -{{/isBasicBearer}} -{{/isBasic}} -{{#isApiKey}} -* Api Key Authentication ({{name}}): -{{/isApiKey }} -{{#isOAuth}} -* OAuth Authentication ({{name}}): -{{/isOAuth }} -{{/authMethods}} -{{/hasAuthMethods}} -{{> python-experimental/api_doc_example }} -### Parameters -{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} -Name | Type | Description | Notes -------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}} -{{#requiredParams}}{{^defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | -{{/defaultValue}}{{/requiredParams}}{{#requiredParams}}{{#defaultValue}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | defaults to {{{.}}} -{{/defaultValue}}{{/requiredParams}}{{#optionalParams}} **{{paramName}}** | {{^baseType}}**{{dataType}}**{{/baseType}}{{#baseType}}[**{{dataType}}**]({{baseType}}.md){{/baseType}}| {{description}} | [optional]{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} -{{/optionalParams}} - -### Return type - -{{#returnType}}{{#returnTypeIsPrimitive}}**{{{returnType}}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}[**{{{returnType}}}**]({{returnBaseType}}.md){{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}void (empty response body){{/returnType}} - -### Authorization - -{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} - -### HTTP request headers - - - **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}} - - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} - -{{#responses.0}} -### HTTP response details -| Status code | Description | Response headers | -|-------------|-------------|------------------| -{{#responses}} -**{{code}}** | {{message}} | {{#headers}} * {{baseName}} - {{description}}
{{/headers}}{{^headers.0}} - {{/headers.0}} | -{{/responses}} -{{/responses.0}} - -[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) - -{{/operation}} -{{/operations}} diff --git a/python-experimental/api_doc_example.mustache b/python-experimental/api_doc_example.mustache deleted file mode 100644 index bf989ae430..0000000000 --- a/python-experimental/api_doc_example.mustache +++ /dev/null @@ -1,76 +0,0 @@ -```python -import time -import {{{packageName}}} -from {{apiPackage}} import {{classVarName}} -{{#imports}} -{{{.}}} -{{/imports}} -from pprint import pprint -{{> python_doc_auth_partial}} -# Enter a context with an instance of the API client -{{#hasAuthMethods}} -with {{{packageName}}}.ApiClient(configuration) as api_client: -{{/hasAuthMethods}} -{{^hasAuthMethods}} -with {{{packageName}}}.ApiClient() as api_client: -{{/hasAuthMethods}} - # Create an instance of the API class - api_instance = {{classVarName}}.{{{classname}}}(api_client) -{{#requiredParams}} -{{^defaultValue}} - {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} -{{/defaultValue}} -{{/requiredParams}} -{{#optionalParams}} - {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} -{{/optionalParams}} -{{#requiredParams}} -{{#-last}} - - # example passing only required values which don't have defaults set - try: -{{#summary}} - # {{{.}}} -{{/summary}} - {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}{{^-last}}, {{/-last}}{{/defaultValue}}{{/requiredParams}}) -{{#returnType}} - pprint(api_response) -{{/returnType}} - except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/-last}} -{{/requiredParams}} -{{#optionalParams}} -{{#-last}} - - # example passing only required values which don't have defaults set - # and optional values - try: -{{#summary}} - # {{{.}}} -{{/summary}} - {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}({{#requiredParams}}{{^defaultValue}}{{paramName}}, {{/defaultValue}}{{/requiredParams}}{{#optionalParams}}{{paramName}}={{paramName}}{{^-last}}, {{/-last}}{{/optionalParams}}) -{{#returnType}} - pprint(api_response) -{{/returnType}} - except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/-last}} -{{/optionalParams}} -{{^requiredParams}} -{{^optionalParams}} - - # example, this endpoint has no required or optional parameters - try: -{{#summary}} - # {{{.}}} -{{/summary}} - {{#returnType}}api_response = {{/returnType}}api_instance.{{{operationId}}}() -{{#returnType}} - pprint(api_response) -{{/returnType}} - except {{{packageName}}}.ApiException as e: - print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) -{{/optionalParams}} -{{/requiredParams}} -``` diff --git a/python-experimental/api_test.mustache b/python-experimental/api_test.mustache deleted file mode 100644 index f9276b443c..0000000000 --- a/python-experimental/api_test.mustache +++ /dev/null @@ -1,34 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import unittest - -import {{packageName}} -from {{apiPackage}}.{{classVarName}} import {{classname}} # noqa: E501 - - -class {{#operations}}Test{{classname}}(unittest.TestCase): - """{{classname}} unit test stubs""" - - def setUp(self): - self.api = {{classname}}() # noqa: E501 - - def tearDown(self): - pass - - {{#operation}} - def test_{{operationId}}(self): - """Test case for {{{operationId}}} - -{{#summary}} - {{{summary}}} # noqa: E501 -{{/summary}} - """ - pass - - {{/operation}} -{{/operations}} - -if __name__ == '__main__': - unittest.main() diff --git a/python-experimental/configuration.mustache b/python-experimental/configuration.mustache deleted file mode 100644 index ca6fc37747..0000000000 --- a/python-experimental/configuration.mustache +++ /dev/null @@ -1,635 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import copy -import logging -{{^asyncio}} -import multiprocessing -{{/asyncio}} -import sys -import urllib3 - -from http import client as http_client -from {{packageName}}.exceptions import ApiValueError - - -JSON_SCHEMA_VALIDATION_KEYWORDS = { - 'multipleOf', 'maximum', 'exclusiveMaximum', - 'minimum', 'exclusiveMinimum', 'maxLength', - 'minLength', 'pattern', 'maxItems', 'minItems' -} - -class Configuration(object): - """NOTE: This class is auto generated by OpenAPI Generator - - Ref: https://openapi-generator.tech - Do not edit the class manually. - - :param host: Base url - :param api_key: Dict to store API key(s). - Each entry in the dict specifies an API key. - The dict key is the name of the security scheme in the OAS specification. - The dict value is the API key secret. - :param api_key_prefix: Dict to store API prefix (e.g. Bearer) - The dict key is the name of the security scheme in the OAS specification. - The dict value is an API key prefix when generating the auth data. - :param username: Username for HTTP basic authentication - :param password: Password for HTTP basic authentication - :param discard_unknown_keys: Boolean value indicating whether to discard - unknown properties. A server may send a response that includes additional - properties that are not known by the client in the following scenarios: - 1. The OpenAPI document is incomplete, i.e. it does not match the server - implementation. - 2. The client was generated using an older version of the OpenAPI document - and the server has been upgraded since then. - If a schema in the OpenAPI document defines the additionalProperties attribute, - then all undeclared properties received by the server are injected into the - additional properties map. In that case, there are undeclared properties, and - nothing to discard. - :param disabled_client_side_validations (string): Comma-separated list of - JSON schema validation keywords to disable JSON schema structural validation - rules. The following keywords may be specified: multipleOf, maximum, - exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength, pattern, - maxItems, minItems. - By default, the validation is performed for data generated locally by the client - and data received from the server, independent of any validation performed by - the server side. If the input data does not satisfy the JSON schema validation - rules specified in the OpenAPI document, an exception is raised. - If disabled_client_side_validations is set, structural validation is - disabled. This can be useful to troubleshoot data validation problem, such as - when the OpenAPI document validation rules do not match the actual API data - received by the server. -{{#hasHttpSignatureMethods}} - :param signing_info: Configuration parameters for the HTTP signature security scheme. - Must be an instance of {{{packageName}}}.signing.HttpSigningConfiguration -{{/hasHttpSignatureMethods}} - :param server_index: Index to servers configuration. - :param server_variables: Mapping with string values to replace variables in - templated server configuration. The validation of enums is performed for - variables with defined enum values before. - :param server_operation_index: Mapping from operation ID to an index to server - configuration. - :param server_operation_variables: Mapping from operation ID to a mapping with - string values to replace variables in templated server configuration. - The validation of enums is performed for variables with defined enum values before. - -{{#hasAuthMethods}} - :Example: -{{#hasApiKeyMethods}} - - API Key Authentication Example. - Given the following security scheme in the OpenAPI specification: - components: - securitySchemes: - cookieAuth: # name for the security scheme - type: apiKey - in: cookie - name: JSESSIONID # cookie name - - You can programmatically set the cookie: - -conf = {{{packageName}}}.Configuration( - api_key={'cookieAuth': 'abc123'} - api_key_prefix={'cookieAuth': 'JSESSIONID'} -) - - The following cookie will be added to the HTTP request: - Cookie: JSESSIONID abc123 -{{/hasApiKeyMethods}} -{{#hasHttpBasicMethods}} - - HTTP Basic Authentication Example. - Given the following security scheme in the OpenAPI specification: - components: - securitySchemes: - http_basic_auth: - type: http - scheme: basic - - Configure API client with HTTP basic authentication: - -conf = {{{packageName}}}.Configuration( - username='the-user', - password='the-password', -) - -{{/hasHttpBasicMethods}} -{{#hasHttpSignatureMethods}} - - HTTP Signature Authentication Example. - Given the following security scheme in the OpenAPI specification: - components: - securitySchemes: - http_basic_auth: - type: http - scheme: signature - - Configure API client with HTTP signature authentication. Use the 'hs2019' signature scheme, - sign the HTTP requests with the RSA-SSA-PSS signature algorithm, and set the expiration time - of the signature to 5 minutes after the signature has been created. - Note you can use the constants defined in the {{{packageName}}}.signing module, and you can - also specify arbitrary HTTP headers to be included in the HTTP signature, except for the - 'Authorization' header, which is used to carry the signature. - - One may be tempted to sign all headers by default, but in practice it rarely works. - This is beccause explicit proxies, transparent proxies, TLS termination endpoints or - load balancers may add/modify/remove headers. Include the HTTP headers that you know - are not going to be modified in transit. - -conf = {{{packageName}}}.Configuration( - signing_info = {{{packageName}}}.signing.HttpSigningConfiguration( - key_id = 'my-key-id', - private_key_path = 'rsa.pem', - signing_scheme = {{{packageName}}}.signing.SCHEME_HS2019, - signing_algorithm = {{{packageName}}}.signing.ALGORITHM_RSASSA_PSS, - signed_headers = [{{{packageName}}}.signing.HEADER_REQUEST_TARGET, - {{{packageName}}}.signing.HEADER_CREATED, - {{{packageName}}}.signing.HEADER_EXPIRES, - {{{packageName}}}.signing.HEADER_HOST, - {{{packageName}}}.signing.HEADER_DATE, - {{{packageName}}}.signing.HEADER_DIGEST, - 'Content-Type', - 'User-Agent' - ], - signature_max_validity = datetime.timedelta(minutes=5) - ) -) -{{/hasHttpSignatureMethods}} -{{/hasAuthMethods}} - """ - - _default = None - - def __init__(self, host=None, - api_key=None, api_key_prefix=None, - username=None, password=None, - discard_unknown_keys=False, - disabled_client_side_validations="", -{{#hasHttpSignatureMethods}} - signing_info=None, -{{/hasHttpSignatureMethods}} - server_index=None, server_variables=None, - server_operation_index=None, server_operation_variables=None, - ): - """Constructor - """ - self._base_path = "{{{basePath}}}" if host is None else host - """Default Base url - """ - self.server_index = 0 if server_index is None and host is None else server_index - self.server_operation_index = server_operation_index or {} - """Default server index - """ - self.server_variables = server_variables or {} - self.server_operation_variables = server_operation_variables or {} - """Default server variables - """ - self.temp_folder_path = None - """Temp file folder for downloading files - """ - # Authentication Settings - self.api_key = {} - if api_key: - self.api_key = api_key - """dict to store API key(s) - """ - self.api_key_prefix = {} - if api_key_prefix: - self.api_key_prefix = api_key_prefix - """dict to store API prefix (e.g. Bearer) - """ - self.refresh_api_key_hook = None - """function hook to refresh API key if expired - """ - self.username = username - """Username for HTTP basic authentication - """ - self.password = password - """Password for HTTP basic authentication - """ - self.discard_unknown_keys = discard_unknown_keys - self.disabled_client_side_validations = disabled_client_side_validations -{{#hasHttpSignatureMethods}} - if signing_info is not None: - signing_info.host = host - self.signing_info = signing_info - """The HTTP signing configuration - """ -{{/hasHttpSignatureMethods}} -{{#hasOAuthMethods}} - self.access_token = None - """access token for OAuth/Bearer - """ -{{/hasOAuthMethods}} -{{^hasOAuthMethods}} -{{#hasBearerMethods}} - self.access_token = None - """access token for OAuth/Bearer - """ -{{/hasBearerMethods}} -{{/hasOAuthMethods}} - self.logger = {} - """Logging Settings - """ - self.logger["package_logger"] = logging.getLogger("{{packageName}}") - self.logger["urllib3_logger"] = logging.getLogger("urllib3") - self.logger_format = '%(asctime)s %(levelname)s %(message)s' - """Log format - """ - self.logger_stream_handler = None - """Log stream handler - """ - self.logger_file_handler = None - """Log file handler - """ - self.logger_file = None - """Debug file location - """ - self.debug = False - """Debug switch - """ - - self.verify_ssl = True - """SSL/TLS verification - Set this to false to skip verifying SSL certificate when calling API - from https server. - """ - self.ssl_ca_cert = None - """Set this to customize the certificate file to verify the peer. - """ - self.cert_file = None - """client certificate file - """ - self.key_file = None - """client key file - """ - self.assert_hostname = None - """Set this to True/False to enable/disable SSL hostname verification. - """ - - {{#asyncio}} - self.connection_pool_maxsize = 100 - """This value is passed to the aiohttp to limit simultaneous connections. - Default values is 100, None means no-limit. - """ - {{/asyncio}} - {{^asyncio}} - self.connection_pool_maxsize = multiprocessing.cpu_count() * 5 - """urllib3 connection pool's maximum number of connections saved - per pool. urllib3 uses 1 connection as default value, but this is - not the best value when you are making a lot of possibly parallel - requests to the same host, which is often the case here. - cpu_count * 5 is used as default value to increase performance. - """ - {{/asyncio}} - - self.proxy = None - """Proxy URL - """ - self.proxy_headers = None - """Proxy headers - """ - self.safe_chars_for_path_param = '' - """Safe chars for path_param - """ - self.retries = None - """Adding retries to override urllib3 default value 3 - """ - # Enable client side validation - self.client_side_validation = True - - # Options to pass down to the underlying urllib3 socket - self.socket_options = None - - def __deepcopy__(self, memo): - cls = self.__class__ - result = cls.__new__(cls) - memo[id(self)] = result - for k, v in self.__dict__.items(): - if k not in ('logger', 'logger_file_handler'): - setattr(result, k, copy.deepcopy(v, memo)) - # shallow copy of loggers - result.logger = copy.copy(self.logger) - # use setters to configure loggers - result.logger_file = self.logger_file - result.debug = self.debug - return result - - def __setattr__(self, name, value): - object.__setattr__(self, name, value) - if name == 'disabled_client_side_validations': - s = set(filter(None, value.split(','))) - for v in s: - if v not in JSON_SCHEMA_VALIDATION_KEYWORDS: - raise ApiValueError( - "Invalid keyword: '{0}''".format(v)) - self._disabled_client_side_validations = s -{{#hasHttpSignatureMethods}} - if name == "signing_info" and value is not None: - # Ensure the host paramater from signing info is the same as - # Configuration.host. - value.host = self.host -{{/hasHttpSignatureMethods}} - - @classmethod - def set_default(cls, default): - """Set default instance of configuration. - - It stores default configuration, which can be - returned by get_default_copy method. - - :param default: object of Configuration - """ - cls._default = copy.deepcopy(default) - - @classmethod - def get_default_copy(cls): - """Return new instance of configuration. - - This method returns newly created, based on default constructor, - object of Configuration class or returns a copy of default - configuration passed by the set_default method. - - :return: The configuration object. - """ - if cls._default is not None: - return copy.deepcopy(cls._default) - return Configuration() - - @property - def logger_file(self): - """The logger file. - - If the logger_file is None, then add stream handler and remove file - handler. Otherwise, add file handler and remove stream handler. - - :param value: The logger_file path. - :type: str - """ - return self.__logger_file - - @logger_file.setter - def logger_file(self, value): - """The logger file. - - If the logger_file is None, then add stream handler and remove file - handler. Otherwise, add file handler and remove stream handler. - - :param value: The logger_file path. - :type: str - """ - self.__logger_file = value - if self.__logger_file: - # If set logging file, - # then add file handler and remove stream handler. - self.logger_file_handler = logging.FileHandler(self.__logger_file) - self.logger_file_handler.setFormatter(self.logger_formatter) - for _, logger in self.logger.items(): - logger.addHandler(self.logger_file_handler) - - @property - def debug(self): - """Debug status - - :param value: The debug status, True or False. - :type: bool - """ - return self.__debug - - @debug.setter - def debug(self, value): - """Debug status - - :param value: The debug status, True or False. - :type: bool - """ - self.__debug = value - if self.__debug: - # if debug status is True, turn on debug logging - for _, logger in self.logger.items(): - logger.setLevel(logging.DEBUG) - # turn on http_client debug - http_client.HTTPConnection.debuglevel = 1 - else: - # if debug status is False, turn off debug logging, - # setting log level to default `logging.WARNING` - for _, logger in self.logger.items(): - logger.setLevel(logging.WARNING) - # turn off http_client debug - http_client.HTTPConnection.debuglevel = 0 - - @property - def logger_format(self): - """The logger format. - - The logger_formatter will be updated when sets logger_format. - - :param value: The format string. - :type: str - """ - return self.__logger_format - - @logger_format.setter - def logger_format(self, value): - """The logger format. - - The logger_formatter will be updated when sets logger_format. - - :param value: The format string. - :type: str - """ - self.__logger_format = value - self.logger_formatter = logging.Formatter(self.__logger_format) - - def get_api_key_with_prefix(self, identifier, alias=None): - """Gets API key (with prefix if set). - - :param identifier: The identifier of apiKey. - :param alias: The alternative identifier of apiKey. - :return: The token for api key authentication. - """ - if self.refresh_api_key_hook is not None: - self.refresh_api_key_hook(self) - key = self.api_key.get(identifier, self.api_key.get(alias) if alias is not None else None) - if key: - prefix = self.api_key_prefix.get(identifier) - if prefix: - return "%s %s" % (prefix, key) - else: - return key - - def get_basic_auth_token(self): - """Gets HTTP basic authentication header (string). - - :return: The token for basic HTTP authentication. - """ - username = "" - if self.username is not None: - username = self.username - password = "" - if self.password is not None: - password = self.password - return urllib3.util.make_headers( - basic_auth=username + ':' + password - ).get('authorization') - - def auth_settings(self): - """Gets Auth Settings dict for api client. - - :return: The Auth Settings information dict. - """ - auth = {} -{{#authMethods}} -{{#isApiKey}} - if '{{name}}' in self.api_key{{#vendorExtensions.x-auth-id-alias}} or '{{.}}' in self.api_key{{/vendorExtensions.x-auth-id-alias}}: - auth['{{name}}'] = { - 'type': 'api_key', - 'in': {{#isKeyInCookie}}'cookie'{{/isKeyInCookie}}{{#isKeyInHeader}}'header'{{/isKeyInHeader}}{{#isKeyInQuery}}'query'{{/isKeyInQuery}}, - 'key': '{{keyParamName}}', - 'value': self.get_api_key_with_prefix( - '{{name}}',{{#vendorExtensions.x-auth-id-alias}} - alias='{{.}}',{{/vendorExtensions.x-auth-id-alias}} - ), - } -{{/isApiKey}} -{{#isBasic}} - {{#isBasicBasic}} - if self.username is not None and self.password is not None: - auth['{{name}}'] = { - 'type': 'basic', - 'in': 'header', - 'key': 'Authorization', - 'value': self.get_basic_auth_token() - } - {{/isBasicBasic}} - {{#isBasicBearer}} - if self.access_token is not None: - auth['{{name}}'] = { - 'type': 'bearer', - 'in': 'header', - {{#bearerFormat}} - 'format': '{{{.}}}', - {{/bearerFormat}} - 'key': 'Authorization', - 'value': 'Bearer ' + self.access_token - } - {{/isBasicBearer}} - {{#isHttpSignature}} - if self.signing_info is not None: - auth['{{name}}'] = { - 'type': 'http-signature', - 'in': 'header', - 'key': 'Authorization', - 'value': None # Signature headers are calculated for every HTTP request - } - {{/isHttpSignature}} -{{/isBasic}} -{{#isOAuth}} - if self.access_token is not None: - auth['{{name}}'] = { - 'type': 'oauth2', - 'in': 'header', - 'key': 'Authorization', - 'value': 'Bearer ' + self.access_token - } -{{/isOAuth}} -{{/authMethods}} - return auth - - def to_debug_report(self): - """Gets the essential information for debugging. - - :return: The report for debugging. - """ - return "Python SDK Debug Report:\n"\ - "OS: {env}\n"\ - "Python Version: {pyversion}\n"\ - "Version of the API: {{version}}\n"\ - "SDK Package Version: {{packageVersion}}".\ - format(env=sys.platform, pyversion=sys.version) - - def get_host_settings(self): - """Gets an array of host settings - - :return: An array of host settings - """ - return [ - {{#servers}} - { - 'url': "{{{url}}}", - 'description': "{{{description}}}{{^description}}No description provided{{/description}}", - {{#variables}} - {{#-first}} - 'variables': { - {{/-first}} - '{{{name}}}': { - 'description': "{{{description}}}{{^description}}No description provided{{/description}}", - 'default_value': "{{{defaultValue}}}", - {{#enumValues}} - {{#-first}} - 'enum_values': [ - {{/-first}} - "{{{.}}}"{{^-last}},{{/-last}} - {{#-last}} - ] - {{/-last}} - {{/enumValues}} - }{{^-last}},{{/-last}} - {{#-last}} - } - {{/-last}} - {{/variables}} - }{{^-last}},{{/-last}} - {{/servers}} - ] - - def get_host_from_settings(self, index, variables=None, servers=None): - """Gets host URL based on the index and variables - :param index: array index of the host settings - :param variables: hash of variable and the corresponding value - :param servers: an array of host settings or None - :return: URL based on host settings - """ - if index is None: - return self._base_path - - variables = {} if variables is None else variables - servers = self.get_host_settings() if servers is None else servers - - try: - server = servers[index] - except IndexError: - raise ValueError( - "Invalid index {0} when selecting the host settings. " - "Must be less than {1}".format(index, len(servers))) - - url = server['url'] - - # go through variables and replace placeholders - for variable_name, variable in server.get('variables', {}).items(): - used_value = variables.get( - variable_name, variable['default_value']) - - if 'enum_values' in variable \ - and used_value not in variable['enum_values']: - raise ValueError( - "The variable `{0}` in the host URL has invalid value " - "{1}. Must be {2}.".format( - variable_name, variables[variable_name], - variable['enum_values'])) - - url = url.replace("{" + variable_name + "}", used_value) - - return url - - @property - def host(self): - """Return generated host.""" - return self.get_host_from_settings(self.server_index, variables=self.server_variables) - - @host.setter - def host(self, value): - """Fix base path.""" - self._base_path = value - self.server_index = None diff --git a/python-experimental/exceptions.mustache b/python-experimental/exceptions.mustache deleted file mode 100644 index 8d445c6e24..0000000000 --- a/python-experimental/exceptions.mustache +++ /dev/null @@ -1,129 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - - -class OpenApiException(Exception): - """The base exception class for all OpenAPIExceptions""" - - -class ApiTypeError(OpenApiException, TypeError): - def __init__(self, msg, path_to_item=None, valid_classes=None, - key_type=None): - """ Raises an exception for TypeErrors - - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (list): a list of keys an indices to get to the - current_item - None if unset - valid_classes (tuple): the primitive classes that current item - should be an instance of - None if unset - key_type (bool): False if our value is a value in a dict - True if it is a key in a dict - False if our item is an item in a list - None if unset - """ - self.path_to_item = path_to_item - self.valid_classes = valid_classes - self.key_type = key_type - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiTypeError, self).__init__(full_msg) - - -class ApiValueError(OpenApiException, ValueError): - def __init__(self, msg, path_to_item=None): - """ - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (list) the path to the exception in the - received_data dict. None if unset - """ - - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiValueError, self).__init__(full_msg) - - -class ApiAttributeError(OpenApiException, AttributeError): - def __init__(self, msg, path_to_item=None): - """ - Raised when an attribute reference or assignment fails. - - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (None/list) the path to the exception in the - received_data dict - """ - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiAttributeError, self).__init__(full_msg) - - -class ApiKeyError(OpenApiException, KeyError): - def __init__(self, msg, path_to_item=None): - """ - Args: - msg (str): the exception message - - Keyword Args: - path_to_item (None/list) the path to the exception in the - received_data dict - """ - self.path_to_item = path_to_item - full_msg = msg - if path_to_item: - full_msg = "{0} at {1}".format(msg, render_path(path_to_item)) - super(ApiKeyError, self).__init__(full_msg) - - -class ApiException(OpenApiException): - - def __init__(self, status=None, reason=None, http_resp=None): - if http_resp: - self.status = http_resp.status - self.reason = http_resp.reason - self.body = http_resp.data - self.headers = http_resp.getheaders() - else: - self.status = status - self.reason = reason - self.body = None - self.headers = None - - def __str__(self): - """Custom error messages for exception""" - error_message = "({0})\n"\ - "Reason: {1}\n".format(self.status, self.reason) - if self.headers: - error_message += "HTTP response headers: {0}\n".format( - self.headers) - - if self.body: - error_message += "HTTP response body: {0}\n".format(self.body) - - return error_message - - -def render_path(path_to_item): - """Returns a string representation of a path""" - result = "" - for pth in path_to_item: - if isinstance(pth, int): - result += "[{0}]".format(pth) - else: - result += "['{0}']".format(pth) - return result diff --git a/python-experimental/gitlab-ci.mustache b/python-experimental/gitlab-ci.mustache deleted file mode 100644 index 60c4b37893..0000000000 --- a/python-experimental/gitlab-ci.mustache +++ /dev/null @@ -1,29 +0,0 @@ -# ref: https://docs.gitlab.com/ee/ci/README.html - -stages: - - test - -.tests: - stage: test - script: - - pip install -r requirements.txt - - pip install -r test-requirements.txt - {{#useNose}} - - nosetests - {{/useNose}} - {{^useNose}} - - pytest --cov={{{packageName}}} - {{/useNose}} - -test-3.5: - extends: .tests - image: python:3.5-alpine -test-3.6: - extends: .tests - image: python:3.6-alpine -test-3.7: - extends: .tests - image: python:3.7-alpine -test-3.8: - extends: .tests - image: python:3.8-alpine diff --git a/python-experimental/model.mustache b/python-experimental/model.mustache deleted file mode 100644 index 1fc47d9056..0000000000 --- a/python-experimental/model.mustache +++ /dev/null @@ -1,59 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import re # noqa: F401 -import sys # noqa: F401 - -import nulltype # noqa: F401 - -from {{packageName}}.model_utils import ( # noqa: F401 - ApiTypeError, - ModelComposed, - ModelNormal, - ModelSimple, - cached_property, - change_keys_js_to_python, - convert_js_args_to_python_args, - date, - datetime, - file_type, - none_type, - validate_get_composed_info, -) -{{#models}} -{{#model}} -{{#imports}} -{{#-first}} - -def lazy_import(): -{{/-first}} - {{{.}}} -{{/imports}} - - -{{^interfaces}} -{{#isArray}} -{{> python-experimental/model_templates/model_simple }} -{{/isArray}} -{{#isEnum}} -{{> python-experimental/model_templates/model_simple }} -{{/isEnum}} -{{#isAlias}} -{{> python-experimental/model_templates/model_simple }} -{{/isAlias}} -{{^isArray}} -{{^isEnum}} -{{^isAlias}} -{{> python-experimental/model_templates/model_normal }} -{{/isAlias}} -{{/isEnum}} -{{/isArray}} -{{/interfaces}} -{{#interfaces}} -{{#-last}} -{{> python-experimental/model_templates/model_composed }} -{{/-last}} -{{/interfaces}} -{{/model}} -{{/models}} diff --git a/python-experimental/model_doc.mustache b/python-experimental/model_doc.mustache deleted file mode 100644 index 7971d6c85f..0000000000 --- a/python-experimental/model_doc.mustache +++ /dev/null @@ -1,36 +0,0 @@ -{{#models}}{{#model}}# {{classname}} - -{{#description}}{{&description}} -{{/description}} -## Properties -Name | Type | Description | Notes ------------- | ------------- | ------------- | ------------- -{{#isEnum}} -**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}}{{#allowableValues}}{{#defaultValue}}, {{/defaultValue}} must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} -{{/isEnum}} -{{#isAlias}} -**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} -{{/isAlias}} -{{#isArray}} -**value** | {{^arrayModelType}}**{{dataType}}**{{/arrayModelType}}{{#arrayModelType}}[**{{dataType}}**]({{arrayModelType}}.md){{/arrayModelType}} | {{description}} | {{#defaultValue}}{{#hasRequired}} if omitted the server will use the default value of {{/hasRequired}}{{^hasRequired}}defaults to {{/hasRequired}}{{{.}}}{{/defaultValue}} -{{/isArray}} -{{#requiredVars}} -{{^defaultValue}} -**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{#isReadOnly}}[readonly] {{/isReadOnly}} -{{/defaultValue}} -{{/requiredVars}} -{{#requiredVars}} -{{#defaultValue}} -**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | {{^required}}[optional] {{/required}}{{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}}defaults to {{{.}}}{{/defaultValue}} -{{/defaultValue}} -{{/requiredVars}} -{{#optionalVars}} -**{{name}}** | {{^complexType}}**{{dataType}}**{{/complexType}}{{#complexType}}[**{{dataType}}**]({{complexType}}.md){{/complexType}} | {{description}} | [optional] {{#isReadOnly}}[readonly] {{/isReadOnly}}{{#defaultValue}} if omitted the server will use the default value of {{{.}}}{{/defaultValue}} -{{/optionalVars}} -{{#additionalPropertiesType}} -**any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional] -{{/additionalPropertiesType}} - -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) - -{{/model}}{{/models}} diff --git a/python-experimental/model_test.mustache b/python-experimental/model_test.mustache deleted file mode 100644 index 669cc12185..0000000000 --- a/python-experimental/model_test.mustache +++ /dev/null @@ -1,36 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import sys -import unittest - -import {{packageName}} -{{#models}} -{{#model}} -{{#imports}} -{{{.}}} -{{/imports}} -from {{modelPackage}}.{{classFilename}} import {{classname}} - - -class Test{{classname}}(unittest.TestCase): - """{{classname}} unit test stubs""" - - def setUp(self): - pass - - def tearDown(self): - pass - - def test{{classname}}(self): - """Test {{classname}}""" - # FIXME: construct object with mandatory attributes with example values - # model = {{classname}}() # noqa: E501 - pass - -{{/model}} -{{/models}} - -if __name__ == '__main__': - unittest.main() diff --git a/python-experimental/requirements.mustache b/python-experimental/requirements.mustache deleted file mode 100644 index 2c2f00fcb2..0000000000 --- a/python-experimental/requirements.mustache +++ /dev/null @@ -1,5 +0,0 @@ -nulltype -certifi >= 14.05.14 -python_dateutil >= 2.5.3 -setuptools >= 21.0.0 -urllib3 >= 1.15.1 diff --git a/python-experimental/rest.mustache b/python-experimental/rest.mustache deleted file mode 100644 index 5fb2da0af2..0000000000 --- a/python-experimental/rest.mustache +++ /dev/null @@ -1,282 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -import io -import json -import logging -import re -import ssl -from urllib.parse import urlencode - -import certifi -import urllib3 - -from {{packageName}}.exceptions import ApiException, ApiValueError - - -logger = logging.getLogger(__name__) - - -class RESTResponse(io.IOBase): - - def __init__(self, resp): - self.urllib3_response = resp - self.status = resp.status - self.reason = resp.reason - self.data = resp.data - - def getheaders(self): - """Returns a dictionary of the response headers.""" - return self.urllib3_response.getheaders() - - def getheader(self, name, default=None): - """Returns a given response header.""" - return self.urllib3_response.getheader(name, default) - - -class RESTClientObject(object): - - def __init__(self, configuration, pools_size=4, maxsize=None): - # urllib3.PoolManager will pass all kw parameters to connectionpool - # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/poolmanager.py#L75 # noqa: E501 - # https://github.com/shazow/urllib3/blob/f9409436f83aeb79fbaf090181cd81b784f1b8ce/urllib3/connectionpool.py#L680 # noqa: E501 - # maxsize is the number of requests to host that are allowed in parallel # noqa: E501 - # Custom SSL certificates and client certificates: http://urllib3.readthedocs.io/en/latest/advanced-usage.html # noqa: E501 - - # cert_reqs - if configuration.verify_ssl: - cert_reqs = ssl.CERT_REQUIRED - else: - cert_reqs = ssl.CERT_NONE - - # ca_certs - if configuration.ssl_ca_cert: - ca_certs = configuration.ssl_ca_cert - else: - # if not set certificate file, use Mozilla's root certificates. - ca_certs = certifi.where() - - addition_pool_args = {} - if configuration.assert_hostname is not None: - addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 - - if configuration.retries is not None: - addition_pool_args['retries'] = configuration.retries - - if configuration.socket_options is not None: - addition_pool_args['socket_options'] = configuration.socket_options - - if maxsize is None: - if configuration.connection_pool_maxsize is not None: - maxsize = configuration.connection_pool_maxsize - else: - maxsize = 4 - - # https pool manager - if configuration.proxy: - self.pool_manager = urllib3.ProxyManager( - num_pools=pools_size, - maxsize=maxsize, - cert_reqs=cert_reqs, - ca_certs=ca_certs, - cert_file=configuration.cert_file, - key_file=configuration.key_file, - proxy_url=configuration.proxy, - proxy_headers=configuration.proxy_headers, - **addition_pool_args - ) - else: - self.pool_manager = urllib3.PoolManager( - num_pools=pools_size, - maxsize=maxsize, - cert_reqs=cert_reqs, - ca_certs=ca_certs, - cert_file=configuration.cert_file, - key_file=configuration.key_file, - **addition_pool_args - ) - - def request(self, method, url, query_params=None, headers=None, - body=None, post_params=None, _preload_content=True, - _request_timeout=None): - """Perform requests. - - :param method: http request method - :param url: http request url - :param query_params: query parameters in the url - :param headers: http request headers - :param body: request json body, for `application/json` - :param post_params: request post parameters, - `application/x-www-form-urlencoded` - and `multipart/form-data` - :param _preload_content: if False, the urllib3.HTTPResponse object will - be returned without reading/decoding response - data. Default is True. - :param _request_timeout: timeout setting for this request. If one - number provided, it will be total request - timeout. It can also be a pair (tuple) of - (connection, read) timeouts. - """ - method = method.upper() - assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', - 'PATCH', 'OPTIONS'] - - if post_params and body: - raise ApiValueError( - "body parameter cannot be used with post_params parameter." - ) - - post_params = post_params or {} - headers = headers or {} - - timeout = None - if _request_timeout: - if isinstance(_request_timeout, (int, float)): # noqa: E501,F821 - timeout = urllib3.Timeout(total=_request_timeout) - elif (isinstance(_request_timeout, tuple) and - len(_request_timeout) == 2): - timeout = urllib3.Timeout( - connect=_request_timeout[0], read=_request_timeout[1]) - - if 'Content-Type' not in headers: - headers['Content-Type'] = 'application/json' - - try: - # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` - if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: - if query_params: - url += '?' + urlencode(query_params) - if re.search('json', headers['Content-Type'], re.IGNORECASE): - request_body = None - if body is not None: - request_body = json.dumps(body) - r = self.pool_manager.request( - method, url, - body=request_body, - preload_content=_preload_content, - timeout=timeout, - headers=headers) - elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 - r = self.pool_manager.request( - method, url, - fields=post_params, - encode_multipart=False, - preload_content=_preload_content, - timeout=timeout, - headers=headers) - elif headers['Content-Type'] == 'multipart/form-data': - # must del headers['Content-Type'], or the correct - # Content-Type which generated by urllib3 will be - # overwritten. - del headers['Content-Type'] - r = self.pool_manager.request( - method, url, - fields=post_params, - encode_multipart=True, - preload_content=_preload_content, - timeout=timeout, - headers=headers) - # Pass a `string` parameter directly in the body to support - # other content types than Json when `body` argument is - # provided in serialized form - elif isinstance(body, str) or isinstance(body, bytes): - request_body = body - r = self.pool_manager.request( - method, url, - body=request_body, - preload_content=_preload_content, - timeout=timeout, - headers=headers) - else: - # Cannot generate the request from given parameters - msg = """Cannot prepare a request message for provided - arguments. Please check that your arguments match - declared content type.""" - raise ApiException(status=0, reason=msg) - # For `GET`, `HEAD` - else: - r = self.pool_manager.request(method, url, - fields=query_params, - preload_content=_preload_content, - timeout=timeout, - headers=headers) - except urllib3.exceptions.SSLError as e: - msg = "{0}\n{1}".format(type(e).__name__, str(e)) - raise ApiException(status=0, reason=msg) - - if _preload_content: - r = RESTResponse(r) - - # log response body - logger.debug("response body: %s", r.data) - - if not 200 <= r.status <= 299: - raise ApiException(http_resp=r) - - return r - - def GET(self, url, headers=None, query_params=None, _preload_content=True, - _request_timeout=None): - return self.request("GET", url, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - query_params=query_params) - - def HEAD(self, url, headers=None, query_params=None, _preload_content=True, - _request_timeout=None): - return self.request("HEAD", url, - headers=headers, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - query_params=query_params) - - def OPTIONS(self, url, headers=None, query_params=None, post_params=None, - body=None, _preload_content=True, _request_timeout=None): - return self.request("OPTIONS", url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - - def DELETE(self, url, headers=None, query_params=None, body=None, - _preload_content=True, _request_timeout=None): - return self.request("DELETE", url, - headers=headers, - query_params=query_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - - def POST(self, url, headers=None, query_params=None, post_params=None, - body=None, _preload_content=True, _request_timeout=None): - return self.request("POST", url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - - def PUT(self, url, headers=None, query_params=None, post_params=None, - body=None, _preload_content=True, _request_timeout=None): - return self.request("PUT", url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) - - def PATCH(self, url, headers=None, query_params=None, post_params=None, - body=None, _preload_content=True, _request_timeout=None): - return self.request("PATCH", url, - headers=headers, - query_params=query_params, - post_params=post_params, - _preload_content=_preload_content, - _request_timeout=_request_timeout, - body=body) diff --git a/python-experimental/setup.mustache b/python-experimental/setup.mustache deleted file mode 100644 index 632584a592..0000000000 --- a/python-experimental/setup.mustache +++ /dev/null @@ -1,55 +0,0 @@ -# coding: utf-8 - -{{>partial_header}} - -from setuptools import setup, find_packages # noqa: H301 - -NAME = "{{{projectName}}}" -VERSION = "{{packageVersion}}" -{{#apiInfo}} -{{#apis}} -{{#-last}} -# To install the library, run the following -# -# python setup.py install -# -# prerequisite: setuptools -# http://pypi.python.org/pypi/setuptools - -REQUIRES = [ - "urllib3 >= 1.15", - "certifi", - "python-dateutil", - "nulltype", -{{#asyncio}} - "aiohttp >= 3.0.0", -{{/asyncio}} -{{#tornado}} - "tornado>=4.2,<5", -{{/tornado}} -{{#hasHttpSignatureMethods}} - "pem>=19.3.0", - "pycryptodome>=3.9.0", -{{/hasHttpSignatureMethods}} -] - -setup( - name=NAME, - version=VERSION, - description="{{appName}}", - author="{{#infoName}}{{infoName}}{{/infoName}}{{^infoName}}OpenAPI Generator community{{/infoName}}", - author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", - url="{{packageUrl}}", - keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], - python_requires=">=3.5", - install_requires=REQUIRES, - packages=find_packages(exclude=["test", "tests"]), - include_package_data=True, - {{#licenseInfo}}license="{{licenseInfo}}", - {{/licenseInfo}}long_description="""\ - {{appDescription}} # noqa: E501 - """ -) -{{/-last}} -{{/apis}} -{{/apiInfo}} diff --git a/python-experimental/test-requirements.mustache b/python-experimental/test-requirements.mustache deleted file mode 100644 index cc68f6484f..0000000000 --- a/python-experimental/test-requirements.mustache +++ /dev/null @@ -1,15 +0,0 @@ -{{#useNose}} -coverage>=4.0.3 -nose>=1.3.7 -pluggy>=0.3.1 -py>=1.4.31 -randomize>=0.13 -{{/useNose}} -{{^useNose}} -pytest~=4.6.7 # needed for python 3.4 -pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 3.4 -{{/useNose}} -{{#hasHttpSignatureMethods}} -pycryptodome>=3.9.0 -{{/hasHttpSignatureMethods}} \ No newline at end of file diff --git a/python-experimental/tox.mustache b/python-experimental/tox.mustache deleted file mode 100644 index 4c771c472b..0000000000 --- a/python-experimental/tox.mustache +++ /dev/null @@ -1,9 +0,0 @@ -[tox] -envlist = py3 - -[testenv] -deps=-r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt - -commands= - {{^useNose}}pytest --cov={{{packageName}}}{{/useNose}}{{#useNose}}nosetests{{/useNose}} diff --git a/python-experimental/travis.mustache b/python-experimental/travis.mustache deleted file mode 100644 index 3c255f64e9..0000000000 --- a/python-experimental/travis.mustache +++ /dev/null @@ -1,18 +0,0 @@ -# ref: https://docs.travis-ci.com/user/languages/python -language: python -python: - - "3.5" - - "3.6" - - "3.7" - - "3.8" -# command to install dependencies -install: - - "pip install -r requirements.txt" - - "pip install -r test-requirements.txt" -# command to run tests -{{#useNose}} -script: nosetests -{{/useNose}} -{{^useNose}} -script: pytest --cov={{{packageName}}} -{{/useNose}} diff --git a/requirements.mustache b/requirements.mustache index eb358efd5b..2c2f00fcb2 100644 --- a/requirements.mustache +++ b/requirements.mustache @@ -1,6 +1,5 @@ +nulltype certifi >= 14.05.14 -future; python_version<="2.7" -six >= 1.10 python_dateutil >= 2.5.3 setuptools >= 21.0.0 urllib3 >= 1.15.1 diff --git a/rest.mustache b/rest.mustache index 3916878624..5fb2da0af2 100644 --- a/rest.mustache +++ b/rest.mustache @@ -2,21 +2,17 @@ {{>partial_header}} -from __future__ import absolute_import - import io import json import logging import re import ssl +from urllib.parse import urlencode import certifi -# python 2 and python 3 compatibility library -import six -from six.moves.urllib.parse import urlencode import urllib3 -from {{packageName}}.exceptions import ApiException, UnauthorizedException, ForbiddenException, NotFoundException, ServiceException, ApiValueError +from {{packageName}}.exceptions import ApiException, ApiValueError logger = logging.getLogger(__name__) @@ -136,7 +132,7 @@ class RESTClientObject(object): timeout = None if _request_timeout: - if isinstance(_request_timeout, six.integer_types + (float, )): # noqa: E501,F821 + if isinstance(_request_timeout, (int, float)): # noqa: E501,F821 timeout = urllib3.Timeout(total=_request_timeout) elif (isinstance(_request_timeout, tuple) and len(_request_timeout) == 2): @@ -216,18 +212,6 @@ class RESTClientObject(object): logger.debug("response body: %s", r.data) if not 200 <= r.status <= 299: - if r.status == 401: - raise UnauthorizedException(http_resp=r) - - if r.status == 403: - raise ForbiddenException(http_resp=r) - - if r.status == 404: - raise NotFoundException(http_resp=r) - - if 500 <= r.status <= 599: - raise ServiceException(http_resp=r) - raise ApiException(http_resp=r) return r diff --git a/setup.mustache b/setup.mustache index a14de4016f..632584a592 100644 --- a/setup.mustache +++ b/setup.mustache @@ -16,13 +16,22 @@ VERSION = "{{packageVersion}}" # prerequisite: setuptools # http://pypi.python.org/pypi/setuptools -REQUIRES = ["urllib3 >= 1.15", "six >= 1.10", "certifi", "python-dateutil"] +REQUIRES = [ + "urllib3 >= 1.15", + "certifi", + "python-dateutil", + "nulltype", {{#asyncio}} -REQUIRES.append("aiohttp >= 3.0.0") + "aiohttp >= 3.0.0", {{/asyncio}} {{#tornado}} -REQUIRES.append("tornado>=4.2,<5") + "tornado>=4.2,<5", {{/tornado}} +{{#hasHttpSignatureMethods}} + "pem>=19.3.0", + "pycryptodome>=3.9.0", +{{/hasHttpSignatureMethods}} +] setup( name=NAME, @@ -32,6 +41,7 @@ setup( author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], + python_requires=">=3.5", install_requires=REQUIRES, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, diff --git a/python-experimental/signing.mustache b/signing.mustache similarity index 100% rename from python-experimental/signing.mustache rename to signing.mustache diff --git a/test-requirements.mustache b/test-requirements.mustache index 12021b47a1..cc68f6484f 100644 --- a/test-requirements.mustache +++ b/test-requirements.mustache @@ -6,7 +6,10 @@ py>=1.4.31 randomize>=0.13 {{/useNose}} {{^useNose}} -pytest~=4.6.7 # needed for python 2.7+3.4 +pytest~=4.6.7 # needed for python 3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -{{/useNose}} \ No newline at end of file +pytest-randomly==1.2.3 # needed for python 3.4 +{{/useNose}} +{{#hasHttpSignatureMethods}} +pycryptodome>=3.9.0 +{{/hasHttpSignatureMethods}} \ No newline at end of file diff --git a/tox.mustache b/tox.mustache index fe989faf93..4c771c472b 100644 --- a/tox.mustache +++ b/tox.mustache @@ -1,10 +1,5 @@ [tox] -{{^asyncio}} -envlist = py27, py3 -{{/asyncio}} -{{#asyncio}} envlist = py3 -{{/asyncio}} [testenv] deps=-r{toxinidir}/requirements.txt diff --git a/travis.mustache b/travis.mustache index 195488737d..3c255f64e9 100644 --- a/travis.mustache +++ b/travis.mustache @@ -1,10 +1,6 @@ # ref: https://docs.travis-ci.com/user/languages/python language: python python: - - "2.7" - - "3.2" - - "3.3" - - "3.4" - "3.5" - "3.6" - "3.7" From bd8874e85211117646786d81efd7138849c5153e Mon Sep 17 00:00:00 2001 From: Sergey Date: Sat, 5 Dec 2020 23:02:00 +0300 Subject: [PATCH 154/180] [python] Re-merge Subclass Python exceptions (#7321) (#8095) * Subclass Python exceptions (#7321) * Subclass Python exceptions: - UnauthorizedException (401) - ForbiddenException (403) - NotFoundException (404) - ServiceException [500 - 599] Fixes #2151 * add generated sample code * use Python 2 flavor inheritance * regenerate samples * update samples Co-authored-by: Ryan Rishi Co-authored-by: William Cheng --- exceptions.mustache | 24 ++++++++++++++++++++++++ rest.mustache | 14 +++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/exceptions.mustache b/exceptions.mustache index 8d445c6e24..a60554dc5e 100644 --- a/exceptions.mustache +++ b/exceptions.mustache @@ -118,6 +118,30 @@ class ApiException(OpenApiException): return error_message +class NotFoundException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(NotFoundException, self).__init__(status, reason, http_resp) + + +class UnauthorizedException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(UnauthorizedException, self).__init__(status, reason, http_resp) + + +class ForbiddenException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ForbiddenException, self).__init__(status, reason, http_resp) + + +class ServiceException(ApiException): + + def __init__(self, status=None, reason=None, http_resp=None): + super(ServiceException, self).__init__(status, reason, http_resp) + + def render_path(path_to_item): """Returns a string representation of a path""" result = "" diff --git a/rest.mustache b/rest.mustache index 5fb2da0af2..cc8884fb77 100644 --- a/rest.mustache +++ b/rest.mustache @@ -12,7 +12,7 @@ from urllib.parse import urlencode import certifi import urllib3 -from {{packageName}}.exceptions import ApiException, ApiValueError +from {{packageName}}.exceptions import ApiException, UnauthorizedException, ForbiddenException, NotFoundException, ServiceException, ApiValueError logger = logging.getLogger(__name__) @@ -212,6 +212,18 @@ class RESTClientObject(object): logger.debug("response body: %s", r.data) if not 200 <= r.status <= 299: + if r.status == 401: + raise UnauthorizedException(http_resp=r) + + if r.status == 403: + raise ForbiddenException(http_resp=r) + + if r.status == 404: + raise NotFoundException(http_resp=r) + + if 500 <= r.status <= 599: + raise ServiceException(http_resp=r) + raise ApiException(http_resp=r) return r From 19b2ceccebb3868e0b3e28d357a5a3b595e2b7d4 Mon Sep 17 00:00:00 2001 From: itaru2622 <70509350+itaru2622@users.noreply.github.com> Date: Tue, 8 Dec 2020 02:50:09 +0900 Subject: [PATCH 155/180] Fix bug [python][client] generated python client code cannot POST object in multipart/form-data (#8075) * encode object in json and add content-type:application/json for multipart/form-data fix issue https://github.com/OpenAPITools/openapi-generator/issues/8068 * update samples by ./bin/generate-samples.sh * non-ascii chars supported in encoding object to json, and add "content-type:application/json; charset=utf-8" * update samples again, by ./bin/generate-samples.sh * update comment(docstring) in parameters_to_multipart according to the discussion in PR review. * fix default value in parameters_to_multipart function as described in PR review comment. * update samples again, by ./bin/generate-samples.sh --- api_client.mustache | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/api_client.mustache b/api_client.mustache index fd3d0b8a20..63ad0f1f8f 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -10,6 +10,7 @@ import os import re import typing from urllib.parse import quote +from urllib3.fields import RequestField {{#tornado}} import tornado.gen @@ -169,6 +170,9 @@ class ApiClient(object): post_params = self.parameters_to_tuples(post_params, collection_formats) post_params.extend(self.files_parameters(files)) + if header_params['Content-Type'].startswith("multipart"): + post_params = self.parameters_to_multipart(post_params, + (dict) ) # body if body: @@ -243,6 +247,26 @@ class ApiClient(object): response_data.getheaders())) {{/tornado}} + def parameters_to_multipart(self, params, collection_types): + """Get parameters as list of tuples, formatting as json if value is collection_types + + :param params: Parameters as list of two-tuples + :param dict collection_types: Parameter collection types + :return: Parameters as list of tuple or urllib3.fields.RequestField + """ + new_params = [] + if collection_types is None: + collection_types = (dict) + for k, v in params.items() if isinstance(params, dict) else params: # noqa: E501 + if isinstance(v, collection_types): # v is instance of collection_type, formatting as application/json + v = json.dumps(v, ensure_ascii=False).encode("utf-8") + field = RequestField(k, v) + field.make_multipart(content_type="application/json; charset=utf-8") + new_params.append(field) + else: + new_params.append((k, v)) + return new_params + @classmethod def sanitize_for_serialization(cls, obj): """Builds a JSON POST object. From 39618772c7b5a401745a89451bd5909c944ac702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=9Clgen=20Sar=C4=B1kavak?= Date: Mon, 7 Dec 2020 23:07:35 +0300 Subject: [PATCH 156/180] [python] Update python versions (#8042) * Remove redundant encoding definitions UTF-8 is already the default encoding in Python 3. * Remove Python3.4 related requirements * Remove dead Python version 3.5 * Add Python 3.9 to CI and test configs * Update petstore example --- README.mustache | 2 +- README_onlypackage.mustache | 2 +- __init__apis.mustache | 1 - __init__models.mustache | 2 -- __init__package.mustache | 2 -- api.mustache | 2 -- api_client.mustache | 1 - api_test.mustache | 2 -- asyncio/rest.mustache | 2 -- configuration.mustache | 2 -- exceptions.mustache | 2 -- gitlab-ci.mustache | 6 +++--- model.mustache | 2 -- model_test.mustache | 2 -- model_utils.mustache | 2 -- rest.mustache | 2 -- setup.mustache | 4 +--- signing.mustache | 1 - test-requirements.mustache | 4 +--- tornado/rest.mustache | 2 -- travis.mustache | 2 +- 21 files changed, 8 insertions(+), 39 deletions(-) diff --git a/README.mustache b/README.mustache index 463e4e0d56..65a06eaae0 100644 --- a/README.mustache +++ b/README.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python >= 3.5 +Python >= 3.6 ## Installation & Usage ### pip install diff --git a/README_onlypackage.mustache b/README_onlypackage.mustache index 40dc242b7b..684f4a5efb 100644 --- a/README_onlypackage.mustache +++ b/README_onlypackage.mustache @@ -17,7 +17,7 @@ For more information, please visit [{{{infoUrl}}}]({{{infoUrl}}}) ## Requirements. -Python >= 3.5 +Python >= 3.6 ## Installation & Usage diff --git a/__init__apis.mustache b/__init__apis.mustache index 32d101a97d..b4ec8a9a47 100644 --- a/__init__apis.mustache +++ b/__init__apis.mustache @@ -1,7 +1,6 @@ {{#apiInfo}} {{#apis}} {{#-first}} -# coding: utf-8 # flake8: noqa diff --git a/__init__models.mustache b/__init__models.mustache index 5a2f25f875..76d91fc5d4 100644 --- a/__init__models.mustache +++ b/__init__models.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - # flake8: noqa # import all models into this package diff --git a/__init__package.mustache b/__init__package.mustache index d7ff5b8260..6308ba683f 100644 --- a/__init__package.mustache +++ b/__init__package.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - # flake8: noqa {{>partial_header}} diff --git a/api.mustache b/api.mustache index 0e76b3f29f..eb9a9cd2ef 100644 --- a/api.mustache +++ b/api.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import re # noqa: F401 diff --git a/api_client.mustache b/api_client.mustache index 63ad0f1f8f..aaf14c4af3 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -1,4 +1,3 @@ -# coding: utf-8 {{>partial_header}} import json diff --git a/api_test.mustache b/api_test.mustache index f9276b443c..bf2cd19285 100644 --- a/api_test.mustache +++ b/api_test.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import unittest diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 44531fce5a..7d1f477ea5 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import io diff --git a/configuration.mustache b/configuration.mustache index ca6fc37747..88697bc45f 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import copy diff --git a/exceptions.mustache b/exceptions.mustache index a60554dc5e..046dcd9a5a 100644 --- a/exceptions.mustache +++ b/exceptions.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} diff --git a/gitlab-ci.mustache b/gitlab-ci.mustache index 60c4b37893..cf785a80ab 100644 --- a/gitlab-ci.mustache +++ b/gitlab-ci.mustache @@ -15,9 +15,6 @@ stages: - pytest --cov={{{packageName}}} {{/useNose}} -test-3.5: - extends: .tests - image: python:3.5-alpine test-3.6: extends: .tests image: python:3.6-alpine @@ -27,3 +24,6 @@ test-3.7: test-3.8: extends: .tests image: python:3.8-alpine +test-3.9: + extends: .tests + image: python:3.9-alpine diff --git a/model.mustache b/model.mustache index f2cb2368ca..34fd9e5cde 100644 --- a/model.mustache +++ b/model.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{> partial_header }} import re # noqa: F401 diff --git a/model_test.mustache b/model_test.mustache index 669cc12185..aa95f64944 100644 --- a/model_test.mustache +++ b/model_test.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import sys diff --git a/model_utils.mustache b/model_utils.mustache index 1523dbc2d7..9f3264e98e 100644 --- a/model_utils.mustache +++ b/model_utils.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} from datetime import date, datetime # noqa: F401 diff --git a/rest.mustache b/rest.mustache index cc8884fb77..0fbb0831ae 100644 --- a/rest.mustache +++ b/rest.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import io diff --git a/setup.mustache b/setup.mustache index 632584a592..a009be3f91 100644 --- a/setup.mustache +++ b/setup.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} from setuptools import setup, find_packages # noqa: H301 @@ -41,7 +39,7 @@ setup( author_email="{{#infoEmail}}{{infoEmail}}{{/infoEmail}}{{^infoEmail}}team@openapitools.org{{/infoEmail}}", url="{{packageUrl}}", keywords=["OpenAPI", "OpenAPI-Generator", "{{{appName}}}"], - python_requires=">=3.5", + python_requires=">=3.6", install_requires=REQUIRES, packages=find_packages(exclude=["test", "tests"]), include_package_data=True, diff --git a/signing.mustache b/signing.mustache index 26d2b8cb37..8dfbf5148f 100644 --- a/signing.mustache +++ b/signing.mustache @@ -1,4 +1,3 @@ -# coding: utf-8 {{>partial_header}} from base64 import b64encode diff --git a/test-requirements.mustache b/test-requirements.mustache index cc68f6484f..635b816e74 100644 --- a/test-requirements.mustache +++ b/test-requirements.mustache @@ -6,10 +6,8 @@ py>=1.4.31 randomize>=0.13 {{/useNose}} {{^useNose}} -pytest~=4.6.7 # needed for python 3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 3.4 {{/useNose}} {{#hasHttpSignatureMethods}} pycryptodome>=3.9.0 -{{/hasHttpSignatureMethods}} \ No newline at end of file +{{/hasHttpSignatureMethods}} diff --git a/tornado/rest.mustache b/tornado/rest.mustache index 2679760ea5..9e5cc12092 100644 --- a/tornado/rest.mustache +++ b/tornado/rest.mustache @@ -1,5 +1,3 @@ -# coding: utf-8 - {{>partial_header}} import io diff --git a/travis.mustache b/travis.mustache index 3c255f64e9..a26c984f3d 100644 --- a/travis.mustache +++ b/travis.mustache @@ -1,10 +1,10 @@ # ref: https://docs.travis-ci.com/user/languages/python language: python python: - - "3.5" - "3.6" - "3.7" - "3.8" + - "3.9" # command to install dependencies install: - "pip install -r requirements.txt" From 3acda73be21d8e85aa637b9068febe3aa932719b Mon Sep 17 00:00:00 2001 From: fbl100 Date: Mon, 7 Dec 2020 15:18:16 -0500 Subject: [PATCH 157/180] Fixes issue #8014, _check_type flag not being honored. (#8053) * Fixes issue 8014, _check_type flag not being honored. Updated model_utils.mustache to pass the check_type flag into attempt_convert_item(). Failure to do so results in type validation errors occurring when the user has specifically requested that they be disabled. * regenerated samples Co-authored-by: Frank Levine --- model_utils.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/model_utils.mustache b/model_utils.mustache index 9f3264e98e..9c299d4b3e 100644 --- a/model_utils.mustache +++ b/model_utils.mustache @@ -1116,7 +1116,8 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, configuration, spec_property_naming, key_type=False, - must_convert=True + must_convert=True, + check_type=_check_type ) return converted_instance else: @@ -1136,7 +1137,8 @@ def validate_and_convert_types(input_value, required_types_mixed, path_to_item, configuration, spec_property_naming, key_type=False, - must_convert=False + must_convert=False, + check_type=_check_type ) return converted_instance From 0e0444a4ed3bef2ceb6fbacc7cae375e00e35214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 15 Dec 2020 18:30:50 +0100 Subject: [PATCH 158/180] Include description directly in python docstrings (#8154) * Include description directly in python docstrings mustache escaping the description make them render weirdly, including sometimes unsupported characters in python. * More parameters --- api.mustache | 6 +++--- model_templates/method_init_shared.mustache | 6 +++--- model_templates/method_init_simple.mustache | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/api.mustache b/api.mustache index eb9a9cd2ef..a2a3d53697 100644 --- a/api.mustache +++ b/api.mustache @@ -64,17 +64,17 @@ class {{classname}}(object): {{/requiredParams}} {{#requiredParams}} {{^defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}{{/description}} + {{paramName}} ({{dataType}}):{{#description}} {{{description}}}{{/description}} {{/defaultValue}} {{/requiredParams}} {{#requiredParams}} {{#defaultValue}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] + {{paramName}} ({{dataType}}):{{#description}} {{{description}}}.{{/description}} defaults to {{{defaultValue}}}, must be one of [{{{defaultValue}}}] {{/defaultValue}} {{/requiredParams}} Keyword Args:{{#optionalParams}} - {{paramName}} ({{dataType}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} + {{paramName}} ({{dataType}}):{{#description}} {{{description}}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}}{{/optionalParams}} _return_http_data_only (bool): response data without head status code and headers. Default is True. _preload_content (bool): if False, the urllib3.HTTPResponse object diff --git a/model_templates/method_init_shared.mustache b/model_templates/method_init_shared.mustache index f3497ef53b..a766c14bac 100644 --- a/model_templates/method_init_shared.mustache +++ b/model_templates/method_init_shared.mustache @@ -7,7 +7,7 @@ Args: {{/-first}} {{^defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}{{/description}} + {{name}} ({{{dataType}}}):{{#description}} {{{description}}}{{/description}} {{/defaultValue}} {{#-last}} @@ -16,12 +16,12 @@ Keyword Args: {{#requiredVars}} {{#defaultValue}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 + {{name}} ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}} defaults to {{{defaultValue}}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{/defaultValue}} {{/requiredVars}} {{> model_templates/docstring_init_required_kwargs }} {{#optionalVars}} - {{name}} ({{{dataType}}}):{{#description}} {{description}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 + {{name}} ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}} [optional]{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} # noqa: E501 {{/optionalVars}} """ diff --git a/model_templates/method_init_simple.mustache b/model_templates/method_init_simple.mustache index 2340cf74ef..c1f323881e 100644 --- a/model_templates/method_init_simple.mustache +++ b/model_templates/method_init_simple.mustache @@ -14,10 +14,10 @@ Note that value can be passed either in args or in kwargs, but not in both. Args: - args[0] ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 + args[0] ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 Keyword Args: - value ({{{dataType}}}):{{#description}} {{description}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 + value ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{> model_templates/docstring_init_required_kwargs }} """ From d79ed54a0427081cdcbb147de68486a65176e29c Mon Sep 17 00:00:00 2001 From: Robert Parini Date: Wed, 16 Dec 2020 00:36:35 +0000 Subject: [PATCH 159/180] [Python][Client] Default to system CA instead of certifi (#8108) * Use system CA by default and remove certifi See https://github.com/OpenAPITools/openapi-generator/issues/6506 * Use system CA by default in asyncio client * Update README_onlypackage.mustache * Result of ./bin/generate-samples.sh * Add ssl_ca_cert argument for Configuration * Result of ./bin/generate-samples.sh * Remove certifi, use system CA by default --- README_onlypackage.mustache | 3 +-- asyncio/rest.mustache | 10 +--------- configuration.mustache | 5 ++++- requirements.mustache | 3 +-- rest.mustache | 12 ++---------- setup.mustache | 3 +-- 6 files changed, 10 insertions(+), 26 deletions(-) diff --git a/README_onlypackage.mustache b/README_onlypackage.mustache index 684f4a5efb..7202059fba 100644 --- a/README_onlypackage.mustache +++ b/README_onlypackage.mustache @@ -25,8 +25,7 @@ This python library package is generated without supporting files like setup.py To be able to use it, you will need these dependencies in your own package that uses this library: -* urllib3 >= 1.15 -* certifi +* urllib3 >= 1.25.3 * python-dateutil {{#asyncio}} * aiohttp diff --git a/asyncio/rest.mustache b/asyncio/rest.mustache index 7d1f477ea5..3744b62c81 100644 --- a/asyncio/rest.mustache +++ b/asyncio/rest.mustache @@ -7,7 +7,6 @@ import re import ssl import aiohttp -import certifi # python 2 and python 3 compatibility library from six.moves.urllib.parse import urlencode @@ -41,14 +40,7 @@ class RESTClientObject(object): if maxsize is None: maxsize = configuration.connection_pool_maxsize - # ca_certs - if configuration.ssl_ca_cert: - ca_certs = configuration.ssl_ca_cert - else: - # if not set certificate file, use Mozilla's root certificates. - ca_certs = certifi.where() - - ssl_context = ssl.create_default_context(cafile=ca_certs) + ssl_context = ssl.create_default_context(cafile=configuration.ssl_ca_cert) if configuration.cert_file: ssl_context.load_cert_chain( configuration.cert_file, keyfile=configuration.key_file diff --git a/configuration.mustache b/configuration.mustache index 88697bc45f..2f698db3fe 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -71,6 +71,8 @@ class Configuration(object): :param server_operation_variables: Mapping from operation ID to a mapping with string values to replace variables in templated server configuration. The validation of enums is performed for variables with defined enum values before. + :param ssl_ca_cert: str - the path to a file of concatenated CA certificates + in PEM format {{#hasAuthMethods}} :Example: @@ -169,6 +171,7 @@ conf = {{{packageName}}}.Configuration( {{/hasHttpSignatureMethods}} server_index=None, server_variables=None, server_operation_index=None, server_operation_variables=None, + ssl_ca_cert=None, ): """Constructor """ @@ -253,7 +256,7 @@ conf = {{{packageName}}}.Configuration( Set this to false to skip verifying SSL certificate when calling API from https server. """ - self.ssl_ca_cert = None + self.ssl_ca_cert = ssl_ca_cert """Set this to customize the certificate file to verify the peer. """ self.cert_file = None diff --git a/requirements.mustache b/requirements.mustache index 2c2f00fcb2..73a84334c8 100644 --- a/requirements.mustache +++ b/requirements.mustache @@ -1,5 +1,4 @@ nulltype -certifi >= 14.05.14 python_dateutil >= 2.5.3 setuptools >= 21.0.0 -urllib3 >= 1.15.1 +urllib3 >= 1.25.3 diff --git a/rest.mustache b/rest.mustache index 0fbb0831ae..9e73386489 100644 --- a/rest.mustache +++ b/rest.mustache @@ -7,7 +7,6 @@ import re import ssl from urllib.parse import urlencode -import certifi import urllib3 from {{packageName}}.exceptions import ApiException, UnauthorizedException, ForbiddenException, NotFoundException, ServiceException, ApiValueError @@ -48,13 +47,6 @@ class RESTClientObject(object): else: cert_reqs = ssl.CERT_NONE - # ca_certs - if configuration.ssl_ca_cert: - ca_certs = configuration.ssl_ca_cert - else: - # if not set certificate file, use Mozilla's root certificates. - ca_certs = certifi.where() - addition_pool_args = {} if configuration.assert_hostname is not None: addition_pool_args['assert_hostname'] = configuration.assert_hostname # noqa: E501 @@ -77,7 +69,7 @@ class RESTClientObject(object): num_pools=pools_size, maxsize=maxsize, cert_reqs=cert_reqs, - ca_certs=ca_certs, + ca_certs=configuration.ssl_ca_cert, cert_file=configuration.cert_file, key_file=configuration.key_file, proxy_url=configuration.proxy, @@ -89,7 +81,7 @@ class RESTClientObject(object): num_pools=pools_size, maxsize=maxsize, cert_reqs=cert_reqs, - ca_certs=ca_certs, + ca_certs=configuration.ssl_ca_cert, cert_file=configuration.cert_file, key_file=configuration.key_file, **addition_pool_args diff --git a/setup.mustache b/setup.mustache index a009be3f91..707ff5bb50 100644 --- a/setup.mustache +++ b/setup.mustache @@ -15,8 +15,7 @@ VERSION = "{{packageVersion}}" # http://pypi.python.org/pypi/setuptools REQUIRES = [ - "urllib3 >= 1.15", - "certifi", + "urllib3 >= 1.25.3", "python-dateutil", "nulltype", {{#asyncio}} From 48a3cacc5645ff8c4d49cae1ca9b610796c74c98 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 8 Jan 2021 13:15:55 -0800 Subject: [PATCH 160/180] Fixes object serialization when there is an inline array property which contains a refed enum (#8387) * Fixes object inline enum defintion with refed enum item * Adds refed array model example w/ serialization + deserialization --- model_utils.mustache | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/model_utils.mustache b/model_utils.mustache index 9c299d4b3e..07b77a99d1 100644 --- a/model_utils.mustache +++ b/model_utils.mustache @@ -1211,10 +1211,13 @@ def model_to_dict(model_instance, serialize=True): # exist in attribute_map attr = model_instance.attribute_map.get(attr, attr) if isinstance(value, list): - result[attr] = list(map( - lambda x: model_to_dict(x, serialize=serialize) - if hasattr(x, '_data_store') else x, value - )) + if not value or isinstance(value[0], PRIMITIVE_TYPES): + # empty list or primitive types + result[attr] = value + elif isinstance(value[0], ModelSimple): + result[attr] = [x.value for x in value] + else: + result[attr] = [model_to_dict(x, serialize=serialize) for x in value] elif isinstance(value, dict): result[attr] = dict(map( lambda item: (item[0], From 1dd008e926b98598f00e4380e17e3d640ca3a89b Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Wed, 13 Jan 2021 17:38:41 +0100 Subject: [PATCH 161/180] [python] fix #8404: avoid shadowing the name Endpoint (#8405) if a type was named Endpoint, its import for use in the api would shadow the name Endpoint for the internal utility --- api.mustache | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api.mustache b/api.mustache index a2a3d53697..cbad6df2c5 100644 --- a/api.mustache +++ b/api.mustache @@ -3,7 +3,7 @@ import re # noqa: F401 import sys # noqa: F401 -from {{packageName}}.api_client import ApiClient, Endpoint +from {{packageName}}.api_client import ApiClient, Endpoint as _Endpoint from {{packageName}}.model_utils import ( # noqa: F401 check_allowed_values, check_validations, @@ -125,7 +125,7 @@ class {{classname}}(object): {{/requiredParams}} return self.call_with_http_info(**kwargs) - self.{{operationId}} = Endpoint( + self.{{operationId}} = _Endpoint( settings={ 'response_type': {{#returnType}}({{{returnType}}},){{/returnType}}{{^returnType}}None{{/returnType}}, {{#authMethods}} From 0937196534313d51a7572d49dd40dcbbbb26e072 Mon Sep 17 00:00:00 2001 From: Justin Black Date: Fri, 15 Jan 2021 13:27:33 -0800 Subject: [PATCH 162/180] [python] Fixes file upload + download, adds tests (#8437) * Adds tests for file upload and files upload * Adds test_download_attachment * Fixes test_upload_file * Adds download_attachment endpoint * Adds test_download_attachment * Updates assert_request_called_with signature * Samples regen * Adds upload download file spec route and sample gen * Fixes file upload for application/octet-stream, writes test_upload_download_file * Changes if into elif * Improves python code in api_client --- api_client.mustache | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/api_client.mustache b/api_client.mustache index aaf14c4af3..9b9a04fefd 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -199,8 +199,6 @@ class ApiClient(object): e.body = e.body.decode('utf-8') raise e - content_type = response_data.getheader('content-type') - self.last_response = response_data return_data = response_data @@ -214,15 +212,17 @@ class ApiClient(object): {{/tornado}} return return_data - if response_type not in ["file", "bytes"]: - match = None - if content_type is not None: - match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) - encoding = match.group(1) if match else "utf-8" - response_data.data = response_data.data.decode(encoding) - # deserialize response data if response_type: + if response_type != (file_type,): + encoding = "utf-8" + content_type = response_data.getheader('content-type') + if content_type is not None: + match = re.search(r"charset=([a-zA-Z\-\d]+)[\s\;]?", content_type) + if match: + encoding = match.group(1) + response_data.data = response_data.data.decode(encoding) + return_data = self.deserialize( response_data, response_type, @@ -268,7 +268,7 @@ class ApiClient(object): @classmethod def sanitize_for_serialization(cls, obj): - """Builds a JSON POST object. + """Prepares data for transmission before it is sent with the rest client If obj is None, return None. If obj is str, int, long, float, bool, return directly. If obj is datetime.datetime, datetime.date @@ -276,6 +276,7 @@ class ApiClient(object): If obj is list, sanitize each element in the list. If obj is dict, return the dict. If obj is OpenAPI model, return the properties dict. + If obj is io.IOBase, return the bytes :param obj: The data to serialize. :return: The serialized form of data. """ @@ -283,6 +284,8 @@ class ApiClient(object): return { key: cls.sanitize_for_serialization(val) for key, val in model_to_dict(obj, serialize=True).items() } + elif isinstance(obj, io.IOBase): + return cls.get_file_data_and_close_file(obj) elif isinstance(obj, (str, int, float, none_type, bool)): return obj elif isinstance(obj, (datetime, date)): @@ -526,6 +529,12 @@ class ApiClient(object): new_params.append((k, v)) return new_params + @staticmethod + def get_file_data_and_close_file(file_instance: io.IOBase) -> bytes: + file_data = file_instance.read() + file_instance.close() + return file_data + def files_parameters(self, files: typing.Optional[typing.Dict[str, typing.List[io.IOBase]]] = None): """Builds form parameters. @@ -551,12 +560,11 @@ class ApiClient(object): "for %s must be open." % param_name ) filename = os.path.basename(file_instance.name) - filedata = file_instance.read() + filedata = self.get_file_data_and_close_file(file_instance) mimetype = (mimetypes.guess_type(filename)[0] or 'application/octet-stream') params.append( tuple([param_name, tuple([filename, filedata, mimetype])])) - file_instance.close() return params From ba1b7aa172fa6821f1c24dbca6bb0bec53c210d5 Mon Sep 17 00:00:00 2001 From: Johannes Wienke Date: Fri, 15 Jan 2021 22:51:12 +0100 Subject: [PATCH 163/180] Fix counting for large API solutions in generated Python README (#8403) * Fix counting for large API solutions Let 2 follow 1. * Update Python samples with new readme --- README_common.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_common.mustache b/README_common.mustache index ec525d175b..9999f508c8 100644 --- a/README_common.mustache +++ b/README_common.mustache @@ -100,7 +100,7 @@ Use specific imports for apis and models like: - `from {{{packageName}}}.api.default_api import DefaultApi` - `from {{{packageName}}}.model.pet import Pet` -Solution 1: +Solution 2: Before importing the package, adjust the maximum recursion limit as shown below: ``` import sys From 6c8f7fe80722d5514205d79c455fb33a08cfe43c Mon Sep 17 00:00:00 2001 From: Justin Black Date: Thu, 28 Jan 2021 09:30:36 -0800 Subject: [PATCH 164/180] Removes nulltype from python, updates samples (#8555) * Removes nulltype from python, updates samples * Removes nulltype from the python requirements * Removes nulltype import in models, moves requiredVars to optionalVars when approprieate --- model.mustache | 2 -- model_templates/method_init_composed.mustache | 5 ----- requirements.mustache | 1 - setup.mustache | 1 - 4 files changed, 9 deletions(-) diff --git a/model.mustache b/model.mustache index 34fd9e5cde..680b60644c 100644 --- a/model.mustache +++ b/model.mustache @@ -3,8 +3,6 @@ import re # noqa: F401 import sys # noqa: F401 -import nulltype # noqa: F401 - from {{packageName}}.model_utils import ( # noqa: F401 ApiTypeError, ModelComposed, diff --git a/model_templates/method_init_composed.mustache b/model_templates/method_init_composed.mustache index 8b3650b33a..9b29837971 100644 --- a/model_templates/method_init_composed.mustache +++ b/model_templates/method_init_composed.mustache @@ -24,11 +24,6 @@ '{{name}}': {{name}}, {{/requiredVars}} } - # remove args whose value is Null because they are unset - required_arg_names = list(required_args.keys()) - for required_arg_name in required_arg_names: - if required_args[required_arg_name] is nulltype.Null: - del required_args[required_arg_name] model_args = {} model_args.update(required_args) model_args.update(kwargs) diff --git a/requirements.mustache b/requirements.mustache index 73a84334c8..96947f6040 100644 --- a/requirements.mustache +++ b/requirements.mustache @@ -1,4 +1,3 @@ -nulltype python_dateutil >= 2.5.3 setuptools >= 21.0.0 urllib3 >= 1.25.3 diff --git a/setup.mustache b/setup.mustache index 707ff5bb50..d5154f3fa6 100644 --- a/setup.mustache +++ b/setup.mustache @@ -17,7 +17,6 @@ VERSION = "{{packageVersion}}" REQUIRES = [ "urllib3 >= 1.25.3", "python-dateutil", - "nulltype", {{#asyncio}} "aiohttp >= 3.0.0", {{/asyncio}} From 4222aa0130bc18db9780efe68a9b42fc3d4a7a70 Mon Sep 17 00:00:00 2001 From: adpoliak <3969913+adpoliak@users.noreply.github.com> Date: Fri, 29 Jan 2021 19:24:10 -0500 Subject: [PATCH 165/180] [PYTHON] use customized default Configuration() objects if configured by the programmer (#8500) --- api_client.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_client.mustache b/api_client.mustache index 9b9a04fefd..8d6395a4c2 100644 --- a/api_client.mustache +++ b/api_client.mustache @@ -61,7 +61,7 @@ class ApiClient(object): def __init__(self, configuration=None, header_name=None, header_value=None, cookie=None, pool_threads=1): if configuration is None: - configuration = Configuration() + configuration = Configuration.get_default_copy() self.configuration = configuration self.pool_threads = pool_threads From a94b5ecd1d53225ca41e38475385487317e8ec7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=BDilvinas=20Urbonas?= Date: Fri, 5 Feb 2021 23:09:53 +0200 Subject: [PATCH 166/180] [BUG][Python] init access token for python client configuration (#7469) * fix: init access token for python client configuration * fix: remove duplicate initializations for access_token --- configuration.mustache | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/configuration.mustache b/configuration.mustache index 2f698db3fe..9ab0a84089 100644 --- a/configuration.mustache +++ b/configuration.mustache @@ -163,6 +163,7 @@ conf = {{{packageName}}}.Configuration( def __init__(self, host=None, api_key=None, api_key_prefix=None, + access_token=None, username=None, password=None, discard_unknown_keys=False, disabled_client_side_validations="", @@ -190,6 +191,7 @@ conf = {{{packageName}}}.Configuration( """Temp file folder for downloading files """ # Authentication Settings + self.access_token = access_token self.api_key = {} if api_key: self.api_key = api_key @@ -218,18 +220,6 @@ conf = {{{packageName}}}.Configuration( """The HTTP signing configuration """ {{/hasHttpSignatureMethods}} -{{#hasOAuthMethods}} - self.access_token = None - """access token for OAuth/Bearer - """ -{{/hasOAuthMethods}} -{{^hasOAuthMethods}} -{{#hasBearerMethods}} - self.access_token = None - """access token for OAuth/Bearer - """ -{{/hasBearerMethods}} -{{/hasOAuthMethods}} self.logger = {} """Logging Settings """ From e6909406b3ff381542163da98978645452d72de2 Mon Sep 17 00:00:00 2001 From: Ronny Pfannschmidt Date: Tue, 23 Feb 2021 06:00:14 +0100 Subject: [PATCH 167/180] [python][template] move _path_to_item of simple init to avoid name error (#8737) * [python][template] move _path_to_item of simple init up so its avaliable for missing default errors * update generated examples --- model_templates/method_init_simple.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/model_templates/method_init_simple.mustache b/model_templates/method_init_simple.mustache index c1f323881e..9e06a6a22e 100644 --- a/model_templates/method_init_simple.mustache +++ b/model_templates/method_init_simple.mustache @@ -20,6 +20,8 @@ value ({{{dataType}}}):{{#description}} {{{description}}}.{{/description}}{{#defaultValue}} if omitted defaults to {{{defaultValue}}}{{/defaultValue}}{{#allowableValues}}, must be one of [{{#enumVars}}{{{value}}}, {{/enumVars}}]{{/allowableValues}} # noqa: E501 {{> model_templates/docstring_init_required_kwargs }} """ + # required up here when default value is not given + _path_to_item = kwargs.pop('_path_to_item', ()) if 'value' in kwargs: value = kwargs.pop('value') @@ -41,7 +43,6 @@ _check_type = kwargs.pop('_check_type', True) _spec_property_naming = kwargs.pop('_spec_property_naming', False) - _path_to_item = kwargs.pop('_path_to_item', ()) _configuration = kwargs.pop('_configuration', None) _visited_composed_classes = kwargs.pop('_visited_composed_classes', ()) From 9f9dee6eed23b99f34a6ec6bdbffd484400c3f59 Mon Sep 17 00:00:00 2001 From: Tyler Ballast Date: Mon, 8 Mar 2021 14:40:54 +0100 Subject: [PATCH 168/180] Add whitespace to SDK documentation where necessary (#8919) * Add a space between table title and the line above it to resolve issues when translating markdown to asciidoc * Regenerate Samples Co-authored-by: Tyler Ballast Co-authored-by: tballast --- api_doc.mustache | 2 ++ model_doc.mustache | 1 + 2 files changed, 3 insertions(+) diff --git a/api_doc.mustache b/api_doc.mustache index 36eac3ca91..7c19d58ebd 100644 --- a/api_doc.mustache +++ b/api_doc.mustache @@ -38,6 +38,7 @@ Method | HTTP request | Description {{/authMethods}} {{/hasAuthMethods}} {{> api_doc_example }} + ### Parameters {{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}} Name | Type | Description | Notes @@ -61,6 +62,7 @@ Name | Type | Description | Notes - **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}} {{#responses.0}} + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/model_doc.mustache b/model_doc.mustache index 7971d6c85f..ff7358618e 100644 --- a/model_doc.mustache +++ b/model_doc.mustache @@ -2,6 +2,7 @@ {{#description}}{{&description}} {{/description}} + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- From 3558319621f0195edcbe1c9853d44a6acdcf63e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 169/180] Apply template-patches/python-fix-readme-links.patch --- templates/README_common.mustache | 4 ++-- templates/api_doc.mustache | 4 ++-- templates/model_doc.mustache | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/README_common.mustache b/templates/README_common.mustache index 9999f508c8..f1fa2c2d7d 100644 --- a/templates/README_common.mustache +++ b/templates/README_common.mustache @@ -42,12 +42,12 @@ All URIs are relative to *{{basePath}}* Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- -{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} +{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}} {{/operation}}{{/operations}}{{/apis}}{{/apiInfo}} ## Documentation For Models -{{#models}}{{#model}} - [{{{classname}}}]({{modelDocPath}}{{{classname}}}.md) +{{#models}}{{#model}} - [{{{classname}}}]({{{classname}}}.md) {{/model}}{{/models}} ## Documentation For Authorization diff --git a/templates/api_doc.mustache b/templates/api_doc.mustache index 7c19d58ebd..3946bfa584 100644 --- a/templates/api_doc.mustache +++ b/templates/api_doc.mustache @@ -54,7 +54,7 @@ Name | Type | Description | Notes ### Authorization -{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](../README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} +{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{{name}}}](README.md#{{{name}}}){{^-last}}, {{/-last}}{{/authMethods}} ### HTTP request headers @@ -71,7 +71,7 @@ Name | Type | Description | Notes {{/responses}} {{/responses.0}} -[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +[[Back to top]](#) [[Back to API list]](README.md#documentation-for-api-endpoints) [[Back to Model list]](README.md#documentation-for-models) [[Back to README]](README.md) {{/operation}} {{/operations}} diff --git a/templates/model_doc.mustache b/templates/model_doc.mustache index ff7358618e..d81a598b67 100644 --- a/templates/model_doc.mustache +++ b/templates/model_doc.mustache @@ -32,6 +32,6 @@ Name | Type | Description | Notes **any string name** | **{{additionalPropertiesType}}** | any string name can be used but the value must be the correct type | [optional] {{/additionalPropertiesType}} -[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) +[[Back to Model list]](README.md#documentation-for-models) [[Back to API list]](README.md#documentation-for-api-endpoints) [[Back to README]](README.md) {{/model}}{{/models}} From 3aa2ba3fd87aa17f8ecdfb81b817008e354bd4ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 170/180] Apply template-patches/python-custom-license-header.patch --- templates/partial_header.mustache | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/templates/partial_header.mustache b/templates/partial_header.mustache index c52fbceb13..07fc869f36 100644 --- a/templates/partial_header.mustache +++ b/templates/partial_header.mustache @@ -1,17 +1,3 @@ -""" -{{#appName}} - {{{appName}}} -{{/appName}} - -{{#appDescription}} - {{{appDescription}}} # noqa: E501 -{{/appDescription}} - - {{#version}} - The version of the OpenAPI document: {{{version}}} - {{/version}} - {{#infoEmail}} - Contact: {{{infoEmail}}} - {{/infoEmail}} - Generated by: https://openapi-generator.tech -""" +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. From 940bb9aaa22d23b664ab57f825db1a33434a792d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 171/180] Apply template-patches/python-operation-id-header.patch --- templates/api_client.mustache | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/api_client.mustache b/templates/api_client.mustache index 8d6395a4c2..0721b9f9d3 100644 --- a/templates/api_client.mustache +++ b/templates/api_client.mustache @@ -839,6 +839,7 @@ class Endpoint(object): self.__validate_inputs(kwargs) params = self.__gather_params(kwargs) + params['header']['Dd-Operation-Id'] = ''.join(x.title() for x in self.settings['operation_id'].split('_')) accept_headers_list = self.headers_map['accept'] if accept_headers_list: From f1b1082731b50e7108887a09692e86cc5e3004aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 172/180] Apply template-patches/python-user-agent.patch --- templates/api_client.mustache | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/templates/api_client.mustache b/templates/api_client.mustache index 0721b9f9d3..a371c9a04c 100644 --- a/templates/api_client.mustache +++ b/templates/api_client.mustache @@ -71,7 +71,7 @@ class ApiClient(object): self.default_headers[header_name] = header_value self.cookie = cookie # Set default User-Agent. - self.user_agent = '{{#httpUserAgent}}{{{.}}}{{/httpUserAgent}}{{^httpUserAgent}}OpenAPI-Generator/{{{packageVersion}}}/python{{/httpUserAgent}}' + self.user_agent = user_agent() def __enter__(self): return self @@ -869,3 +869,15 @@ class Endpoint(object): _request_timeout=kwargs['_request_timeout'], _host=_host, collection_formats=params['collection_format']) + + +def user_agent(): + """Generate default User-Agent header.""" + import platform + from datadog_api_client.version import __version__ + return "datadog-api-client-python/{version} (python {py}; os {os}; arch {arch})".format( + version=__version__, + py=platform.python_version(), + os=platform.system(), + arch=platform.machine(), + ) From 1c463336922679fa9fb9e969381b49f2cb573471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 173/180] Apply template-patches/python-discard-unknown-keys.patch --- templates/configuration.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/configuration.mustache b/templates/configuration.mustache index 9ab0a84089..7fcd96b874 100644 --- a/templates/configuration.mustache +++ b/templates/configuration.mustache @@ -165,7 +165,7 @@ conf = {{{packageName}}}.Configuration( api_key=None, api_key_prefix=None, access_token=None, username=None, password=None, - discard_unknown_keys=False, + discard_unknown_keys=True, disabled_client_side_validations="", {{#hasHttpSignatureMethods}} signing_info=None, From 38a96d872df762e223153238a7385fad5abb39ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 174/180] Apply template-patches/python-remove-extra-fields-in-attribute-map.patch --- templates/model_templates/classvars.mustache | 7 +++++++ templates/model_templates/model_composed.mustache | 9 +-------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/model_templates/classvars.mustache b/templates/model_templates/classvars.mustache index 88ae5df9f1..1c6aab23e9 100644 --- a/templates/model_templates/classvars.mustache +++ b/templates/model_templates/classvars.mustache @@ -90,6 +90,12 @@ openapi_types (dict): The key is attribute name and the value is attribute type. """ +{{#oneOf}} +{{#-first}} + return {} +{{/-first}} +{{/oneOf}} +{{^oneOf}} {{#imports}} {{#-first}} lazy_import() @@ -112,6 +118,7 @@ '{{name}}': ({{{dataType}}},), # noqa: E501 {{/optionalVars}} } +{{/oneOf}} @cached_property def discriminator(): diff --git a/templates/model_templates/model_composed.mustache b/templates/model_templates/model_composed.mustache index 76fe3a8f50..5b348e9d23 100644 --- a/templates/model_templates/model_composed.mustache +++ b/templates/model_templates/model_composed.mustache @@ -15,14 +15,7 @@ class {{classname}}(ModelComposed): {{> model_templates/classvars }} - attribute_map = { -{{#requiredVars}} - '{{name}}': '{{baseName}}', # noqa: E501 -{{/requiredVars}} -{{#optionalVars}} - '{{name}}': '{{baseName}}', # noqa: E501 -{{/optionalVars}} - } + attribute_map = {} {{> model_templates/method_init_composed }} From a0e2ac07142eb44be9c14b13cf20f35a22231bb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 175/180] Apply template-patches/python-unstable-operations.patch --- templates/api_client.mustache | 7 +++++++ templates/configuration.mustache | 15 +++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/templates/api_client.mustache b/templates/api_client.mustache index a371c9a04c..cede0a2b4e 100644 --- a/templates/api_client.mustache +++ b/templates/api_client.mustache @@ -3,6 +3,7 @@ import json import atexit import mimetypes +import warnings from multiprocessing.pool import ThreadPool import io import os @@ -793,6 +794,12 @@ class Endpoint(object): def call_with_http_info(self, **kwargs): + is_unstable = self.api_client.configuration.unstable_operations.get(self.settings['operation_id']) + if is_unstable: + warnings.warn("Using unstable operation '{0}'".format(self.settings['operation_id'])) + elif is_unstable is False: + raise ApiValueError("Unstable operation '{0}' is disabled".format(self.settings['operation_id'])) + try: index = self.api_client.configuration.server_operation_index.get( self.settings['operation_id'], self.api_client.configuration.server_index diff --git a/templates/configuration.mustache b/templates/configuration.mustache index 7fcd96b874..92dc64f41d 100644 --- a/templates/configuration.mustache +++ b/templates/configuration.mustache @@ -293,6 +293,21 @@ conf = {{{packageName}}}.Configuration( # Options to pass down to the underlying urllib3 socket self.socket_options = None + # Keep track of unstable operations + self.unstable_operations = { + {{#apiInfo}} + {{#apis}} + {{#operations}} + {{#operation}} + {{#vendorExtensions.x-unstable}} + "{{operationId}}": False, + {{/vendorExtensions.x-unstable}} + {{/operation}} + {{/operations}} + {{/apis}} + {{/apiInfo}} + } + def __deepcopy__(self, memo): cls = self.__class__ result = cls.__new__(cls) From 726e70c3a9f93ed98cad83fd727591fba227b003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 176/180] Apply template-patches/python-example-doc-use-env-var-names.patch --- templates/api_doc_example.mustache | 23 +++++++++++----------- templates/python_doc_auth_partial.mustache | 14 +++---------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/templates/api_doc_example.mustache b/templates/api_doc_example.mustache index bf989ae430..17bfe3795b 100644 --- a/templates/api_doc_example.mustache +++ b/templates/api_doc_example.mustache @@ -1,28 +1,27 @@ ```python -import time -import {{{packageName}}} +import os +from dateutil.parser import parse as dateutil_parser +from {{{packageName}}} import ApiClient, ApiException, Configuration from {{apiPackage}} import {{classVarName}} -{{#imports}} -{{{.}}} -{{/imports}} +from {{{packageName}}}.models import * from pprint import pprint {{> python_doc_auth_partial}} # Enter a context with an instance of the API client {{#hasAuthMethods}} -with {{{packageName}}}.ApiClient(configuration) as api_client: +with ApiClient(configuration) as api_client: {{/hasAuthMethods}} {{^hasAuthMethods}} -with {{{packageName}}}.ApiClient() as api_client: +with ApiClient() as api_client: {{/hasAuthMethods}} # Create an instance of the API class api_instance = {{classVarName}}.{{{classname}}}(api_client) {{#requiredParams}} {{^defaultValue}} - {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}} {{/defaultValue}} {{/requiredParams}} {{#optionalParams}} - {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} + {{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} if omitted the server will use the default value of {{{defaultValue}}}{{/defaultValue}} {{/optionalParams}} {{#requiredParams}} {{#-last}} @@ -36,7 +35,7 @@ with {{{packageName}}}.ApiClient() as api_client: {{#returnType}} pprint(api_response) {{/returnType}} - except {{{packageName}}}.ApiException as e: + except ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/-last}} {{/requiredParams}} @@ -53,7 +52,7 @@ with {{{packageName}}}.ApiClient() as api_client: {{#returnType}} pprint(api_response) {{/returnType}} - except {{{packageName}}}.ApiException as e: + except ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/-last}} {{/optionalParams}} @@ -69,7 +68,7 @@ with {{{packageName}}}.ApiClient() as api_client: {{#returnType}} pprint(api_response) {{/returnType}} - except {{{packageName}}}.ApiException as e: + except ApiException as e: print("Exception when calling {{classname}}->{{operationId}}: %s\n" % e) {{/optionalParams}} {{/requiredParams}} diff --git a/templates/python_doc_auth_partial.mustache b/templates/python_doc_auth_partial.mustache index 5106632d21..2e7db69617 100644 --- a/templates/python_doc_auth_partial.mustache +++ b/templates/python_doc_auth_partial.mustache @@ -1,14 +1,9 @@ # Defining the host is optional and defaults to {{{basePath}}} # See configuration.py for a list of all supported configuration parameters. -configuration = {{{packageName}}}.Configuration( - host = "{{{basePath}}}" +configuration = Configuration( + host="{{{basePath}}}" ) - {{#hasAuthMethods}} -# The client must configure the authentication and authorization parameters -# in accordance with the API server security policy. -# Examples for each auth method are provided below, use the example that -# satisfies your auth use case. {{#authMethods}} {{#isBasic}} {{#isBasicBasic}} @@ -92,10 +87,7 @@ configuration = {{{packageName}}}.Configuration( {{#isApiKey}} # Configure API key authorization: {{{name}}} -configuration.api_key['{{{name}}}'] = 'YOUR_API_KEY' - -# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed -# configuration.api_key_prefix['{{name}}'] = 'Bearer' +configuration.api_key['{{{name}}}'] = os.getenv('{{{vendorExtensions.x-env-name}}}') {{/isApiKey}} {{#isOAuth}} From eaca3527cc6209cbec4ff5b6e548726f2ca39391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 177/180] Apply template-patches/python-doc-unstable-op.patch --- templates/python_doc_auth_partial.mustache | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/python_doc_auth_partial.mustache b/templates/python_doc_auth_partial.mustache index 2e7db69617..b8b11175fb 100644 --- a/templates/python_doc_auth_partial.mustache +++ b/templates/python_doc_auth_partial.mustache @@ -98,4 +98,7 @@ configuration = {{{packageName}}}.Configuration( configuration.access_token = 'YOUR_ACCESS_TOKEN' {{/isOAuth}} {{/authMethods}} +{{#vendorExtensions.x-unstable}} +configuration.unstable_operations["{{operationId}}"] = True +{{/vendorExtensions.x-unstable}} {{/hasAuthMethods}} From 90daac2346bcc51281e32b60a56de7a989f21a5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 09:28:08 +0100 Subject: [PATCH 178/180] Apply template-patches/python-examples-with-dd-site.patch --- templates/python_doc_auth_partial.mustache | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/templates/python_doc_auth_partial.mustache b/templates/python_doc_auth_partial.mustache index b8b11175fb..47cc52b301 100644 --- a/templates/python_doc_auth_partial.mustache +++ b/templates/python_doc_auth_partial.mustache @@ -1,8 +1,9 @@ -# Defining the host is optional and defaults to {{{basePath}}} # See configuration.py for a list of all supported configuration parameters. -configuration = Configuration( - host="{{{basePath}}}" -) +configuration = Configuration() + +# Defining the site is optional and defaults to datadoghq.com +if "DD_SITE" in os.environ: + configuration.server_variables["site"] = os.environ["DD_SITE"] {{#hasAuthMethods}} {{#authMethods}} {{#isBasic}} From f6bd190b1f3fc387376be06c944e47ab0aff7888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Herv=C3=A9?= Date: Tue, 23 Mar 2021 10:32:36 +0100 Subject: [PATCH 179/180] Move templates --- {templates => .generator/templates}/README.mustache | 0 {templates => .generator/templates}/README_common.mustache | 0 {templates => .generator/templates}/README_onlypackage.mustache | 0 {templates => .generator/templates}/__init__.mustache | 0 {templates => .generator/templates}/__init__api.mustache | 0 {templates => .generator/templates}/__init__apis.mustache | 0 {templates => .generator/templates}/__init__model.mustache | 0 {templates => .generator/templates}/__init__models.mustache | 0 {templates => .generator/templates}/__init__package.mustache | 0 {templates => .generator/templates}/api.mustache | 0 {templates => .generator/templates}/api_client.mustache | 0 {templates => .generator/templates}/api_doc.mustache | 0 {templates => .generator/templates}/api_doc_example.mustache | 0 {templates => .generator/templates}/api_test.mustache | 0 {templates => .generator/templates}/asyncio/rest.mustache | 0 {templates => .generator/templates}/configuration.mustache | 0 {templates => .generator/templates}/exceptions.mustache | 0 {templates => .generator/templates}/git_push.sh.mustache | 0 {templates => .generator/templates}/gitignore.mustache | 0 {templates => .generator/templates}/gitlab-ci.mustache | 0 {templates => .generator/templates}/model.mustache | 0 {templates => .generator/templates}/model_doc.mustache | 0 .../templates}/model_templates/classvars.mustache | 0 .../templates}/model_templates/docstring_allowed.mustache | 0 .../model_templates/docstring_init_required_kwargs.mustache | 0 .../model_templates/docstring_openapi_validations.mustache | 0 .../templates}/model_templates/method_init_composed.mustache | 0 .../templates}/model_templates/method_init_normal.mustache | 0 .../templates}/model_templates/method_init_shared.mustache | 0 .../templates}/model_templates/method_init_simple.mustache | 0 .../templates}/model_templates/method_set_attribute.mustache | 0 .../model_templates/methods_setattr_getattr_composed.mustache | 0 .../model_templates/methods_setattr_getattr_normal.mustache | 0 .../templates}/model_templates/methods_shared.mustache | 0 .../model_templates/methods_todict_tostr_eq_shared.mustache | 0 .../templates}/model_templates/methods_tostr_eq_simple.mustache | 0 .../templates}/model_templates/model_composed.mustache | 0 .../templates}/model_templates/model_normal.mustache | 0 .../templates}/model_templates/model_simple.mustache | 0 .../templates}/model_templates/validations.mustache | 0 {templates => .generator/templates}/model_test.mustache | 0 {templates => .generator/templates}/model_utils.mustache | 0 {templates => .generator/templates}/partial_header.mustache | 0 .../templates}/python_doc_auth_partial.mustache | 0 {templates => .generator/templates}/requirements.mustache | 0 {templates => .generator/templates}/rest.mustache | 0 {templates => .generator/templates}/setup.mustache | 0 {templates => .generator/templates}/setup_cfg.mustache | 0 {templates => .generator/templates}/signing.mustache | 0 {templates => .generator/templates}/test-requirements.mustache | 0 {templates => .generator/templates}/tornado/rest.mustache | 0 {templates => .generator/templates}/tox.mustache | 0 {templates => .generator/templates}/travis.mustache | 0 53 files changed, 0 insertions(+), 0 deletions(-) rename {templates => .generator/templates}/README.mustache (100%) rename {templates => .generator/templates}/README_common.mustache (100%) rename {templates => .generator/templates}/README_onlypackage.mustache (100%) rename {templates => .generator/templates}/__init__.mustache (100%) rename {templates => .generator/templates}/__init__api.mustache (100%) rename {templates => .generator/templates}/__init__apis.mustache (100%) rename {templates => .generator/templates}/__init__model.mustache (100%) rename {templates => .generator/templates}/__init__models.mustache (100%) rename {templates => .generator/templates}/__init__package.mustache (100%) rename {templates => .generator/templates}/api.mustache (100%) rename {templates => .generator/templates}/api_client.mustache (100%) rename {templates => .generator/templates}/api_doc.mustache (100%) rename {templates => .generator/templates}/api_doc_example.mustache (100%) rename {templates => .generator/templates}/api_test.mustache (100%) rename {templates => .generator/templates}/asyncio/rest.mustache (100%) rename {templates => .generator/templates}/configuration.mustache (100%) rename {templates => .generator/templates}/exceptions.mustache (100%) rename {templates => .generator/templates}/git_push.sh.mustache (100%) rename {templates => .generator/templates}/gitignore.mustache (100%) rename {templates => .generator/templates}/gitlab-ci.mustache (100%) rename {templates => .generator/templates}/model.mustache (100%) rename {templates => .generator/templates}/model_doc.mustache (100%) rename {templates => .generator/templates}/model_templates/classvars.mustache (100%) rename {templates => .generator/templates}/model_templates/docstring_allowed.mustache (100%) rename {templates => .generator/templates}/model_templates/docstring_init_required_kwargs.mustache (100%) rename {templates => .generator/templates}/model_templates/docstring_openapi_validations.mustache (100%) rename {templates => .generator/templates}/model_templates/method_init_composed.mustache (100%) rename {templates => .generator/templates}/model_templates/method_init_normal.mustache (100%) rename {templates => .generator/templates}/model_templates/method_init_shared.mustache (100%) rename {templates => .generator/templates}/model_templates/method_init_simple.mustache (100%) rename {templates => .generator/templates}/model_templates/method_set_attribute.mustache (100%) rename {templates => .generator/templates}/model_templates/methods_setattr_getattr_composed.mustache (100%) rename {templates => .generator/templates}/model_templates/methods_setattr_getattr_normal.mustache (100%) rename {templates => .generator/templates}/model_templates/methods_shared.mustache (100%) rename {templates => .generator/templates}/model_templates/methods_todict_tostr_eq_shared.mustache (100%) rename {templates => .generator/templates}/model_templates/methods_tostr_eq_simple.mustache (100%) rename {templates => .generator/templates}/model_templates/model_composed.mustache (100%) rename {templates => .generator/templates}/model_templates/model_normal.mustache (100%) rename {templates => .generator/templates}/model_templates/model_simple.mustache (100%) rename {templates => .generator/templates}/model_templates/validations.mustache (100%) rename {templates => .generator/templates}/model_test.mustache (100%) rename {templates => .generator/templates}/model_utils.mustache (100%) rename {templates => .generator/templates}/partial_header.mustache (100%) rename {templates => .generator/templates}/python_doc_auth_partial.mustache (100%) rename {templates => .generator/templates}/requirements.mustache (100%) rename {templates => .generator/templates}/rest.mustache (100%) rename {templates => .generator/templates}/setup.mustache (100%) rename {templates => .generator/templates}/setup_cfg.mustache (100%) rename {templates => .generator/templates}/signing.mustache (100%) rename {templates => .generator/templates}/test-requirements.mustache (100%) rename {templates => .generator/templates}/tornado/rest.mustache (100%) rename {templates => .generator/templates}/tox.mustache (100%) rename {templates => .generator/templates}/travis.mustache (100%) diff --git a/templates/README.mustache b/.generator/templates/README.mustache similarity index 100% rename from templates/README.mustache rename to .generator/templates/README.mustache diff --git a/templates/README_common.mustache b/.generator/templates/README_common.mustache similarity index 100% rename from templates/README_common.mustache rename to .generator/templates/README_common.mustache diff --git a/templates/README_onlypackage.mustache b/.generator/templates/README_onlypackage.mustache similarity index 100% rename from templates/README_onlypackage.mustache rename to .generator/templates/README_onlypackage.mustache diff --git a/templates/__init__.mustache b/.generator/templates/__init__.mustache similarity index 100% rename from templates/__init__.mustache rename to .generator/templates/__init__.mustache diff --git a/templates/__init__api.mustache b/.generator/templates/__init__api.mustache similarity index 100% rename from templates/__init__api.mustache rename to .generator/templates/__init__api.mustache diff --git a/templates/__init__apis.mustache b/.generator/templates/__init__apis.mustache similarity index 100% rename from templates/__init__apis.mustache rename to .generator/templates/__init__apis.mustache diff --git a/templates/__init__model.mustache b/.generator/templates/__init__model.mustache similarity index 100% rename from templates/__init__model.mustache rename to .generator/templates/__init__model.mustache diff --git a/templates/__init__models.mustache b/.generator/templates/__init__models.mustache similarity index 100% rename from templates/__init__models.mustache rename to .generator/templates/__init__models.mustache diff --git a/templates/__init__package.mustache b/.generator/templates/__init__package.mustache similarity index 100% rename from templates/__init__package.mustache rename to .generator/templates/__init__package.mustache diff --git a/templates/api.mustache b/.generator/templates/api.mustache similarity index 100% rename from templates/api.mustache rename to .generator/templates/api.mustache diff --git a/templates/api_client.mustache b/.generator/templates/api_client.mustache similarity index 100% rename from templates/api_client.mustache rename to .generator/templates/api_client.mustache diff --git a/templates/api_doc.mustache b/.generator/templates/api_doc.mustache similarity index 100% rename from templates/api_doc.mustache rename to .generator/templates/api_doc.mustache diff --git a/templates/api_doc_example.mustache b/.generator/templates/api_doc_example.mustache similarity index 100% rename from templates/api_doc_example.mustache rename to .generator/templates/api_doc_example.mustache diff --git a/templates/api_test.mustache b/.generator/templates/api_test.mustache similarity index 100% rename from templates/api_test.mustache rename to .generator/templates/api_test.mustache diff --git a/templates/asyncio/rest.mustache b/.generator/templates/asyncio/rest.mustache similarity index 100% rename from templates/asyncio/rest.mustache rename to .generator/templates/asyncio/rest.mustache diff --git a/templates/configuration.mustache b/.generator/templates/configuration.mustache similarity index 100% rename from templates/configuration.mustache rename to .generator/templates/configuration.mustache diff --git a/templates/exceptions.mustache b/.generator/templates/exceptions.mustache similarity index 100% rename from templates/exceptions.mustache rename to .generator/templates/exceptions.mustache diff --git a/templates/git_push.sh.mustache b/.generator/templates/git_push.sh.mustache similarity index 100% rename from templates/git_push.sh.mustache rename to .generator/templates/git_push.sh.mustache diff --git a/templates/gitignore.mustache b/.generator/templates/gitignore.mustache similarity index 100% rename from templates/gitignore.mustache rename to .generator/templates/gitignore.mustache diff --git a/templates/gitlab-ci.mustache b/.generator/templates/gitlab-ci.mustache similarity index 100% rename from templates/gitlab-ci.mustache rename to .generator/templates/gitlab-ci.mustache diff --git a/templates/model.mustache b/.generator/templates/model.mustache similarity index 100% rename from templates/model.mustache rename to .generator/templates/model.mustache diff --git a/templates/model_doc.mustache b/.generator/templates/model_doc.mustache similarity index 100% rename from templates/model_doc.mustache rename to .generator/templates/model_doc.mustache diff --git a/templates/model_templates/classvars.mustache b/.generator/templates/model_templates/classvars.mustache similarity index 100% rename from templates/model_templates/classvars.mustache rename to .generator/templates/model_templates/classvars.mustache diff --git a/templates/model_templates/docstring_allowed.mustache b/.generator/templates/model_templates/docstring_allowed.mustache similarity index 100% rename from templates/model_templates/docstring_allowed.mustache rename to .generator/templates/model_templates/docstring_allowed.mustache diff --git a/templates/model_templates/docstring_init_required_kwargs.mustache b/.generator/templates/model_templates/docstring_init_required_kwargs.mustache similarity index 100% rename from templates/model_templates/docstring_init_required_kwargs.mustache rename to .generator/templates/model_templates/docstring_init_required_kwargs.mustache diff --git a/templates/model_templates/docstring_openapi_validations.mustache b/.generator/templates/model_templates/docstring_openapi_validations.mustache similarity index 100% rename from templates/model_templates/docstring_openapi_validations.mustache rename to .generator/templates/model_templates/docstring_openapi_validations.mustache diff --git a/templates/model_templates/method_init_composed.mustache b/.generator/templates/model_templates/method_init_composed.mustache similarity index 100% rename from templates/model_templates/method_init_composed.mustache rename to .generator/templates/model_templates/method_init_composed.mustache diff --git a/templates/model_templates/method_init_normal.mustache b/.generator/templates/model_templates/method_init_normal.mustache similarity index 100% rename from templates/model_templates/method_init_normal.mustache rename to .generator/templates/model_templates/method_init_normal.mustache diff --git a/templates/model_templates/method_init_shared.mustache b/.generator/templates/model_templates/method_init_shared.mustache similarity index 100% rename from templates/model_templates/method_init_shared.mustache rename to .generator/templates/model_templates/method_init_shared.mustache diff --git a/templates/model_templates/method_init_simple.mustache b/.generator/templates/model_templates/method_init_simple.mustache similarity index 100% rename from templates/model_templates/method_init_simple.mustache rename to .generator/templates/model_templates/method_init_simple.mustache diff --git a/templates/model_templates/method_set_attribute.mustache b/.generator/templates/model_templates/method_set_attribute.mustache similarity index 100% rename from templates/model_templates/method_set_attribute.mustache rename to .generator/templates/model_templates/method_set_attribute.mustache diff --git a/templates/model_templates/methods_setattr_getattr_composed.mustache b/.generator/templates/model_templates/methods_setattr_getattr_composed.mustache similarity index 100% rename from templates/model_templates/methods_setattr_getattr_composed.mustache rename to .generator/templates/model_templates/methods_setattr_getattr_composed.mustache diff --git a/templates/model_templates/methods_setattr_getattr_normal.mustache b/.generator/templates/model_templates/methods_setattr_getattr_normal.mustache similarity index 100% rename from templates/model_templates/methods_setattr_getattr_normal.mustache rename to .generator/templates/model_templates/methods_setattr_getattr_normal.mustache diff --git a/templates/model_templates/methods_shared.mustache b/.generator/templates/model_templates/methods_shared.mustache similarity index 100% rename from templates/model_templates/methods_shared.mustache rename to .generator/templates/model_templates/methods_shared.mustache diff --git a/templates/model_templates/methods_todict_tostr_eq_shared.mustache b/.generator/templates/model_templates/methods_todict_tostr_eq_shared.mustache similarity index 100% rename from templates/model_templates/methods_todict_tostr_eq_shared.mustache rename to .generator/templates/model_templates/methods_todict_tostr_eq_shared.mustache diff --git a/templates/model_templates/methods_tostr_eq_simple.mustache b/.generator/templates/model_templates/methods_tostr_eq_simple.mustache similarity index 100% rename from templates/model_templates/methods_tostr_eq_simple.mustache rename to .generator/templates/model_templates/methods_tostr_eq_simple.mustache diff --git a/templates/model_templates/model_composed.mustache b/.generator/templates/model_templates/model_composed.mustache similarity index 100% rename from templates/model_templates/model_composed.mustache rename to .generator/templates/model_templates/model_composed.mustache diff --git a/templates/model_templates/model_normal.mustache b/.generator/templates/model_templates/model_normal.mustache similarity index 100% rename from templates/model_templates/model_normal.mustache rename to .generator/templates/model_templates/model_normal.mustache diff --git a/templates/model_templates/model_simple.mustache b/.generator/templates/model_templates/model_simple.mustache similarity index 100% rename from templates/model_templates/model_simple.mustache rename to .generator/templates/model_templates/model_simple.mustache diff --git a/templates/model_templates/validations.mustache b/.generator/templates/model_templates/validations.mustache similarity index 100% rename from templates/model_templates/validations.mustache rename to .generator/templates/model_templates/validations.mustache diff --git a/templates/model_test.mustache b/.generator/templates/model_test.mustache similarity index 100% rename from templates/model_test.mustache rename to .generator/templates/model_test.mustache diff --git a/templates/model_utils.mustache b/.generator/templates/model_utils.mustache similarity index 100% rename from templates/model_utils.mustache rename to .generator/templates/model_utils.mustache diff --git a/templates/partial_header.mustache b/.generator/templates/partial_header.mustache similarity index 100% rename from templates/partial_header.mustache rename to .generator/templates/partial_header.mustache diff --git a/templates/python_doc_auth_partial.mustache b/.generator/templates/python_doc_auth_partial.mustache similarity index 100% rename from templates/python_doc_auth_partial.mustache rename to .generator/templates/python_doc_auth_partial.mustache diff --git a/templates/requirements.mustache b/.generator/templates/requirements.mustache similarity index 100% rename from templates/requirements.mustache rename to .generator/templates/requirements.mustache diff --git a/templates/rest.mustache b/.generator/templates/rest.mustache similarity index 100% rename from templates/rest.mustache rename to .generator/templates/rest.mustache diff --git a/templates/setup.mustache b/.generator/templates/setup.mustache similarity index 100% rename from templates/setup.mustache rename to .generator/templates/setup.mustache diff --git a/templates/setup_cfg.mustache b/.generator/templates/setup_cfg.mustache similarity index 100% rename from templates/setup_cfg.mustache rename to .generator/templates/setup_cfg.mustache diff --git a/templates/signing.mustache b/.generator/templates/signing.mustache similarity index 100% rename from templates/signing.mustache rename to .generator/templates/signing.mustache diff --git a/templates/test-requirements.mustache b/.generator/templates/test-requirements.mustache similarity index 100% rename from templates/test-requirements.mustache rename to .generator/templates/test-requirements.mustache diff --git a/templates/tornado/rest.mustache b/.generator/templates/tornado/rest.mustache similarity index 100% rename from templates/tornado/rest.mustache rename to .generator/templates/tornado/rest.mustache diff --git a/templates/tox.mustache b/.generator/templates/tox.mustache similarity index 100% rename from templates/tox.mustache rename to .generator/templates/tox.mustache diff --git a/templates/travis.mustache b/.generator/templates/travis.mustache similarity index 100% rename from templates/travis.mustache rename to .generator/templates/travis.mustache From e3c647b7079d170a166ba0576dca1ad92806d1ea Mon Sep 17 00:00:00 2001 From: "ci.datadog-api-spec" Date: Tue, 23 Mar 2021 14:03:27 +0000 Subject: [PATCH 180/180] Regenerate client from commit 7e667f1 of spec repo --- .apigentools-info | 8 +-- docs/v1/APIErrorResponse.md | 1 + docs/v1/AWSAccount.md | 1 + docs/v1/AWSAccountAndLambdaRequest.md | 1 + docs/v1/AWSAccountCreateResponse.md | 1 + docs/v1/AWSAccountListResponse.md | 1 + docs/v1/AWSIntegrationApi.md | 18 ++++++ docs/v1/AWSLogsAsyncError.md | 1 + docs/v1/AWSLogsAsyncResponse.md | 1 + docs/v1/AWSLogsIntegrationApi.md | 14 +++++ docs/v1/AWSLogsLambda.md | 1 + docs/v1/AWSLogsListResponse.md | 1 + docs/v1/AWSLogsListServicesResponse.md | 1 + docs/v1/AWSLogsServicesRequest.md | 1 + docs/v1/AWSNamespace.md | 1 + docs/v1/AWSTagFilter.md | 1 + docs/v1/AWSTagFilterCreateRequest.md | 1 + docs/v1/AWSTagFilterDeleteRequest.md | 1 + docs/v1/AWSTagFilterListResponse.md | 1 + docs/v1/AccessRole.md | 1 + docs/v1/AlertGraphWidgetDefinition.md | 1 + docs/v1/AlertGraphWidgetDefinitionType.md | 1 + docs/v1/AlertValueWidgetDefinition.md | 1 + docs/v1/AlertValueWidgetDefinitionType.md | 1 + docs/v1/ApiKey.md | 1 + docs/v1/ApiKeyListResponse.md | 1 + docs/v1/ApiKeyResponse.md | 1 + docs/v1/ApmStatsQueryColumnType.md | 1 + docs/v1/ApmStatsQueryDefinition.md | 1 + docs/v1/ApmStatsQueryRowType.md | 1 + docs/v1/ApplicationKey.md | 1 + docs/v1/ApplicationKeyListResponse.md | 1 + docs/v1/ApplicationKeyResponse.md | 1 + docs/v1/AuthenticationApi.md | 2 + docs/v1/AuthenticationValidationResponse.md | 1 + docs/v1/AzureAccount.md | 1 + docs/v1/AzureAccountListResponse.md | 1 + docs/v1/AzureIntegrationApi.md | 10 ++++ docs/v1/CancelDowntimesByScopeRequest.md | 1 + docs/v1/CanceledDowntimesIds.md | 1 + docs/v1/ChangeWidgetDefinition.md | 1 + docs/v1/ChangeWidgetDefinitionType.md | 1 + docs/v1/ChangeWidgetRequest.md | 1 + docs/v1/CheckCanDeleteMonitorResponse.md | 1 + docs/v1/CheckCanDeleteMonitorResponseData.md | 1 + docs/v1/CheckCanDeleteSLOResponse.md | 1 + docs/v1/CheckCanDeleteSLOResponseData.md | 1 + docs/v1/CheckStatusWidgetDefinition.md | 1 + docs/v1/CheckStatusWidgetDefinitionType.md | 1 + docs/v1/Creator.md | 1 + docs/v1/Dashboard.md | 1 + docs/v1/DashboardDeleteResponse.md | 1 + docs/v1/DashboardLayoutType.md | 1 + docs/v1/DashboardList.md | 1 + docs/v1/DashboardListDeleteResponse.md | 1 + docs/v1/DashboardListListResponse.md | 1 + docs/v1/DashboardListsApi.md | 10 ++++ docs/v1/DashboardSummary.md | 1 + docs/v1/DashboardSummaryDefinition.md | 1 + docs/v1/DashboardTemplateVariable.md | 1 + docs/v1/DashboardTemplateVariablePreset.md | 1 + .../DashboardTemplateVariablePresetValue.md | 1 + docs/v1/DashboardsApi.md | 10 ++++ docs/v1/DeletedMonitor.md | 1 + docs/v1/DistributionWidgetDefinition.md | 1 + docs/v1/DistributionWidgetDefinitionType.md | 1 + docs/v1/DistributionWidgetRequest.md | 1 + docs/v1/Downtime.md | 1 + docs/v1/DowntimeRecurrence.md | 1 + docs/v1/DowntimesApi.md | 12 ++++ docs/v1/Event.md | 1 + docs/v1/EventAlertType.md | 1 + docs/v1/EventListResponse.md | 1 + docs/v1/EventPriority.md | 1 + docs/v1/EventQueryDefinition.md | 1 + docs/v1/EventResponse.md | 1 + docs/v1/EventStreamWidgetDefinition.md | 1 + docs/v1/EventStreamWidgetDefinitionType.md | 1 + docs/v1/EventTimelineWidgetDefinition.md | 1 + docs/v1/EventTimelineWidgetDefinitionType.md | 1 + docs/v1/EventsApi.md | 4 ++ docs/v1/FormulaAndFunctionEventAggregation.md | 1 + .../FormulaAndFunctionEventQueryDefinition.md | 1 + ...aAndFunctionEventQueryDefinitionCompute.md | 1 + ...laAndFunctionEventQueryDefinitionSearch.md | 1 + .../v1/FormulaAndFunctionEventQueryGroupBy.md | 1 + ...FormulaAndFunctionEventQueryGroupBySort.md | 1 + docs/v1/FormulaAndFunctionEventsDataSource.md | 1 + .../v1/FormulaAndFunctionMetricAggregation.md | 1 + docs/v1/FormulaAndFunctionMetricDataSource.md | 1 + ...FormulaAndFunctionMetricQueryDefinition.md | 1 + ...ormulaAndFunctionProcessQueryDataSource.md | 1 + ...ormulaAndFunctionProcessQueryDefinition.md | 1 + docs/v1/FormulaAndFunctionQueryDefinition.md | 1 + docs/v1/FormulaAndFunctionResponseFormat.md | 1 + docs/v1/FreeTextWidgetDefinition.md | 1 + docs/v1/FreeTextWidgetDefinitionType.md | 1 + docs/v1/GCPAccount.md | 1 + docs/v1/GCPAccountListResponse.md | 1 + docs/v1/GCPIntegrationApi.md | 8 +++ docs/v1/GeomapWidgetDefinition.md | 1 + docs/v1/GeomapWidgetDefinitionStyle.md | 1 + docs/v1/GeomapWidgetDefinitionType.md | 1 + docs/v1/GeomapWidgetDefinitionView.md | 1 + docs/v1/GeomapWidgetRequest.md | 1 + docs/v1/GraphSnapshot.md | 1 + docs/v1/GroupWidgetDefinition.md | 1 + docs/v1/GroupWidgetDefinitionType.md | 1 + docs/v1/HTTPMethod.md | 1 + docs/v1/HeatMapWidgetDefinition.md | 1 + docs/v1/HeatMapWidgetDefinitionType.md | 1 + docs/v1/HeatMapWidgetRequest.md | 1 + docs/v1/Host.md | 1 + docs/v1/HostListResponse.md | 1 + docs/v1/HostMapRequest.md | 1 + docs/v1/HostMapWidgetDefinition.md | 1 + docs/v1/HostMapWidgetDefinitionRequests.md | 1 + docs/v1/HostMapWidgetDefinitionStyle.md | 1 + docs/v1/HostMapWidgetDefinitionType.md | 1 + docs/v1/HostMeta.md | 1 + docs/v1/HostMetrics.md | 1 + docs/v1/HostMuteResponse.md | 1 + docs/v1/HostMuteSettings.md | 1 + docs/v1/HostTags.md | 1 + docs/v1/HostTotals.md | 1 + docs/v1/HostsApi.md | 8 +++ docs/v1/IFrameWidgetDefinition.md | 1 + docs/v1/IFrameWidgetDefinitionType.md | 1 + docs/v1/IPPrefixesAPI.md | 1 + docs/v1/IPPrefixesAPM.md | 1 + docs/v1/IPPrefixesAgents.md | 1 + docs/v1/IPPrefixesLogs.md | 1 + docs/v1/IPPrefixesProcess.md | 1 + docs/v1/IPPrefixesSynthetics.md | 1 + docs/v1/IPPrefixesWebhooks.md | 1 + docs/v1/IPRanges.md | 1 + docs/v1/IPRangesApi.md | 2 + docs/v1/IdpFormData.md | 1 + docs/v1/IdpResponse.md | 1 + docs/v1/ImageWidgetDefinition.md | 1 + docs/v1/ImageWidgetDefinitionType.md | 1 + docs/v1/KeyManagementApi.md | 20 +++++++ docs/v1/Log.md | 1 + docs/v1/LogContent.md | 1 + docs/v1/LogQueryDefinition.md | 1 + docs/v1/LogQueryDefinitionGroupBy.md | 1 + docs/v1/LogQueryDefinitionGroupBySort.md | 1 + docs/v1/LogQueryDefinitionSearch.md | 1 + docs/v1/LogStreamWidgetDefinition.md | 1 + docs/v1/LogStreamWidgetDefinitionType.md | 1 + docs/v1/LogsAPIError.md | 1 + docs/v1/LogsAPIErrorResponse.md | 1 + docs/v1/LogsApi.md | 2 + docs/v1/LogsArithmeticProcessor.md | 1 + docs/v1/LogsArithmeticProcessorType.md | 1 + docs/v1/LogsAttributeRemapper.md | 1 + docs/v1/LogsAttributeRemapperType.md | 1 + docs/v1/LogsCategoryProcessor.md | 1 + docs/v1/LogsCategoryProcessorCategory.md | 1 + docs/v1/LogsCategoryProcessorType.md | 1 + docs/v1/LogsDateRemapper.md | 1 + docs/v1/LogsDateRemapperType.md | 1 + docs/v1/LogsExclusion.md | 1 + docs/v1/LogsExclusionFilter.md | 1 + docs/v1/LogsFilter.md | 1 + docs/v1/LogsGeoIPParser.md | 1 + docs/v1/LogsGeoIPParserType.md | 1 + docs/v1/LogsGrokParser.md | 1 + docs/v1/LogsGrokParserRules.md | 1 + docs/v1/LogsGrokParserType.md | 1 + docs/v1/LogsIndex.md | 1 + docs/v1/LogsIndexListResponse.md | 1 + docs/v1/LogsIndexUpdateRequest.md | 1 + docs/v1/LogsIndexesApi.md | 12 ++++ docs/v1/LogsIndexesOrder.md | 1 + docs/v1/LogsListRequest.md | 1 + docs/v1/LogsListRequestTime.md | 1 + docs/v1/LogsListResponse.md | 1 + docs/v1/LogsLookupProcessor.md | 1 + docs/v1/LogsLookupProcessorType.md | 1 + docs/v1/LogsMessageRemapper.md | 1 + docs/v1/LogsMessageRemapperType.md | 1 + docs/v1/LogsPipeline.md | 1 + docs/v1/LogsPipelineList.md | 1 + docs/v1/LogsPipelineProcessor.md | 1 + docs/v1/LogsPipelineProcessorType.md | 1 + docs/v1/LogsPipelinesApi.md | 14 +++++ docs/v1/LogsPipelinesOrder.md | 1 + docs/v1/LogsProcessor.md | 1 + docs/v1/LogsQueryCompute.md | 1 + docs/v1/LogsServiceRemapper.md | 1 + docs/v1/LogsServiceRemapperType.md | 1 + docs/v1/LogsSort.md | 1 + docs/v1/LogsStatusRemapper.md | 1 + docs/v1/LogsStatusRemapperType.md | 1 + docs/v1/LogsStringBuilderProcessor.md | 1 + docs/v1/LogsStringBuilderProcessorType.md | 1 + docs/v1/LogsTraceRemapper.md | 1 + docs/v1/LogsTraceRemapperType.md | 1 + docs/v1/LogsURLParser.md | 1 + docs/v1/LogsURLParserType.md | 1 + docs/v1/LogsUserAgentParser.md | 1 + docs/v1/LogsUserAgentParserType.md | 1 + docs/v1/MetricMetadata.md | 1 + docs/v1/MetricSearchResponse.md | 1 + docs/v1/MetricSearchResponseResults.md | 1 + docs/v1/MetricsApi.md | 10 ++++ docs/v1/MetricsListResponse.md | 1 + docs/v1/MetricsQueryMetadata.md | 1 + docs/v1/MetricsQueryResponse.md | 1 + docs/v1/MetricsQueryUnit.md | 1 + docs/v1/Monitor.md | 1 + docs/v1/MonitorDeviceID.md | 1 + docs/v1/MonitorOptions.md | 1 + docs/v1/MonitorOptionsAggregation.md | 1 + docs/v1/MonitorOverallStates.md | 1 + docs/v1/MonitorState.md | 1 + docs/v1/MonitorStateGroup.md | 1 + docs/v1/MonitorSummaryWidgetDefinition.md | 1 + docs/v1/MonitorSummaryWidgetDefinitionType.md | 1 + docs/v1/MonitorThresholdWindowOptions.md | 1 + docs/v1/MonitorThresholds.md | 1 + docs/v1/MonitorType.md | 1 + docs/v1/MonitorUpdateRequest.md | 1 + docs/v1/MonitorsApi.md | 14 +++++ docs/v1/NoteWidgetDefinition.md | 1 + docs/v1/NoteWidgetDefinitionType.md | 1 + docs/v1/Organization.md | 1 + docs/v1/OrganizationBilling.md | 1 + docs/v1/OrganizationCreateBody.md | 1 + docs/v1/OrganizationCreateResponse.md | 1 + docs/v1/OrganizationListResponse.md | 1 + docs/v1/OrganizationResponse.md | 1 + docs/v1/OrganizationSettings.md | 1 + docs/v1/OrganizationSettingsSaml.md | 1 + ...ationSettingsSamlAutocreateUsersDomains.md | 1 + ...ganizationSettingsSamlIdpInitiatedLogin.md | 1 + docs/v1/OrganizationSettingsSamlStrictMode.md | 1 + docs/v1/OrganizationSubscription.md | 1 + docs/v1/OrganizationsApi.md | 10 ++++ docs/v1/PagerDutyIntegrationApi.md | 8 +++ docs/v1/PagerDutyService.md | 1 + docs/v1/PagerDutyServiceKey.md | 1 + docs/v1/PagerDutyServiceName.md | 1 + docs/v1/Point.md | 1 + docs/v1/ProcessQueryDefinition.md | 1 + docs/v1/QuerySortOrder.md | 1 + docs/v1/QueryValueWidgetDefinition.md | 1 + docs/v1/QueryValueWidgetDefinitionType.md | 1 + docs/v1/QueryValueWidgetRequest.md | 1 + docs/v1/SLOBulkDelete.md | 1 + docs/v1/SLOBulkDeleteError.md | 1 + docs/v1/SLOBulkDeleteResponse.md | 1 + docs/v1/SLOBulkDeleteResponseData.md | 1 + docs/v1/SLOCorrection.md | 1 + docs/v1/SLOCorrectionCategory.md | 1 + docs/v1/SLOCorrectionCreateData.md | 1 + docs/v1/SLOCorrectionCreateRequest.md | 1 + .../SLOCorrectionCreateRequestAttributes.md | 1 + docs/v1/SLOCorrectionListResponse.md | 1 + docs/v1/SLOCorrectionResponse.md | 1 + docs/v1/SLOCorrectionResponseAttributes.md | 1 + docs/v1/SLOCorrectionType.md | 1 + docs/v1/SLOCorrectionUpdateData.md | 1 + docs/v1/SLOCorrectionUpdateRequest.md | 1 + .../SLOCorrectionUpdateRequestAttributes.md | 1 + docs/v1/SLODeleteResponse.md | 1 + docs/v1/SLOErrorBudgetRemainingData.md | 1 + docs/v1/SLOErrorTimeframe.md | 1 + docs/v1/SLOHistoryMetrics.md | 1 + docs/v1/SLOHistoryMetricsSeries.md | 1 + docs/v1/SLOHistoryMetricsSeriesMetadata.md | 1 + .../v1/SLOHistoryMetricsSeriesMetadataUnit.md | 1 + docs/v1/SLOHistoryResponse.md | 1 + docs/v1/SLOHistoryResponseData.md | 1 + docs/v1/SLOHistoryResponseError.md | 1 + docs/v1/SLOHistorySLIData.md | 1 + docs/v1/SLOListResponse.md | 1 + docs/v1/SLOResponse.md | 1 + docs/v1/SLOThreshold.md | 1 + docs/v1/SLOTimeframe.md | 1 + docs/v1/SLOType.md | 1 + docs/v1/SLOTypeNumeric.md | 1 + docs/v1/SLOWidgetDefinition.md | 1 + docs/v1/SLOWidgetDefinitionType.md | 1 + docs/v1/ScatterPlotRequest.md | 1 + docs/v1/ScatterPlotWidgetDefinition.md | 1 + .../v1/ScatterPlotWidgetDefinitionRequests.md | 1 + docs/v1/ScatterPlotWidgetDefinitionType.md | 1 + docs/v1/ServiceLevelObjective.md | 1 + .../v1/ServiceLevelObjectiveCorrectionsApi.md | 10 ++++ docs/v1/ServiceLevelObjectiveQuery.md | 1 + docs/v1/ServiceLevelObjectiveRequest.md | 1 + docs/v1/ServiceLevelObjectivesApi.md | 16 +++++ docs/v1/ServiceMapWidgetDefinition.md | 1 + docs/v1/ServiceMapWidgetDefinitionType.md | 1 + docs/v1/ServiceSummaryWidgetDefinition.md | 1 + docs/v1/ServiceSummaryWidgetDefinitionType.md | 1 + docs/v1/SlackIntegrationApi.md | 10 ++++ docs/v1/SlackIntegrationChannel.md | 1 + docs/v1/SlackIntegrationChannelDisplay.md | 1 + docs/v1/SlackIntegrationChannels.md | 1 + docs/v1/SnapshotsApi.md | 2 + docs/v1/SyntheticsAPIStep.md | 1 + docs/v1/SyntheticsAPIStepSubtype.md | 1 + docs/v1/SyntheticsAPITest.md | 1 + docs/v1/SyntheticsAPITestConfig.md | 1 + docs/v1/SyntheticsAPITestResultData.md | 1 + docs/v1/SyntheticsAPITestResultFull.md | 1 + docs/v1/SyntheticsAPITestResultFullCheck.md | 1 + docs/v1/SyntheticsAPITestResultShort.md | 1 + docs/v1/SyntheticsAPITestResultShortResult.md | 1 + docs/v1/SyntheticsAPITestType.md | 1 + docs/v1/SyntheticsApi.md | 50 ++++++++++++++++ docs/v1/SyntheticsAssertion.md | 1 + .../v1/SyntheticsAssertionJSONPathOperator.md | 1 + docs/v1/SyntheticsAssertionJSONPathTarget.md | 1 + ...SyntheticsAssertionJSONPathTargetTarget.md | 1 + docs/v1/SyntheticsAssertionOperator.md | 1 + docs/v1/SyntheticsAssertionTarget.md | 1 + docs/v1/SyntheticsAssertionType.md | 1 + docs/v1/SyntheticsBasicAuth.md | 1 + docs/v1/SyntheticsBrowserError.md | 1 + docs/v1/SyntheticsBrowserErrorType.md | 1 + docs/v1/SyntheticsBrowserTest.md | 1 + docs/v1/SyntheticsBrowserTestConfig.md | 1 + docs/v1/SyntheticsBrowserTestResultData.md | 1 + docs/v1/SyntheticsBrowserTestResultFull.md | 1 + .../SyntheticsBrowserTestResultFullCheck.md | 1 + docs/v1/SyntheticsBrowserTestResultShort.md | 1 + .../SyntheticsBrowserTestResultShortResult.md | 1 + docs/v1/SyntheticsBrowserTestType.md | 1 + docs/v1/SyntheticsBrowserVariable.md | 1 + docs/v1/SyntheticsBrowserVariableType.md | 1 + docs/v1/SyntheticsCITest.md | 1 + docs/v1/SyntheticsCITestBody.md | 1 + docs/v1/SyntheticsCITestMetadata.md | 1 + docs/v1/SyntheticsCITestMetadataCi.md | 1 + docs/v1/SyntheticsCITestMetadataGit.md | 1 + docs/v1/SyntheticsCheckType.md | 1 + docs/v1/SyntheticsConfigVariable.md | 1 + docs/v1/SyntheticsConfigVariableType.md | 1 + docs/v1/SyntheticsCoreWebVitals.md | 1 + docs/v1/SyntheticsDeleteTestsPayload.md | 1 + docs/v1/SyntheticsDeleteTestsResponse.md | 1 + docs/v1/SyntheticsDeletedTest.md | 1 + docs/v1/SyntheticsDevice.md | 1 + docs/v1/SyntheticsDeviceID.md | 1 + docs/v1/SyntheticsErrorCode.md | 1 + ...ntheticsGetAPITestLatestResultsResponse.md | 1 + ...ticsGetBrowserTestLatestResultsResponse.md | 1 + docs/v1/SyntheticsGlobalVariable.md | 1 + ...yntheticsGlobalVariableParseTestOptions.md | 1 + ...eticsGlobalVariableParseTestOptionsType.md | 1 + docs/v1/SyntheticsGlobalVariableParserType.md | 1 + docs/v1/SyntheticsGlobalVariableValue.md | 1 + docs/v1/SyntheticsListTestsResponse.md | 1 + docs/v1/SyntheticsLocation.md | 1 + docs/v1/SyntheticsLocations.md | 1 + docs/v1/SyntheticsParsingOptions.md | 1 + docs/v1/SyntheticsPlayingTab.md | 1 + docs/v1/SyntheticsPrivateLocation.md | 1 + ...ntheticsPrivateLocationCreationResponse.md | 1 + ...ocationCreationResponseResultEncryption.md | 1 + docs/v1/SyntheticsPrivateLocationSecrets.md | 1 + ...icsPrivateLocationSecretsAuthentication.md | 1 + ...sPrivateLocationSecretsConfigDecryption.md | 1 + docs/v1/SyntheticsSSLCertificate.md | 1 + docs/v1/SyntheticsSSLCertificateIssuer.md | 1 + docs/v1/SyntheticsSSLCertificateSubject.md | 1 + docs/v1/SyntheticsStep.md | 1 + docs/v1/SyntheticsStepDetail.md | 1 + docs/v1/SyntheticsStepDetailWarning.md | 1 + docs/v1/SyntheticsStepType.md | 1 + docs/v1/SyntheticsTestConfig.md | 1 + docs/v1/SyntheticsTestDetails.md | 1 + docs/v1/SyntheticsTestDetailsSubType.md | 1 + docs/v1/SyntheticsTestDetailsType.md | 1 + docs/v1/SyntheticsTestHeaders.md | 1 + docs/v1/SyntheticsTestMonitorStatus.md | 1 + docs/v1/SyntheticsTestOptions.md | 1 + .../v1/SyntheticsTestOptionsMonitorOptions.md | 1 + docs/v1/SyntheticsTestOptionsRetry.md | 1 + docs/v1/SyntheticsTestPauseStatus.md | 1 + docs/v1/SyntheticsTestProcessStatus.md | 1 + docs/v1/SyntheticsTestRequest.md | 1 + docs/v1/SyntheticsTestRequestCertificate.md | 1 + .../SyntheticsTestRequestCertificateItem.md | 1 + docs/v1/SyntheticsTickInterval.md | 1 + docs/v1/SyntheticsTiming.md | 1 + docs/v1/SyntheticsTriggerCITestLocation.md | 1 + docs/v1/SyntheticsTriggerCITestRunResult.md | 1 + docs/v1/SyntheticsTriggerCITestsResponse.md | 1 + .../SyntheticsUpdateTestPauseStatusPayload.md | 1 + docs/v1/SyntheticsVariableParser.md | 1 + docs/v1/SyntheticsWarningType.md | 1 + docs/v1/TableWidgetCellDisplayMode.md | 1 + docs/v1/TableWidgetDefinition.md | 1 + docs/v1/TableWidgetDefinitionType.md | 1 + docs/v1/TableWidgetHasSearchBar.md | 1 + docs/v1/TableWidgetRequest.md | 1 + docs/v1/TagToHosts.md | 1 + docs/v1/TagsApi.md | 10 ++++ docs/v1/TargetFormatType.md | 1 + docs/v1/TimeseriesWidgetDefinition.md | 1 + docs/v1/TimeseriesWidgetDefinitionType.md | 1 + docs/v1/TimeseriesWidgetExpressionAlias.md | 1 + docs/v1/TimeseriesWidgetLegendColumn.md | 1 + docs/v1/TimeseriesWidgetLegendLayout.md | 1 + docs/v1/TimeseriesWidgetRequest.md | 1 + docs/v1/ToplistWidgetDefinition.md | 1 + docs/v1/ToplistWidgetDefinitionType.md | 1 + docs/v1/ToplistWidgetRequest.md | 1 + docs/v1/UsageAnalyzedLogsHour.md | 1 + docs/v1/UsageAnalyzedLogsResponse.md | 1 + docs/v1/UsageAttributionAggregates.md | 1 + docs/v1/UsageAttributionAggregatesBody.md | 1 + docs/v1/UsageAttributionBody.md | 1 + docs/v1/UsageAttributionMetadata.md | 1 + docs/v1/UsageAttributionPagination.md | 1 + docs/v1/UsageAttributionResponse.md | 1 + docs/v1/UsageAttributionSort.md | 1 + docs/v1/UsageAttributionTagNames.md | 1 + docs/v1/UsageAttributionValues.md | 1 + docs/v1/UsageBillableSummaryBody.md | 1 + docs/v1/UsageBillableSummaryHour.md | 1 + docs/v1/UsageBillableSummaryKeys.md | 1 + docs/v1/UsageBillableSummaryResponse.md | 1 + docs/v1/UsageCustomReportsAttributes.md | 1 + docs/v1/UsageCustomReportsData.md | 1 + docs/v1/UsageCustomReportsMeta.md | 1 + docs/v1/UsageCustomReportsPage.md | 1 + docs/v1/UsageCustomReportsResponse.md | 1 + docs/v1/UsageFargateHour.md | 1 + docs/v1/UsageFargateResponse.md | 1 + docs/v1/UsageHostHour.md | 1 + docs/v1/UsageHostsResponse.md | 1 + docs/v1/UsageIncidentManagementHour.md | 1 + docs/v1/UsageIncidentManagementResponse.md | 1 + docs/v1/UsageIndexedSpansHour.md | 1 + docs/v1/UsageIndexedSpansResponse.md | 1 + docs/v1/UsageIngestedSpansHour.md | 1 + docs/v1/UsageIngestedSpansResponse.md | 1 + docs/v1/UsageIoTHour.md | 1 + docs/v1/UsageIoTResponse.md | 1 + docs/v1/UsageLambdaHour.md | 1 + docs/v1/UsageLambdaResponse.md | 1 + docs/v1/UsageLogsByIndexHour.md | 1 + docs/v1/UsageLogsByIndexResponse.md | 1 + docs/v1/UsageLogsHour.md | 1 + docs/v1/UsageLogsResponse.md | 1 + docs/v1/UsageMeteringApi.md | 58 +++++++++++++++++++ docs/v1/UsageMetricCategory.md | 1 + docs/v1/UsageNetworkFlowsHour.md | 1 + docs/v1/UsageNetworkFlowsResponse.md | 1 + docs/v1/UsageNetworkHostsHour.md | 1 + docs/v1/UsageNetworkHostsResponse.md | 1 + docs/v1/UsageProfilingHour.md | 1 + docs/v1/UsageProfilingResponse.md | 1 + docs/v1/UsageReportsType.md | 1 + docs/v1/UsageRumSessionsHour.md | 1 + docs/v1/UsageRumSessionsResponse.md | 1 + docs/v1/UsageSNMPHour.md | 1 + docs/v1/UsageSNMPResponse.md | 1 + docs/v1/UsageSort.md | 1 + docs/v1/UsageSortDirection.md | 1 + .../UsageSpecifiedCustomReportsAttributes.md | 1 + docs/v1/UsageSpecifiedCustomReportsData.md | 1 + docs/v1/UsageSpecifiedCustomReportsMeta.md | 1 + docs/v1/UsageSpecifiedCustomReportsPage.md | 1 + .../v1/UsageSpecifiedCustomReportsResponse.md | 1 + docs/v1/UsageSummaryDate.md | 1 + docs/v1/UsageSummaryDateOrg.md | 1 + docs/v1/UsageSummaryResponse.md | 1 + docs/v1/UsageSyntheticsAPIHour.md | 1 + docs/v1/UsageSyntheticsAPIResponse.md | 1 + docs/v1/UsageSyntheticsBrowserHour.md | 1 + docs/v1/UsageSyntheticsBrowserResponse.md | 1 + docs/v1/UsageSyntheticsHour.md | 1 + docs/v1/UsageSyntheticsResponse.md | 1 + docs/v1/UsageTimeseriesHour.md | 1 + docs/v1/UsageTimeseriesResponse.md | 1 + docs/v1/UsageTopAvgMetricsHour.md | 1 + docs/v1/UsageTopAvgMetricsResponse.md | 1 + docs/v1/UsageTraceHour.md | 1 + docs/v1/UsageTraceResponse.md | 1 + docs/v1/UsageTracingWithoutLimitsHour.md | 1 + docs/v1/UsageTracingWithoutLimitsResponse.md | 1 + docs/v1/User.md | 1 + docs/v1/UserDisableResponse.md | 1 + docs/v1/UserListResponse.md | 1 + docs/v1/UserResponse.md | 1 + docs/v1/UsersApi.md | 10 ++++ docs/v1/Widget.md | 1 + docs/v1/WidgetAggregator.md | 1 + docs/v1/WidgetAxis.md | 1 + docs/v1/WidgetChangeType.md | 1 + docs/v1/WidgetColorPreference.md | 1 + docs/v1/WidgetComparator.md | 1 + docs/v1/WidgetCompareTo.md | 1 + docs/v1/WidgetConditionalFormat.md | 1 + docs/v1/WidgetCustomLink.md | 1 + docs/v1/WidgetDefinition.md | 1 + docs/v1/WidgetDisplayType.md | 1 + docs/v1/WidgetEvent.md | 1 + docs/v1/WidgetEventSize.md | 1 + docs/v1/WidgetFieldSort.md | 1 + docs/v1/WidgetFormula.md | 1 + docs/v1/WidgetFormulaLimit.md | 1 + docs/v1/WidgetGrouping.md | 1 + docs/v1/WidgetImageSizing.md | 1 + docs/v1/WidgetLayout.md | 1 + docs/v1/WidgetLayoutType.md | 1 + docs/v1/WidgetLineType.md | 1 + docs/v1/WidgetLineWidth.md | 1 + docs/v1/WidgetLiveSpan.md | 1 + docs/v1/WidgetMargin.md | 1 + docs/v1/WidgetMarker.md | 1 + docs/v1/WidgetMessageDisplay.md | 1 + docs/v1/WidgetMonitorSummaryDisplayFormat.md | 1 + docs/v1/WidgetMonitorSummarySort.md | 1 + docs/v1/WidgetNodeType.md | 1 + docs/v1/WidgetOrderBy.md | 1 + docs/v1/WidgetPalette.md | 1 + docs/v1/WidgetRequestStyle.md | 1 + docs/v1/WidgetServiceSummaryDisplayFormat.md | 1 + docs/v1/WidgetSizeFormat.md | 1 + docs/v1/WidgetSort.md | 1 + docs/v1/WidgetStyle.md | 1 + docs/v1/WidgetSummaryType.md | 1 + docs/v1/WidgetTextAlign.md | 1 + docs/v1/WidgetTickEdge.md | 1 + docs/v1/WidgetTime.md | 1 + docs/v1/WidgetTimeWindows.md | 1 + docs/v1/WidgetViewMode.md | 1 + docs/v1/WidgetVizType.md | 1 + docs/v2/APIErrorResponse.md | 1 + docs/v2/APIKeyCreateAttributes.md | 1 + docs/v2/APIKeyCreateData.md | 1 + docs/v2/APIKeyCreateRequest.md | 1 + docs/v2/APIKeyRelationships.md | 1 + docs/v2/APIKeyResponse.md | 1 + docs/v2/APIKeyResponseIncludedItem.md | 1 + docs/v2/APIKeyUpdateAttributes.md | 1 + docs/v2/APIKeyUpdateData.md | 1 + docs/v2/APIKeyUpdateRequest.md | 1 + docs/v2/APIKeysResponse.md | 1 + docs/v2/APIKeysSort.md | 1 + docs/v2/APIKeysType.md | 1 + docs/v2/ApplicationKeyCreateAttributes.md | 1 + docs/v2/ApplicationKeyCreateData.md | 1 + docs/v2/ApplicationKeyCreateRequest.md | 1 + docs/v2/ApplicationKeyRelationships.md | 1 + docs/v2/ApplicationKeyResponse.md | 1 + docs/v2/ApplicationKeyResponseIncludedItem.md | 1 + docs/v2/ApplicationKeyUpdateAttributes.md | 1 + docs/v2/ApplicationKeyUpdateData.md | 1 + docs/v2/ApplicationKeyUpdateRequest.md | 1 + docs/v2/ApplicationKeysSort.md | 1 + docs/v2/ApplicationKeysType.md | 1 + docs/v2/Creator.md | 1 + docs/v2/DashboardListAddItemsRequest.md | 1 + docs/v2/DashboardListAddItemsResponse.md | 1 + docs/v2/DashboardListDeleteItemsRequest.md | 1 + docs/v2/DashboardListDeleteItemsResponse.md | 1 + docs/v2/DashboardListItem.md | 1 + docs/v2/DashboardListItemRequest.md | 1 + docs/v2/DashboardListItemResponse.md | 1 + docs/v2/DashboardListItems.md | 1 + docs/v2/DashboardListUpdateItemsRequest.md | 1 + docs/v2/DashboardListUpdateItemsResponse.md | 1 + docs/v2/DashboardListsApi.md | 8 +++ docs/v2/DashboardType.md | 1 + docs/v2/FullAPIKey.md | 1 + docs/v2/FullAPIKeyAttributes.md | 1 + docs/v2/FullApplicationKey.md | 1 + docs/v2/FullApplicationKeyAttributes.md | 1 + docs/v2/IncidentCreateAttributes.md | 1 + docs/v2/IncidentCreateData.md | 1 + docs/v2/IncidentCreateRelationships.md | 1 + docs/v2/IncidentCreateRequest.md | 1 + docs/v2/IncidentFieldAttributes.md | 1 + .../IncidentFieldAttributesMultipleValue.md | 1 + docs/v2/IncidentFieldAttributesSingleValue.md | 1 + .../IncidentFieldAttributesSingleValueType.md | 1 + docs/v2/IncidentFieldAttributesValueType.md | 1 + docs/v2/IncidentIntegrationMetadataType.md | 1 + docs/v2/IncidentPostmortemType.md | 1 + docs/v2/IncidentRelatedObject.md | 1 + docs/v2/IncidentResponse.md | 1 + docs/v2/IncidentResponseAttributes.md | 1 + docs/v2/IncidentResponseData.md | 1 + docs/v2/IncidentResponseIncludedItem.md | 1 + docs/v2/IncidentResponseRelationships.md | 1 + docs/v2/IncidentServiceCreateAttributes.md | 1 + docs/v2/IncidentServiceCreateData.md | 1 + docs/v2/IncidentServiceCreateRequest.md | 1 + docs/v2/IncidentServiceIncludedItems.md | 1 + docs/v2/IncidentServiceRelationships.md | 1 + docs/v2/IncidentServiceResponse.md | 1 + docs/v2/IncidentServiceResponseAttributes.md | 1 + docs/v2/IncidentServiceResponseData.md | 1 + docs/v2/IncidentServiceType.md | 1 + docs/v2/IncidentServiceUpdateAttributes.md | 1 + docs/v2/IncidentServiceUpdateData.md | 1 + docs/v2/IncidentServiceUpdateRequest.md | 1 + docs/v2/IncidentServicesApi.md | 10 ++++ docs/v2/IncidentServicesResponse.md | 1 + docs/v2/IncidentServicesResponseMeta.md | 1 + .../IncidentServicesResponseMetaPagination.md | 1 + docs/v2/IncidentTeamCreateAttributes.md | 1 + docs/v2/IncidentTeamCreateData.md | 1 + docs/v2/IncidentTeamCreateRequest.md | 1 + docs/v2/IncidentTeamIncludedItems.md | 1 + docs/v2/IncidentTeamRelationships.md | 1 + docs/v2/IncidentTeamResponse.md | 1 + docs/v2/IncidentTeamResponseAttributes.md | 1 + docs/v2/IncidentTeamResponseData.md | 1 + docs/v2/IncidentTeamType.md | 1 + docs/v2/IncidentTeamUpdateAttributes.md | 1 + docs/v2/IncidentTeamUpdateData.md | 1 + docs/v2/IncidentTeamUpdateRequest.md | 1 + docs/v2/IncidentTeamsApi.md | 10 ++++ docs/v2/IncidentTeamsResponse.md | 1 + .../IncidentTimelineCellCreateAttributes.md | 1 + ...IncidentTimelineCellMarkdownContentType.md | 1 + ...entTimelineCellMarkdownCreateAttributes.md | 1 + ...lineCellMarkdownCreateAttributesContent.md | 1 + docs/v2/IncidentType.md | 1 + docs/v2/IncidentUpdateAttributes.md | 1 + docs/v2/IncidentUpdateData.md | 1 + docs/v2/IncidentUpdateRelationships.md | 1 + docs/v2/IncidentUpdateRequest.md | 1 + docs/v2/IncidentsApi.md | 10 ++++ docs/v2/IncidentsResponse.md | 1 + docs/v2/KeyManagementApi.md | 26 +++++++++ docs/v2/ListApplicationKeysResponse.md | 1 + docs/v2/Log.md | 1 + docs/v2/LogAttributes.md | 1 + docs/v2/LogType.md | 1 + docs/v2/LogsAggregateBucket.md | 1 + docs/v2/LogsAggregateBucketValue.md | 1 + docs/v2/LogsAggregateBucketValueTimeseries.md | 1 + ...LogsAggregateBucketValueTimeseriesPoint.md | 1 + docs/v2/LogsAggregateRequest.md | 1 + docs/v2/LogsAggregateRequestPage.md | 1 + docs/v2/LogsAggregateResponse.md | 1 + docs/v2/LogsAggregateResponseData.md | 1 + docs/v2/LogsAggregateResponseStatus.md | 1 + docs/v2/LogsAggregateSort.md | 1 + docs/v2/LogsAggregateSortType.md | 1 + docs/v2/LogsAggregationFunction.md | 1 + docs/v2/LogsApi.md | 6 ++ docs/v2/LogsArchive.md | 1 + docs/v2/LogsArchiveAttributes.md | 1 + docs/v2/LogsArchiveCreateRequest.md | 1 + docs/v2/LogsArchiveCreateRequestAttributes.md | 1 + docs/v2/LogsArchiveCreateRequestDefinition.md | 1 + .../v2/LogsArchiveCreateRequestDestination.md | 1 + docs/v2/LogsArchiveDefinition.md | 1 + docs/v2/LogsArchiveDestination.md | 1 + docs/v2/LogsArchiveDestinationAzure.md | 1 + docs/v2/LogsArchiveDestinationAzureType.md | 1 + docs/v2/LogsArchiveDestinationGCS.md | 1 + docs/v2/LogsArchiveDestinationGCSType.md | 1 + docs/v2/LogsArchiveDestinationS3.md | 1 + docs/v2/LogsArchiveDestinationS3Type.md | 1 + docs/v2/LogsArchiveIntegrationAzure.md | 1 + docs/v2/LogsArchiveIntegrationGCS.md | 1 + docs/v2/LogsArchiveIntegrationS3.md | 1 + docs/v2/LogsArchiveOrder.md | 1 + docs/v2/LogsArchiveOrderAttributes.md | 1 + docs/v2/LogsArchiveOrderDefinition.md | 1 + docs/v2/LogsArchiveOrderDefinitionType.md | 1 + docs/v2/LogsArchiveState.md | 1 + docs/v2/LogsArchives.md | 1 + docs/v2/LogsArchivesApi.md | 20 +++++++ docs/v2/LogsCompute.md | 1 + docs/v2/LogsComputeType.md | 1 + docs/v2/LogsGroupBy.md | 1 + docs/v2/LogsGroupByHistogram.md | 1 + docs/v2/LogsGroupByMissing.md | 1 + docs/v2/LogsGroupByTotal.md | 1 + docs/v2/LogsListRequest.md | 1 + docs/v2/LogsListRequestPage.md | 1 + docs/v2/LogsListResponse.md | 1 + docs/v2/LogsListResponseLinks.md | 1 + docs/v2/LogsMetricCompute.md | 1 + docs/v2/LogsMetricComputeAggregationType.md | 1 + docs/v2/LogsMetricCreateAttributes.md | 1 + docs/v2/LogsMetricCreateData.md | 1 + docs/v2/LogsMetricCreateRequest.md | 1 + docs/v2/LogsMetricFilter.md | 1 + docs/v2/LogsMetricGroupBy.md | 1 + docs/v2/LogsMetricResponse.md | 1 + docs/v2/LogsMetricResponseAttributes.md | 1 + docs/v2/LogsMetricResponseCompute.md | 1 + ...ogsMetricResponseComputeAggregationType.md | 1 + docs/v2/LogsMetricResponseData.md | 1 + docs/v2/LogsMetricResponseFilter.md | 1 + docs/v2/LogsMetricResponseGroupBy.md | 1 + docs/v2/LogsMetricType.md | 1 + docs/v2/LogsMetricUpdateAttributes.md | 1 + docs/v2/LogsMetricUpdateData.md | 1 + docs/v2/LogsMetricUpdateRequest.md | 1 + docs/v2/LogsMetricsApi.md | 10 ++++ docs/v2/LogsMetricsResponse.md | 1 + docs/v2/LogsQueryFilter.md | 1 + docs/v2/LogsQueryOptions.md | 1 + docs/v2/LogsResponseMetadata.md | 1 + docs/v2/LogsResponseMetadataPage.md | 1 + docs/v2/LogsSort.md | 1 + docs/v2/LogsSortOrder.md | 1 + docs/v2/LogsWarning.md | 1 + docs/v2/Metric.md | 1 + docs/v2/MetricAllTags.md | 1 + docs/v2/MetricAllTagsAttributes.md | 1 + docs/v2/MetricAllTagsResponse.md | 1 + docs/v2/MetricDistinctVolume.md | 1 + docs/v2/MetricDistinctVolumeAttributes.md | 1 + docs/v2/MetricDistinctVolumeType.md | 1 + docs/v2/MetricIngestedIndexedVolume.md | 1 + .../MetricIngestedIndexedVolumeAttributes.md | 1 + docs/v2/MetricIngestedIndexedVolumeType.md | 1 + docs/v2/MetricTagConfiguration.md | 1 + docs/v2/MetricTagConfigurationAttributes.md | 1 + .../MetricTagConfigurationCreateAttributes.md | 1 + docs/v2/MetricTagConfigurationCreateData.md | 1 + .../v2/MetricTagConfigurationCreateRequest.md | 1 + docs/v2/MetricTagConfigurationMetricTypes.md | 1 + docs/v2/MetricTagConfigurationResponse.md | 1 + docs/v2/MetricTagConfigurationType.md | 1 + .../MetricTagConfigurationUpdateAttributes.md | 1 + docs/v2/MetricTagConfigurationUpdateData.md | 1 + .../v2/MetricTagConfigurationUpdateRequest.md | 1 + docs/v2/MetricType.md | 1 + docs/v2/MetricVolumes.md | 1 + docs/v2/MetricVolumesResponse.md | 1 + docs/v2/MetricsAndMetricTagConfigurations.md | 1 + ...tricsAndMetricTagConfigurationsResponse.md | 1 + docs/v2/MetricsApi.md | 14 +++++ docs/v2/Organization.md | 1 + docs/v2/OrganizationAttributes.md | 1 + docs/v2/OrganizationsType.md | 1 + docs/v2/Pagination.md | 1 + docs/v2/PartialAPIKey.md | 1 + docs/v2/PartialAPIKeyAttributes.md | 1 + docs/v2/PartialApplicationKey.md | 1 + docs/v2/PartialApplicationKeyAttributes.md | 1 + docs/v2/Permission.md | 1 + docs/v2/PermissionAttributes.md | 1 + docs/v2/PermissionsResponse.md | 1 + docs/v2/PermissionsType.md | 1 + docs/v2/ProcessSummariesMeta.md | 1 + docs/v2/ProcessSummariesMetaPage.md | 1 + docs/v2/ProcessSummariesResponse.md | 1 + docs/v2/ProcessSummary.md | 1 + docs/v2/ProcessSummaryAttributes.md | 1 + docs/v2/ProcessSummaryType.md | 1 + docs/v2/ProcessesApi.md | 2 + docs/v2/QuerySortOrder.md | 1 + ...onshipToIncidentIntegrationMetadataData.md | 1 + ...ationshipToIncidentIntegrationMetadatas.md | 1 + docs/v2/RelationshipToIncidentPostmortem.md | 1 + .../RelationshipToIncidentPostmortemData.md | 1 + docs/v2/RelationshipToOrganization.md | 1 + docs/v2/RelationshipToOrganizationData.md | 1 + docs/v2/RelationshipToOrganizations.md | 1 + docs/v2/RelationshipToPermission.md | 1 + docs/v2/RelationshipToPermissionData.md | 1 + docs/v2/RelationshipToPermissions.md | 1 + docs/v2/RelationshipToRole.md | 1 + docs/v2/RelationshipToRoleData.md | 1 + docs/v2/RelationshipToRoles.md | 1 + docs/v2/RelationshipToUser.md | 1 + docs/v2/RelationshipToUserData.md | 1 + docs/v2/RelationshipToUsers.md | 1 + docs/v2/ResponseMetaAttributes.md | 1 + docs/v2/Role.md | 1 + docs/v2/RoleAttributes.md | 1 + docs/v2/RoleCreateAttributes.md | 1 + docs/v2/RoleCreateData.md | 1 + docs/v2/RoleCreateRequest.md | 1 + docs/v2/RoleCreateResponse.md | 1 + docs/v2/RoleCreateResponseData.md | 1 + docs/v2/RoleRelationships.md | 1 + docs/v2/RoleResponse.md | 1 + docs/v2/RoleResponseRelationships.md | 1 + docs/v2/RoleUpdateAttributes.md | 1 + docs/v2/RoleUpdateData.md | 1 + docs/v2/RoleUpdateRequest.md | 1 + docs/v2/RoleUpdateResponse.md | 1 + docs/v2/RoleUpdateResponseData.md | 1 + docs/v2/RolesApi.md | 24 ++++++++ docs/v2/RolesResponse.md | 1 + docs/v2/RolesSort.md | 1 + docs/v2/RolesType.md | 1 + docs/v2/SecurityMonitoringApi.md | 14 +++++ docs/v2/SecurityMonitoringFilter.md | 1 + docs/v2/SecurityMonitoringFilterAction.md | 1 + .../v2/SecurityMonitoringListRulesResponse.md | 1 + docs/v2/SecurityMonitoringRuleCase.md | 1 + docs/v2/SecurityMonitoringRuleCaseCreate.md | 1 + .../v2/SecurityMonitoringRuleCreatePayload.md | 1 + .../SecurityMonitoringRuleDetectionMethod.md | 1 + .../SecurityMonitoringRuleEvaluationWindow.md | 1 + docs/v2/SecurityMonitoringRuleKeepAlive.md | 1 + ...SecurityMonitoringRuleMaxSignalDuration.md | 1 + .../SecurityMonitoringRuleNewValueOptions.md | 1 + ...onitoringRuleNewValueOptionsForgetAfter.md | 1 + ...ringRuleNewValueOptionsLearningDuration.md | 1 + docs/v2/SecurityMonitoringRuleOptions.md | 1 + docs/v2/SecurityMonitoringRuleQuery.md | 1 + .../SecurityMonitoringRuleQueryAggregation.md | 1 + docs/v2/SecurityMonitoringRuleQueryCreate.md | 1 + docs/v2/SecurityMonitoringRuleResponse.md | 1 + docs/v2/SecurityMonitoringRuleSeverity.md | 1 + .../v2/SecurityMonitoringRuleUpdatePayload.md | 1 + docs/v2/SecurityMonitoringSignal.md | 1 + docs/v2/SecurityMonitoringSignalAttributes.md | 1 + .../v2/SecurityMonitoringSignalListRequest.md | 1 + ...curityMonitoringSignalListRequestFilter.md | 1 + ...SecurityMonitoringSignalListRequestPage.md | 1 + docs/v2/SecurityMonitoringSignalType.md | 1 + .../SecurityMonitoringSignalsListResponse.md | 1 + ...urityMonitoringSignalsListResponseLinks.md | 1 + ...curityMonitoringSignalsListResponseMeta.md | 1 + ...tyMonitoringSignalsListResponseMetaPage.md | 1 + docs/v2/SecurityMonitoringSignalsSort.md | 1 + docs/v2/User.md | 1 + docs/v2/UserAttributes.md | 1 + docs/v2/UserCreateAttributes.md | 1 + docs/v2/UserCreateData.md | 1 + docs/v2/UserCreateRequest.md | 1 + docs/v2/UserInvitationData.md | 1 + docs/v2/UserInvitationDataAttributes.md | 1 + docs/v2/UserInvitationRelationships.md | 1 + docs/v2/UserInvitationResponse.md | 1 + docs/v2/UserInvitationResponseData.md | 1 + docs/v2/UserInvitationsRequest.md | 1 + docs/v2/UserInvitationsResponse.md | 1 + docs/v2/UserInvitationsType.md | 1 + docs/v2/UserRelationships.md | 1 + docs/v2/UserResponse.md | 1 + docs/v2/UserResponseIncludedItem.md | 1 + docs/v2/UserResponseRelationships.md | 1 + docs/v2/UserUpdateAttributes.md | 1 + docs/v2/UserUpdateData.md | 1 + docs/v2/UserUpdateRequest.md | 1 + docs/v2/UsersApi.md | 18 ++++++ docs/v2/UsersResponse.md | 1 + docs/v2/UsersType.md | 1 + 852 files changed, 1341 insertions(+), 4 deletions(-) diff --git a/.apigentools-info b/.apigentools-info index d28740bc1a..3ff7ef38e9 100644 --- a/.apigentools-info +++ b/.apigentools-info @@ -4,13 +4,13 @@ "spec_versions": { "v1": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:52:34.560111", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:02:46.709774", + "spec_repo_commit": "7e667f1" }, "v2": { "apigentools_version": "1.4.1.dev6", - "regenerated": "2021-03-23 10:53:14.043922", - "spec_repo_commit": "34cf37f" + "regenerated": "2021-03-23 14:03:25.204186", + "spec_repo_commit": "7e667f1" } } } \ No newline at end of file diff --git a/docs/v1/APIErrorResponse.md b/docs/v1/APIErrorResponse.md index d4b0f118e6..ad0fdede58 100644 --- a/docs/v1/APIErrorResponse.md +++ b/docs/v1/APIErrorResponse.md @@ -1,6 +1,7 @@ # APIErrorResponse Error response object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSAccount.md b/docs/v1/AWSAccount.md index c8db243d6a..8c68af3891 100644 --- a/docs/v1/AWSAccount.md +++ b/docs/v1/AWSAccount.md @@ -1,6 +1,7 @@ # AWSAccount Returns the AWS account associated with this integration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSAccountAndLambdaRequest.md b/docs/v1/AWSAccountAndLambdaRequest.md index 4c34aae4c7..bb9ecee3bc 100644 --- a/docs/v1/AWSAccountAndLambdaRequest.md +++ b/docs/v1/AWSAccountAndLambdaRequest.md @@ -1,6 +1,7 @@ # AWSAccountAndLambdaRequest AWS account ID and Lambda ARN. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSAccountCreateResponse.md b/docs/v1/AWSAccountCreateResponse.md index e60f6de970..2d6a57c0ee 100644 --- a/docs/v1/AWSAccountCreateResponse.md +++ b/docs/v1/AWSAccountCreateResponse.md @@ -1,6 +1,7 @@ # AWSAccountCreateResponse The Response returned by the AWS Create Account call. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSAccountListResponse.md b/docs/v1/AWSAccountListResponse.md index c5ae988020..fe3b15b09a 100644 --- a/docs/v1/AWSAccountListResponse.md +++ b/docs/v1/AWSAccountListResponse.md @@ -1,6 +1,7 @@ # AWSAccountListResponse List of enabled AWS accounts. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSIntegrationApi.md b/docs/v1/AWSIntegrationApi.md index 29c5d49efa..ad01004c30 100644 --- a/docs/v1/AWSIntegrationApi.md +++ b/docs/v1/AWSIntegrationApi.md @@ -72,6 +72,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->create_aws_account: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -91,6 +92,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -151,6 +153,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->create_aws_tag_filter: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -170,6 +173,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -236,6 +240,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->create_new_aws_external_id: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -255,6 +260,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -321,6 +327,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->delete_aws_account: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -340,6 +347,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -399,6 +407,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->delete_aws_tag_filter: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -418,6 +427,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -472,6 +482,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->list_available_aws_namespaces: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -488,6 +499,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -545,6 +557,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->list_aws_accounts: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -566,6 +579,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -621,6 +635,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->list_aws_tag_filters: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -640,6 +655,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -718,6 +734,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSIntegrationApi->update_aws_account: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -740,6 +757,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/AWSLogsAsyncError.md b/docs/v1/AWSLogsAsyncError.md index 30f69068cb..d720ffd92a 100644 --- a/docs/v1/AWSLogsAsyncError.md +++ b/docs/v1/AWSLogsAsyncError.md @@ -1,6 +1,7 @@ # AWSLogsAsyncError Description of errors. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSLogsAsyncResponse.md b/docs/v1/AWSLogsAsyncResponse.md index 90c64bcd3a..5dca461bbe 100644 --- a/docs/v1/AWSLogsAsyncResponse.md +++ b/docs/v1/AWSLogsAsyncResponse.md @@ -1,6 +1,7 @@ # AWSLogsAsyncResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSLogsIntegrationApi.md b/docs/v1/AWSLogsIntegrationApi.md index 8716841a79..122a7091fa 100644 --- a/docs/v1/AWSLogsIntegrationApi.md +++ b/docs/v1/AWSLogsIntegrationApi.md @@ -62,6 +62,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->check_aws_logs_lambda_async: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -81,6 +82,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -139,6 +141,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->check_aws_logs_services_async: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -158,6 +161,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -216,6 +220,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->create_aws_lambda_arn: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -235,6 +240,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -293,6 +299,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->delete_aws_lambda_arn: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -312,6 +319,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -370,6 +378,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->enable_aws_log_services: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -389,6 +398,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -443,6 +453,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->list_aws_logs_integrations: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -459,6 +470,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -513,6 +525,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AWSLogsIntegrationApi->list_aws_logs_services: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -529,6 +542,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/AWSLogsLambda.md b/docs/v1/AWSLogsLambda.md index 6641959204..f1fb601cd1 100644 --- a/docs/v1/AWSLogsLambda.md +++ b/docs/v1/AWSLogsLambda.md @@ -1,6 +1,7 @@ # AWSLogsLambda Description of the Lambdas. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSLogsListResponse.md b/docs/v1/AWSLogsListResponse.md index 9cae9b51a9..cbc9816b5c 100644 --- a/docs/v1/AWSLogsListResponse.md +++ b/docs/v1/AWSLogsListResponse.md @@ -1,6 +1,7 @@ # AWSLogsListResponse A list of all Datadog-AWS logs integrations available in your Datadog organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSLogsListServicesResponse.md b/docs/v1/AWSLogsListServicesResponse.md index 9b104a8089..3946882f01 100644 --- a/docs/v1/AWSLogsListServicesResponse.md +++ b/docs/v1/AWSLogsListServicesResponse.md @@ -1,6 +1,7 @@ # AWSLogsListServicesResponse The list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSLogsServicesRequest.md b/docs/v1/AWSLogsServicesRequest.md index 8db6f1a5b6..780b0420db 100644 --- a/docs/v1/AWSLogsServicesRequest.md +++ b/docs/v1/AWSLogsServicesRequest.md @@ -1,6 +1,7 @@ # AWSLogsServicesRequest A list of current AWS services for which Datadog offers automatic log collection. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSNamespace.md b/docs/v1/AWSNamespace.md index cf0ce68c2e..d16aca9b3b 100644 --- a/docs/v1/AWSNamespace.md +++ b/docs/v1/AWSNamespace.md @@ -1,6 +1,7 @@ # AWSNamespace The namespace associated with the tag filter entry. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSTagFilter.md b/docs/v1/AWSTagFilter.md index c0afbb2def..0144b54d48 100644 --- a/docs/v1/AWSTagFilter.md +++ b/docs/v1/AWSTagFilter.md @@ -1,6 +1,7 @@ # AWSTagFilter A tag filter. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSTagFilterCreateRequest.md b/docs/v1/AWSTagFilterCreateRequest.md index 4eb0a587db..831e84dd98 100644 --- a/docs/v1/AWSTagFilterCreateRequest.md +++ b/docs/v1/AWSTagFilterCreateRequest.md @@ -1,6 +1,7 @@ # AWSTagFilterCreateRequest The objects used to set an AWS tag filter. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSTagFilterDeleteRequest.md b/docs/v1/AWSTagFilterDeleteRequest.md index adb1e7ea71..629228ebd1 100644 --- a/docs/v1/AWSTagFilterDeleteRequest.md +++ b/docs/v1/AWSTagFilterDeleteRequest.md @@ -1,6 +1,7 @@ # AWSTagFilterDeleteRequest The objects used to delete an AWS tag filter entry. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AWSTagFilterListResponse.md b/docs/v1/AWSTagFilterListResponse.md index 79e5f946d7..255253c4ee 100644 --- a/docs/v1/AWSTagFilterListResponse.md +++ b/docs/v1/AWSTagFilterListResponse.md @@ -1,6 +1,7 @@ # AWSTagFilterListResponse An array of tag filter rules by `namespace` and tag filter string. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AccessRole.md b/docs/v1/AccessRole.md index a865cbb40c..0c13203cb8 100644 --- a/docs/v1/AccessRole.md +++ b/docs/v1/AccessRole.md @@ -1,6 +1,7 @@ # AccessRole The access role of the user. Options are **st** (standard user), **adm** (admin user), or **ro** (read-only user). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AlertGraphWidgetDefinition.md b/docs/v1/AlertGraphWidgetDefinition.md index 654e540de3..e26e340f5c 100644 --- a/docs/v1/AlertGraphWidgetDefinition.md +++ b/docs/v1/AlertGraphWidgetDefinition.md @@ -1,6 +1,7 @@ # AlertGraphWidgetDefinition Alert graphs are timeseries graphs showing the current status of any monitor defined on your system. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AlertGraphWidgetDefinitionType.md b/docs/v1/AlertGraphWidgetDefinitionType.md index d94d36f7d7..563cf8fc35 100644 --- a/docs/v1/AlertGraphWidgetDefinitionType.md +++ b/docs/v1/AlertGraphWidgetDefinitionType.md @@ -1,6 +1,7 @@ # AlertGraphWidgetDefinitionType Type of the alert graph widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AlertValueWidgetDefinition.md b/docs/v1/AlertValueWidgetDefinition.md index d6429b7716..9c61c0ebbe 100644 --- a/docs/v1/AlertValueWidgetDefinition.md +++ b/docs/v1/AlertValueWidgetDefinition.md @@ -1,6 +1,7 @@ # AlertValueWidgetDefinition Alert values are query values showing the current value of the metric in any monitor defined on your system. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AlertValueWidgetDefinitionType.md b/docs/v1/AlertValueWidgetDefinitionType.md index 7c10d63d94..64ff599233 100644 --- a/docs/v1/AlertValueWidgetDefinitionType.md +++ b/docs/v1/AlertValueWidgetDefinitionType.md @@ -1,6 +1,7 @@ # AlertValueWidgetDefinitionType Type of the alert value widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApiKey.md b/docs/v1/ApiKey.md index e66fd027ea..5048de007a 100644 --- a/docs/v1/ApiKey.md +++ b/docs/v1/ApiKey.md @@ -1,6 +1,7 @@ # ApiKey Datadog API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApiKeyListResponse.md b/docs/v1/ApiKeyListResponse.md index 8190369a7e..9fae0737ca 100644 --- a/docs/v1/ApiKeyListResponse.md +++ b/docs/v1/ApiKeyListResponse.md @@ -1,6 +1,7 @@ # ApiKeyListResponse List of API and application keys available for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApiKeyResponse.md b/docs/v1/ApiKeyResponse.md index b860ca32fd..688ef85c29 100644 --- a/docs/v1/ApiKeyResponse.md +++ b/docs/v1/ApiKeyResponse.md @@ -1,6 +1,7 @@ # ApiKeyResponse An API key with its associated metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApmStatsQueryColumnType.md b/docs/v1/ApmStatsQueryColumnType.md index cdc6b80451..f8550dff78 100644 --- a/docs/v1/ApmStatsQueryColumnType.md +++ b/docs/v1/ApmStatsQueryColumnType.md @@ -1,6 +1,7 @@ # ApmStatsQueryColumnType Column properties. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApmStatsQueryDefinition.md b/docs/v1/ApmStatsQueryDefinition.md index 1578a8b5a8..3f489dd859 100644 --- a/docs/v1/ApmStatsQueryDefinition.md +++ b/docs/v1/ApmStatsQueryDefinition.md @@ -1,6 +1,7 @@ # ApmStatsQueryDefinition The APM stats query for table and distributions widgets. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApmStatsQueryRowType.md b/docs/v1/ApmStatsQueryRowType.md index dbdceedc0f..c2b347fb81 100644 --- a/docs/v1/ApmStatsQueryRowType.md +++ b/docs/v1/ApmStatsQueryRowType.md @@ -1,6 +1,7 @@ # ApmStatsQueryRowType The level of detail for the request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApplicationKey.md b/docs/v1/ApplicationKey.md index 29ee3962d2..60d02f0437 100644 --- a/docs/v1/ApplicationKey.md +++ b/docs/v1/ApplicationKey.md @@ -1,6 +1,7 @@ # ApplicationKey An application key with its associated metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApplicationKeyListResponse.md b/docs/v1/ApplicationKeyListResponse.md index 9a5bab8219..ae00dcf1f4 100644 --- a/docs/v1/ApplicationKeyListResponse.md +++ b/docs/v1/ApplicationKeyListResponse.md @@ -1,6 +1,7 @@ # ApplicationKeyListResponse An application key response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ApplicationKeyResponse.md b/docs/v1/ApplicationKeyResponse.md index 28828008f2..9c90417b6e 100644 --- a/docs/v1/ApplicationKeyResponse.md +++ b/docs/v1/ApplicationKeyResponse.md @@ -1,6 +1,7 @@ # ApplicationKeyResponse An application key response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AuthenticationApi.md b/docs/v1/AuthenticationApi.md index fd76897834..536d271349 100644 --- a/docs/v1/AuthenticationApi.md +++ b/docs/v1/AuthenticationApi.md @@ -48,6 +48,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AuthenticationApi->validate: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -64,6 +65,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/AuthenticationValidationResponse.md b/docs/v1/AuthenticationValidationResponse.md index 9e351c983f..3322abb45f 100644 --- a/docs/v1/AuthenticationValidationResponse.md +++ b/docs/v1/AuthenticationValidationResponse.md @@ -1,6 +1,7 @@ # AuthenticationValidationResponse Represent validation endpoint responses. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AzureAccount.md b/docs/v1/AzureAccount.md index fc66773c5e..b0ccd6ed8a 100644 --- a/docs/v1/AzureAccount.md +++ b/docs/v1/AzureAccount.md @@ -1,6 +1,7 @@ # AzureAccount Datadog-Azure integrations configured for your organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AzureAccountListResponse.md b/docs/v1/AzureAccountListResponse.md index ccf4ce580b..144db3afd5 100644 --- a/docs/v1/AzureAccountListResponse.md +++ b/docs/v1/AzureAccountListResponse.md @@ -1,6 +1,7 @@ # AzureAccountListResponse Accounts configured for your organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/AzureIntegrationApi.md b/docs/v1/AzureIntegrationApi.md index 048cad1e0b..3816f249e9 100644 --- a/docs/v1/AzureIntegrationApi.md +++ b/docs/v1/AzureIntegrationApi.md @@ -65,6 +65,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AzureIntegrationApi->create_azure_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -84,6 +85,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -147,6 +149,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AzureIntegrationApi->delete_azure_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -166,6 +169,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -220,6 +224,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AzureIntegrationApi->list_azure_integration: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -236,6 +241,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -299,6 +305,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AzureIntegrationApi->update_azure_host_filters: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -318,6 +325,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -381,6 +389,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling AzureIntegrationApi->update_azure_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -400,6 +409,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/CancelDowntimesByScopeRequest.md b/docs/v1/CancelDowntimesByScopeRequest.md index 2ba4d479d1..9ebbc9bbf1 100644 --- a/docs/v1/CancelDowntimesByScopeRequest.md +++ b/docs/v1/CancelDowntimesByScopeRequest.md @@ -1,6 +1,7 @@ # CancelDowntimesByScopeRequest Cancel downtimes according to scope. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CanceledDowntimesIds.md b/docs/v1/CanceledDowntimesIds.md index 2d02527eb1..e4d3728605 100644 --- a/docs/v1/CanceledDowntimesIds.md +++ b/docs/v1/CanceledDowntimesIds.md @@ -1,6 +1,7 @@ # CanceledDowntimesIds Object containing array of IDs of canceled downtimes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ChangeWidgetDefinition.md b/docs/v1/ChangeWidgetDefinition.md index 6cbfdc0e8c..1e71a955a9 100644 --- a/docs/v1/ChangeWidgetDefinition.md +++ b/docs/v1/ChangeWidgetDefinition.md @@ -1,6 +1,7 @@ # ChangeWidgetDefinition The Change graph shows you the change in a value over the time period chosen. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ChangeWidgetDefinitionType.md b/docs/v1/ChangeWidgetDefinitionType.md index 93214fa0f2..3d3bdca350 100644 --- a/docs/v1/ChangeWidgetDefinitionType.md +++ b/docs/v1/ChangeWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ChangeWidgetDefinitionType Type of the change widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ChangeWidgetRequest.md b/docs/v1/ChangeWidgetRequest.md index 61904ec2e6..757652a21f 100644 --- a/docs/v1/ChangeWidgetRequest.md +++ b/docs/v1/ChangeWidgetRequest.md @@ -1,6 +1,7 @@ # ChangeWidgetRequest Updated change widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckCanDeleteMonitorResponse.md b/docs/v1/CheckCanDeleteMonitorResponse.md index eb25e5e7b4..9af024b507 100644 --- a/docs/v1/CheckCanDeleteMonitorResponse.md +++ b/docs/v1/CheckCanDeleteMonitorResponse.md @@ -1,6 +1,7 @@ # CheckCanDeleteMonitorResponse Response of monitor IDs that can or can't be safely deleted. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckCanDeleteMonitorResponseData.md b/docs/v1/CheckCanDeleteMonitorResponseData.md index 4e993d90a5..cd9a7f8998 100644 --- a/docs/v1/CheckCanDeleteMonitorResponseData.md +++ b/docs/v1/CheckCanDeleteMonitorResponseData.md @@ -1,6 +1,7 @@ # CheckCanDeleteMonitorResponseData Wrapper object with the list of monitor IDs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckCanDeleteSLOResponse.md b/docs/v1/CheckCanDeleteSLOResponse.md index cd719e7ec3..c04310b2d1 100644 --- a/docs/v1/CheckCanDeleteSLOResponse.md +++ b/docs/v1/CheckCanDeleteSLOResponse.md @@ -1,6 +1,7 @@ # CheckCanDeleteSLOResponse A service level objective response containing the requested object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckCanDeleteSLOResponseData.md b/docs/v1/CheckCanDeleteSLOResponseData.md index d8bd7de1d6..826f919cc5 100644 --- a/docs/v1/CheckCanDeleteSLOResponseData.md +++ b/docs/v1/CheckCanDeleteSLOResponseData.md @@ -1,6 +1,7 @@ # CheckCanDeleteSLOResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckStatusWidgetDefinition.md b/docs/v1/CheckStatusWidgetDefinition.md index e05f76ab61..8fed87458f 100644 --- a/docs/v1/CheckStatusWidgetDefinition.md +++ b/docs/v1/CheckStatusWidgetDefinition.md @@ -1,6 +1,7 @@ # CheckStatusWidgetDefinition Check status shows the current status or number of results for any check performed. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/CheckStatusWidgetDefinitionType.md b/docs/v1/CheckStatusWidgetDefinitionType.md index 38c683cd09..8727b40644 100644 --- a/docs/v1/CheckStatusWidgetDefinitionType.md +++ b/docs/v1/CheckStatusWidgetDefinitionType.md @@ -1,6 +1,7 @@ # CheckStatusWidgetDefinitionType Type of the check status widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Creator.md b/docs/v1/Creator.md index 15c2d2a969..023e476317 100644 --- a/docs/v1/Creator.md +++ b/docs/v1/Creator.md @@ -1,6 +1,7 @@ # Creator Object describing the creator of the shared element. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Dashboard.md b/docs/v1/Dashboard.md index 1f38fde7bf..26f38e0a08 100644 --- a/docs/v1/Dashboard.md +++ b/docs/v1/Dashboard.md @@ -1,6 +1,7 @@ # Dashboard A dashboard is Datadog’s tool for visually tracking, analyzing, and displaying key performance metrics, which enable you to monitor the health of your infrastructure. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardDeleteResponse.md b/docs/v1/DashboardDeleteResponse.md index c9aeb209d7..54befd3274 100644 --- a/docs/v1/DashboardDeleteResponse.md +++ b/docs/v1/DashboardDeleteResponse.md @@ -1,6 +1,7 @@ # DashboardDeleteResponse Response from the delete dashboard call. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardLayoutType.md b/docs/v1/DashboardLayoutType.md index a24cf1c7d1..24072235ad 100644 --- a/docs/v1/DashboardLayoutType.md +++ b/docs/v1/DashboardLayoutType.md @@ -1,6 +1,7 @@ # DashboardLayoutType Layout type of the dashboard. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardList.md b/docs/v1/DashboardList.md index b12232bab6..a5f19d388f 100644 --- a/docs/v1/DashboardList.md +++ b/docs/v1/DashboardList.md @@ -1,6 +1,7 @@ # DashboardList Your Datadog Dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardListDeleteResponse.md b/docs/v1/DashboardListDeleteResponse.md index d48dabb86a..5c915470f0 100644 --- a/docs/v1/DashboardListDeleteResponse.md +++ b/docs/v1/DashboardListDeleteResponse.md @@ -1,6 +1,7 @@ # DashboardListDeleteResponse Deleted dashboard details. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardListListResponse.md b/docs/v1/DashboardListListResponse.md index 880bf2c43f..28ceaa0d2e 100644 --- a/docs/v1/DashboardListListResponse.md +++ b/docs/v1/DashboardListListResponse.md @@ -1,6 +1,7 @@ # DashboardListListResponse Information on your dashboard lists. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardListsApi.md b/docs/v1/DashboardListsApi.md index 365374be8e..835231293b 100644 --- a/docs/v1/DashboardListsApi.md +++ b/docs/v1/DashboardListsApi.md @@ -70,6 +70,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->create_dashboard_list: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -89,6 +90,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -144,6 +146,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->delete_dashboard_list: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -163,6 +166,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -218,6 +222,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->get_dashboard_list: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -237,6 +242,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -291,6 +297,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->list_dashboard_lists: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -307,6 +314,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -375,6 +383,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->update_dashboard_list: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -395,6 +404,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/DashboardSummary.md b/docs/v1/DashboardSummary.md index 1fc2435c93..2fa874b7d3 100644 --- a/docs/v1/DashboardSummary.md +++ b/docs/v1/DashboardSummary.md @@ -1,6 +1,7 @@ # DashboardSummary Dashboard summary response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardSummaryDefinition.md b/docs/v1/DashboardSummaryDefinition.md index 9cababa371..22566c135c 100644 --- a/docs/v1/DashboardSummaryDefinition.md +++ b/docs/v1/DashboardSummaryDefinition.md @@ -1,6 +1,7 @@ # DashboardSummaryDefinition Dashboard definition. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardTemplateVariable.md b/docs/v1/DashboardTemplateVariable.md index 35b32acf2d..f7218c7950 100644 --- a/docs/v1/DashboardTemplateVariable.md +++ b/docs/v1/DashboardTemplateVariable.md @@ -1,6 +1,7 @@ # DashboardTemplateVariable Template variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardTemplateVariablePreset.md b/docs/v1/DashboardTemplateVariablePreset.md index 93aa7f21d1..c3a4316171 100644 --- a/docs/v1/DashboardTemplateVariablePreset.md +++ b/docs/v1/DashboardTemplateVariablePreset.md @@ -1,6 +1,7 @@ # DashboardTemplateVariablePreset Template variables saved views. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardTemplateVariablePresetValue.md b/docs/v1/DashboardTemplateVariablePresetValue.md index 282db95a6f..09473be9b2 100644 --- a/docs/v1/DashboardTemplateVariablePresetValue.md +++ b/docs/v1/DashboardTemplateVariablePresetValue.md @@ -1,6 +1,7 @@ # DashboardTemplateVariablePresetValue Template variables saved views. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DashboardsApi.md b/docs/v1/DashboardsApi.md index 5f7dda722a..88b99d40a6 100644 --- a/docs/v1/DashboardsApi.md +++ b/docs/v1/DashboardsApi.md @@ -89,6 +89,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardsApi->create_dashboard: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -108,6 +109,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -163,6 +165,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardsApi->delete_dashboard: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -182,6 +185,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -237,6 +241,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardsApi->get_dashboard: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -256,6 +261,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -310,6 +316,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardsApi->list_dashboards: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -326,6 +333,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -413,6 +421,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardsApi->update_dashboard: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -433,6 +442,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/DeletedMonitor.md b/docs/v1/DeletedMonitor.md index 98c2237dda..32e380ee92 100644 --- a/docs/v1/DeletedMonitor.md +++ b/docs/v1/DeletedMonitor.md @@ -1,6 +1,7 @@ # DeletedMonitor Response from the delete monitor call. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DistributionWidgetDefinition.md b/docs/v1/DistributionWidgetDefinition.md index 33357bcea7..165f07f497 100644 --- a/docs/v1/DistributionWidgetDefinition.md +++ b/docs/v1/DistributionWidgetDefinition.md @@ -1,6 +1,7 @@ # DistributionWidgetDefinition The Distribution visualization is another way of showing metrics aggregated across one or several tags, such as hosts. Unlike the heat map, a distribution graph’s x-axis is quantity rather than time. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DistributionWidgetDefinitionType.md b/docs/v1/DistributionWidgetDefinitionType.md index ddba11a761..7d5fb08a80 100644 --- a/docs/v1/DistributionWidgetDefinitionType.md +++ b/docs/v1/DistributionWidgetDefinitionType.md @@ -1,6 +1,7 @@ # DistributionWidgetDefinitionType Type of the distribution widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DistributionWidgetRequest.md b/docs/v1/DistributionWidgetRequest.md index c8efb2ed73..4ab4e71f5f 100644 --- a/docs/v1/DistributionWidgetRequest.md +++ b/docs/v1/DistributionWidgetRequest.md @@ -1,6 +1,7 @@ # DistributionWidgetRequest Updated distribution widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Downtime.md b/docs/v1/Downtime.md index 74bd3742ab..20db9aa77e 100644 --- a/docs/v1/Downtime.md +++ b/docs/v1/Downtime.md @@ -1,6 +1,7 @@ # Downtime Downtiming gives you greater control over monitor notifications by allowing you to globally exclude scopes from alerting. Downtime settings, which can be scheduled with start and end times, prevent all alerting related to specified Datadog tags. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DowntimeRecurrence.md b/docs/v1/DowntimeRecurrence.md index 5e2b47b957..9950ea76ab 100644 --- a/docs/v1/DowntimeRecurrence.md +++ b/docs/v1/DowntimeRecurrence.md @@ -1,6 +1,7 @@ # DowntimeRecurrence An object defining the recurrence of the downtime. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/DowntimesApi.md b/docs/v1/DowntimesApi.md index ea0a9c9da0..1f350030ff 100644 --- a/docs/v1/DowntimesApi.md +++ b/docs/v1/DowntimesApi.md @@ -57,6 +57,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->cancel_downtime: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -76,6 +77,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -133,6 +135,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->cancel_downtimes_by_scope: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -152,6 +155,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -232,6 +236,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->create_downtime: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -251,6 +256,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -306,6 +312,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->get_downtime: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -325,6 +332,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -381,6 +389,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->list_downtimes: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -400,6 +409,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -479,6 +489,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DowntimesApi->update_downtime: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -499,6 +510,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/Event.md b/docs/v1/Event.md index 917985700b..a227f0df7c 100644 --- a/docs/v1/Event.md +++ b/docs/v1/Event.md @@ -1,6 +1,7 @@ # Event Object representing an event. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventAlertType.md b/docs/v1/EventAlertType.md index 83b2727212..2d72a8876d 100644 --- a/docs/v1/EventAlertType.md +++ b/docs/v1/EventAlertType.md @@ -1,6 +1,7 @@ # EventAlertType If an alert event is enabled, set its type. For example, `error`, `warning`, `info`, `success`, `user_update`, `recommendation`, and `snapshot`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventListResponse.md b/docs/v1/EventListResponse.md index c2017802d4..dd8d3ae868 100644 --- a/docs/v1/EventListResponse.md +++ b/docs/v1/EventListResponse.md @@ -1,6 +1,7 @@ # EventListResponse An event list response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventPriority.md b/docs/v1/EventPriority.md index b682976171..1950c320e1 100644 --- a/docs/v1/EventPriority.md +++ b/docs/v1/EventPriority.md @@ -1,6 +1,7 @@ # EventPriority The priority of the event. For example, `normal` or `low`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventQueryDefinition.md b/docs/v1/EventQueryDefinition.md index c02002514b..91f8f0d953 100644 --- a/docs/v1/EventQueryDefinition.md +++ b/docs/v1/EventQueryDefinition.md @@ -1,6 +1,7 @@ # EventQueryDefinition The event query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventResponse.md b/docs/v1/EventResponse.md index 9e49c3090e..63e618d335 100644 --- a/docs/v1/EventResponse.md +++ b/docs/v1/EventResponse.md @@ -1,6 +1,7 @@ # EventResponse Object containing an event response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventStreamWidgetDefinition.md b/docs/v1/EventStreamWidgetDefinition.md index f648cba2a5..bf8a4268ab 100644 --- a/docs/v1/EventStreamWidgetDefinition.md +++ b/docs/v1/EventStreamWidgetDefinition.md @@ -1,6 +1,7 @@ # EventStreamWidgetDefinition The event stream is a widget version of the stream of events on the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventStreamWidgetDefinitionType.md b/docs/v1/EventStreamWidgetDefinitionType.md index c74a291621..9756c633d0 100644 --- a/docs/v1/EventStreamWidgetDefinitionType.md +++ b/docs/v1/EventStreamWidgetDefinitionType.md @@ -1,6 +1,7 @@ # EventStreamWidgetDefinitionType Type of the event stream widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventTimelineWidgetDefinition.md b/docs/v1/EventTimelineWidgetDefinition.md index a6ee22e950..7f2670c8fc 100644 --- a/docs/v1/EventTimelineWidgetDefinition.md +++ b/docs/v1/EventTimelineWidgetDefinition.md @@ -1,6 +1,7 @@ # EventTimelineWidgetDefinition The event timeline is a widget version of the timeline that appears at the top of the Event Stream view. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventTimelineWidgetDefinitionType.md b/docs/v1/EventTimelineWidgetDefinitionType.md index b99df57730..a9e8b8848d 100644 --- a/docs/v1/EventTimelineWidgetDefinitionType.md +++ b/docs/v1/EventTimelineWidgetDefinitionType.md @@ -1,6 +1,7 @@ # EventTimelineWidgetDefinitionType Type of the event timeline widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/EventsApi.md b/docs/v1/EventsApi.md index 994965a2ac..a0af126254 100644 --- a/docs/v1/EventsApi.md +++ b/docs/v1/EventsApi.md @@ -54,6 +54,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling EventsApi->get_event: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -73,6 +74,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -142,6 +144,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling EventsApi->list_events: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -166,6 +169,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/FormulaAndFunctionEventAggregation.md b/docs/v1/FormulaAndFunctionEventAggregation.md index c336a6274e..9e47946ee8 100644 --- a/docs/v1/FormulaAndFunctionEventAggregation.md +++ b/docs/v1/FormulaAndFunctionEventAggregation.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventAggregation Aggregation methods for event platform queries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventQueryDefinition.md b/docs/v1/FormulaAndFunctionEventQueryDefinition.md index eff502bc4e..ee0ce7a5d1 100644 --- a/docs/v1/FormulaAndFunctionEventQueryDefinition.md +++ b/docs/v1/FormulaAndFunctionEventQueryDefinition.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventQueryDefinition A formula and functions events query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md b/docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md index 1717dc225a..96a6bfd586 100644 --- a/docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md +++ b/docs/v1/FormulaAndFunctionEventQueryDefinitionCompute.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventQueryDefinitionCompute Compute options. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md b/docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md index 643e409715..f47245ac54 100644 --- a/docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md +++ b/docs/v1/FormulaAndFunctionEventQueryDefinitionSearch.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventQueryDefinitionSearch Search options. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventQueryGroupBy.md b/docs/v1/FormulaAndFunctionEventQueryGroupBy.md index 861e5a04cd..4b9e0d8c61 100644 --- a/docs/v1/FormulaAndFunctionEventQueryGroupBy.md +++ b/docs/v1/FormulaAndFunctionEventQueryGroupBy.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventQueryGroupBy List of objects used to group by. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventQueryGroupBySort.md b/docs/v1/FormulaAndFunctionEventQueryGroupBySort.md index e2e171e9e8..8a5024d63c 100644 --- a/docs/v1/FormulaAndFunctionEventQueryGroupBySort.md +++ b/docs/v1/FormulaAndFunctionEventQueryGroupBySort.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventQueryGroupBySort Options for sorting group by results. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionEventsDataSource.md b/docs/v1/FormulaAndFunctionEventsDataSource.md index 38d097b448..31d61e198b 100644 --- a/docs/v1/FormulaAndFunctionEventsDataSource.md +++ b/docs/v1/FormulaAndFunctionEventsDataSource.md @@ -1,6 +1,7 @@ # FormulaAndFunctionEventsDataSource Data source for event platform-based queries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionMetricAggregation.md b/docs/v1/FormulaAndFunctionMetricAggregation.md index 2cb84d33f4..0029cdf5ce 100644 --- a/docs/v1/FormulaAndFunctionMetricAggregation.md +++ b/docs/v1/FormulaAndFunctionMetricAggregation.md @@ -1,6 +1,7 @@ # FormulaAndFunctionMetricAggregation The aggregation methods available for metrics queries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionMetricDataSource.md b/docs/v1/FormulaAndFunctionMetricDataSource.md index 6010eea37e..684dae2c66 100644 --- a/docs/v1/FormulaAndFunctionMetricDataSource.md +++ b/docs/v1/FormulaAndFunctionMetricDataSource.md @@ -1,6 +1,7 @@ # FormulaAndFunctionMetricDataSource Data source for metrics queries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionMetricQueryDefinition.md b/docs/v1/FormulaAndFunctionMetricQueryDefinition.md index 469cc7b909..b085c376b0 100644 --- a/docs/v1/FormulaAndFunctionMetricQueryDefinition.md +++ b/docs/v1/FormulaAndFunctionMetricQueryDefinition.md @@ -1,6 +1,7 @@ # FormulaAndFunctionMetricQueryDefinition A formula and functions metrics query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionProcessQueryDataSource.md b/docs/v1/FormulaAndFunctionProcessQueryDataSource.md index 3bd01be740..087261185f 100644 --- a/docs/v1/FormulaAndFunctionProcessQueryDataSource.md +++ b/docs/v1/FormulaAndFunctionProcessQueryDataSource.md @@ -1,6 +1,7 @@ # FormulaAndFunctionProcessQueryDataSource Data sources that rely on the process backend. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionProcessQueryDefinition.md b/docs/v1/FormulaAndFunctionProcessQueryDefinition.md index 83355976ad..808bb6a3d4 100644 --- a/docs/v1/FormulaAndFunctionProcessQueryDefinition.md +++ b/docs/v1/FormulaAndFunctionProcessQueryDefinition.md @@ -1,6 +1,7 @@ # FormulaAndFunctionProcessQueryDefinition Process query using formulas and functions. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionQueryDefinition.md b/docs/v1/FormulaAndFunctionQueryDefinition.md index 3c5d431a59..9b99a53698 100644 --- a/docs/v1/FormulaAndFunctionQueryDefinition.md +++ b/docs/v1/FormulaAndFunctionQueryDefinition.md @@ -1,6 +1,7 @@ # FormulaAndFunctionQueryDefinition A formula and function query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FormulaAndFunctionResponseFormat.md b/docs/v1/FormulaAndFunctionResponseFormat.md index a0ec233003..292dab0ee2 100644 --- a/docs/v1/FormulaAndFunctionResponseFormat.md +++ b/docs/v1/FormulaAndFunctionResponseFormat.md @@ -1,6 +1,7 @@ # FormulaAndFunctionResponseFormat Timeseries or Scalar response. **This feature is currently in beta.** + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FreeTextWidgetDefinition.md b/docs/v1/FreeTextWidgetDefinition.md index 3a2c5dad13..52192451a2 100644 --- a/docs/v1/FreeTextWidgetDefinition.md +++ b/docs/v1/FreeTextWidgetDefinition.md @@ -1,6 +1,7 @@ # FreeTextWidgetDefinition Free text is a widget that allows you to add headings to your screenboard. Commonly used to state the overall purpose of the dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/FreeTextWidgetDefinitionType.md b/docs/v1/FreeTextWidgetDefinitionType.md index 4657465c55..7616b4cb5e 100644 --- a/docs/v1/FreeTextWidgetDefinitionType.md +++ b/docs/v1/FreeTextWidgetDefinitionType.md @@ -1,6 +1,7 @@ # FreeTextWidgetDefinitionType Type of the free text widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GCPAccount.md b/docs/v1/GCPAccount.md index d068203c75..410e205cea 100644 --- a/docs/v1/GCPAccount.md +++ b/docs/v1/GCPAccount.md @@ -1,6 +1,7 @@ # GCPAccount Your Google Cloud Platform Account. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GCPAccountListResponse.md b/docs/v1/GCPAccountListResponse.md index c0c0ca2bc9..ba5cf8609b 100644 --- a/docs/v1/GCPAccountListResponse.md +++ b/docs/v1/GCPAccountListResponse.md @@ -1,6 +1,7 @@ # GCPAccountListResponse Array of GCP account responses. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GCPIntegrationApi.md b/docs/v1/GCPIntegrationApi.md index 84936ea900..c392bc66fa 100644 --- a/docs/v1/GCPIntegrationApi.md +++ b/docs/v1/GCPIntegrationApi.md @@ -70,6 +70,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling GCPIntegrationApi->create_gcp_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -89,6 +90,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -158,6 +160,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling GCPIntegrationApi->delete_gcp_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -177,6 +180,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -231,6 +235,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling GCPIntegrationApi->list_gcp_integration: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -247,6 +252,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -316,6 +322,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling GCPIntegrationApi->update_gcp_integration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -335,6 +342,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/GeomapWidgetDefinition.md b/docs/v1/GeomapWidgetDefinition.md index f7f5419c70..2f4317c13b 100644 --- a/docs/v1/GeomapWidgetDefinition.md +++ b/docs/v1/GeomapWidgetDefinition.md @@ -1,6 +1,7 @@ # GeomapWidgetDefinition This visualization displays a series of values by country on a world map. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GeomapWidgetDefinitionStyle.md b/docs/v1/GeomapWidgetDefinitionStyle.md index d8ff7a6ee0..a42323429f 100644 --- a/docs/v1/GeomapWidgetDefinitionStyle.md +++ b/docs/v1/GeomapWidgetDefinitionStyle.md @@ -1,6 +1,7 @@ # GeomapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GeomapWidgetDefinitionType.md b/docs/v1/GeomapWidgetDefinitionType.md index 09b725093f..f34057ca49 100644 --- a/docs/v1/GeomapWidgetDefinitionType.md +++ b/docs/v1/GeomapWidgetDefinitionType.md @@ -1,6 +1,7 @@ # GeomapWidgetDefinitionType Type of the geomap widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GeomapWidgetDefinitionView.md b/docs/v1/GeomapWidgetDefinitionView.md index 0afe5f608a..bc81e73fd9 100644 --- a/docs/v1/GeomapWidgetDefinitionView.md +++ b/docs/v1/GeomapWidgetDefinitionView.md @@ -1,6 +1,7 @@ # GeomapWidgetDefinitionView The view of the world that the map should render. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GeomapWidgetRequest.md b/docs/v1/GeomapWidgetRequest.md index e9dbf79937..b2a51c6341 100644 --- a/docs/v1/GeomapWidgetRequest.md +++ b/docs/v1/GeomapWidgetRequest.md @@ -1,6 +1,7 @@ # GeomapWidgetRequest An updated geomap widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GraphSnapshot.md b/docs/v1/GraphSnapshot.md index d9802ead48..f4ad77ec0d 100644 --- a/docs/v1/GraphSnapshot.md +++ b/docs/v1/GraphSnapshot.md @@ -1,6 +1,7 @@ # GraphSnapshot Object representing a graph snapshot. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GroupWidgetDefinition.md b/docs/v1/GroupWidgetDefinition.md index 92773ff7e3..863d360d5d 100644 --- a/docs/v1/GroupWidgetDefinition.md +++ b/docs/v1/GroupWidgetDefinition.md @@ -1,6 +1,7 @@ # GroupWidgetDefinition The groups widget allows you to keep similar graphs together on your timeboard. Each group has a custom header, can hold one to many graphs, and is collapsible. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/GroupWidgetDefinitionType.md b/docs/v1/GroupWidgetDefinitionType.md index 63066ca267..57ce99f154 100644 --- a/docs/v1/GroupWidgetDefinitionType.md +++ b/docs/v1/GroupWidgetDefinitionType.md @@ -1,6 +1,7 @@ # GroupWidgetDefinitionType Type of the group widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HTTPMethod.md b/docs/v1/HTTPMethod.md index 4388cd21a8..47394c9d25 100644 --- a/docs/v1/HTTPMethod.md +++ b/docs/v1/HTTPMethod.md @@ -1,6 +1,7 @@ # HTTPMethod The HTTP method. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HeatMapWidgetDefinition.md b/docs/v1/HeatMapWidgetDefinition.md index 88bc140c1d..d15ee914c9 100644 --- a/docs/v1/HeatMapWidgetDefinition.md +++ b/docs/v1/HeatMapWidgetDefinition.md @@ -1,6 +1,7 @@ # HeatMapWidgetDefinition The heat map visualization shows metrics aggregated across many tags, such as hosts. The more hosts that have a particular value, the darker that square is. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HeatMapWidgetDefinitionType.md b/docs/v1/HeatMapWidgetDefinitionType.md index c90fae6458..d31b0f2039 100644 --- a/docs/v1/HeatMapWidgetDefinitionType.md +++ b/docs/v1/HeatMapWidgetDefinitionType.md @@ -1,6 +1,7 @@ # HeatMapWidgetDefinitionType Type of the heat map widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HeatMapWidgetRequest.md b/docs/v1/HeatMapWidgetRequest.md index a491018b97..c2c8f2950c 100644 --- a/docs/v1/HeatMapWidgetRequest.md +++ b/docs/v1/HeatMapWidgetRequest.md @@ -1,6 +1,7 @@ # HeatMapWidgetRequest Updated heat map widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Host.md b/docs/v1/Host.md index 299d0d00ca..1bbf85fad8 100644 --- a/docs/v1/Host.md +++ b/docs/v1/Host.md @@ -1,6 +1,7 @@ # Host Object representing a host. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostListResponse.md b/docs/v1/HostListResponse.md index b393468702..614c9abd44 100644 --- a/docs/v1/HostListResponse.md +++ b/docs/v1/HostListResponse.md @@ -1,6 +1,7 @@ # HostListResponse Response with Host information from Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMapRequest.md b/docs/v1/HostMapRequest.md index 6661d53e3c..61ace7d389 100644 --- a/docs/v1/HostMapRequest.md +++ b/docs/v1/HostMapRequest.md @@ -1,6 +1,7 @@ # HostMapRequest Updated host map. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMapWidgetDefinition.md b/docs/v1/HostMapWidgetDefinition.md index ea4903228f..8fc53c86b6 100644 --- a/docs/v1/HostMapWidgetDefinition.md +++ b/docs/v1/HostMapWidgetDefinition.md @@ -1,6 +1,7 @@ # HostMapWidgetDefinition The host map widget graphs any metric across your hosts using the same visualization available from the main Host Map page. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMapWidgetDefinitionRequests.md b/docs/v1/HostMapWidgetDefinitionRequests.md index 1ab757dbf6..64fb3e44c3 100644 --- a/docs/v1/HostMapWidgetDefinitionRequests.md +++ b/docs/v1/HostMapWidgetDefinitionRequests.md @@ -1,6 +1,7 @@ # HostMapWidgetDefinitionRequests List of definitions. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMapWidgetDefinitionStyle.md b/docs/v1/HostMapWidgetDefinitionStyle.md index c48d2178a6..5955a503dc 100644 --- a/docs/v1/HostMapWidgetDefinitionStyle.md +++ b/docs/v1/HostMapWidgetDefinitionStyle.md @@ -1,6 +1,7 @@ # HostMapWidgetDefinitionStyle The style to apply to the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMapWidgetDefinitionType.md b/docs/v1/HostMapWidgetDefinitionType.md index d22f0b8c67..135db7f6bf 100644 --- a/docs/v1/HostMapWidgetDefinitionType.md +++ b/docs/v1/HostMapWidgetDefinitionType.md @@ -1,6 +1,7 @@ # HostMapWidgetDefinitionType Type of the host map widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMeta.md b/docs/v1/HostMeta.md index ece5c20060..ee7e36837d 100644 --- a/docs/v1/HostMeta.md +++ b/docs/v1/HostMeta.md @@ -1,6 +1,7 @@ # HostMeta Metadata associated with your host. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMetrics.md b/docs/v1/HostMetrics.md index 3a4879df8e..7b95b9e3cc 100644 --- a/docs/v1/HostMetrics.md +++ b/docs/v1/HostMetrics.md @@ -1,6 +1,7 @@ # HostMetrics Host Metrics collected. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMuteResponse.md b/docs/v1/HostMuteResponse.md index e9c91edc9c..511ad369bd 100644 --- a/docs/v1/HostMuteResponse.md +++ b/docs/v1/HostMuteResponse.md @@ -1,6 +1,7 @@ # HostMuteResponse Response with the list of muted host for your organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostMuteSettings.md b/docs/v1/HostMuteSettings.md index 63dbe9521d..cd9993f845 100644 --- a/docs/v1/HostMuteSettings.md +++ b/docs/v1/HostMuteSettings.md @@ -1,6 +1,7 @@ # HostMuteSettings Combination of settings to mute a host. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostTags.md b/docs/v1/HostTags.md index c1cc5cdf0f..6dc4c15ce7 100644 --- a/docs/v1/HostTags.md +++ b/docs/v1/HostTags.md @@ -1,6 +1,7 @@ # HostTags Set of tags to associate with your host. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostTotals.md b/docs/v1/HostTotals.md index 24f7a947c9..a290bdbd66 100644 --- a/docs/v1/HostTotals.md +++ b/docs/v1/HostTotals.md @@ -1,6 +1,7 @@ # HostTotals Total number of host currently monitored by Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/HostsApi.md b/docs/v1/HostsApi.md index ca20058d1c..897235d7c3 100644 --- a/docs/v1/HostsApi.md +++ b/docs/v1/HostsApi.md @@ -57,6 +57,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling HostsApi->get_host_totals: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -76,6 +77,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -139,6 +141,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling HostsApi->list_hosts: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -165,6 +168,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -225,6 +229,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling HostsApi->mute_host: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -245,6 +250,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -300,6 +306,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling HostsApi->unmute_host: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -319,6 +326,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/IFrameWidgetDefinition.md b/docs/v1/IFrameWidgetDefinition.md index 8749be098d..70a0e3999c 100644 --- a/docs/v1/IFrameWidgetDefinition.md +++ b/docs/v1/IFrameWidgetDefinition.md @@ -1,6 +1,7 @@ # IFrameWidgetDefinition The iframe widget allows you to embed a portion of any other web page on your dashboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IFrameWidgetDefinitionType.md b/docs/v1/IFrameWidgetDefinitionType.md index 43841f855d..571c762ce8 100644 --- a/docs/v1/IFrameWidgetDefinitionType.md +++ b/docs/v1/IFrameWidgetDefinitionType.md @@ -1,6 +1,7 @@ # IFrameWidgetDefinitionType Type of the iframe widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesAPI.md b/docs/v1/IPPrefixesAPI.md index 9dc974fa2c..0286edec29 100644 --- a/docs/v1/IPPrefixesAPI.md +++ b/docs/v1/IPPrefixesAPI.md @@ -1,6 +1,7 @@ # IPPrefixesAPI Available prefix information for the API endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesAPM.md b/docs/v1/IPPrefixesAPM.md index 2ade44c808..34784596fe 100644 --- a/docs/v1/IPPrefixesAPM.md +++ b/docs/v1/IPPrefixesAPM.md @@ -1,6 +1,7 @@ # IPPrefixesAPM Available prefix information for the APM endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesAgents.md b/docs/v1/IPPrefixesAgents.md index 93349e1268..ccbe8a2c4b 100644 --- a/docs/v1/IPPrefixesAgents.md +++ b/docs/v1/IPPrefixesAgents.md @@ -1,6 +1,7 @@ # IPPrefixesAgents Available prefix information for the Agent endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesLogs.md b/docs/v1/IPPrefixesLogs.md index 2ab035cc31..6f19c409fd 100644 --- a/docs/v1/IPPrefixesLogs.md +++ b/docs/v1/IPPrefixesLogs.md @@ -1,6 +1,7 @@ # IPPrefixesLogs Available prefix information for the Logs endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesProcess.md b/docs/v1/IPPrefixesProcess.md index 2df463e66b..4e489f0520 100644 --- a/docs/v1/IPPrefixesProcess.md +++ b/docs/v1/IPPrefixesProcess.md @@ -1,6 +1,7 @@ # IPPrefixesProcess Available prefix information for the Process endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesSynthetics.md b/docs/v1/IPPrefixesSynthetics.md index ff36a2e86e..3d0b88710d 100644 --- a/docs/v1/IPPrefixesSynthetics.md +++ b/docs/v1/IPPrefixesSynthetics.md @@ -1,6 +1,7 @@ # IPPrefixesSynthetics Available prefix information for the Synthetics endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPPrefixesWebhooks.md b/docs/v1/IPPrefixesWebhooks.md index db4fc024d9..7e44db40bf 100644 --- a/docs/v1/IPPrefixesWebhooks.md +++ b/docs/v1/IPPrefixesWebhooks.md @@ -1,6 +1,7 @@ # IPPrefixesWebhooks Available prefix information for the Webhook endpoints. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPRanges.md b/docs/v1/IPRanges.md index 456928c511..defbbc14e8 100644 --- a/docs/v1/IPRanges.md +++ b/docs/v1/IPRanges.md @@ -1,6 +1,7 @@ # IPRanges IP ranges. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IPRangesApi.md b/docs/v1/IPRangesApi.md index 15879abdd1..0f7655b6f0 100644 --- a/docs/v1/IPRangesApi.md +++ b/docs/v1/IPRangesApi.md @@ -44,6 +44,7 @@ with ApiClient() as api_client: print("Exception when calling IPRangesApi->get_ip_ranges: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -60,6 +61,7 @@ No authorization required - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/IdpFormData.md b/docs/v1/IdpFormData.md index 648d9d3f82..95307a11b5 100644 --- a/docs/v1/IdpFormData.md +++ b/docs/v1/IdpFormData.md @@ -1,6 +1,7 @@ # IdpFormData Object describing the IdP configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/IdpResponse.md b/docs/v1/IdpResponse.md index 929324afa1..c345673a23 100644 --- a/docs/v1/IdpResponse.md +++ b/docs/v1/IdpResponse.md @@ -1,6 +1,7 @@ # IdpResponse The IdP response object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ImageWidgetDefinition.md b/docs/v1/ImageWidgetDefinition.md index f5e3baca3a..65976f4f7a 100644 --- a/docs/v1/ImageWidgetDefinition.md +++ b/docs/v1/ImageWidgetDefinition.md @@ -1,6 +1,7 @@ # ImageWidgetDefinition The image widget allows you to embed an image on your dashboard. An image can be a PNG, JPG, or animated GIF. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ImageWidgetDefinitionType.md b/docs/v1/ImageWidgetDefinitionType.md index 0c8f44ee7d..ed1fbb6093 100644 --- a/docs/v1/ImageWidgetDefinitionType.md +++ b/docs/v1/ImageWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ImageWidgetDefinitionType Type of the image widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/KeyManagementApi.md b/docs/v1/KeyManagementApi.md index 7fe0268306..6a8ff0798b 100644 --- a/docs/v1/KeyManagementApi.md +++ b/docs/v1/KeyManagementApi.md @@ -67,6 +67,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->create_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -86,6 +87,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -145,6 +147,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->create_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -164,6 +167,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -220,6 +224,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->delete_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -239,6 +244,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -295,6 +301,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->delete_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -314,6 +321,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -369,6 +377,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->get_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -388,6 +397,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -443,6 +453,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->get_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -462,6 +473,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -516,6 +528,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->list_api_keys: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -532,6 +545,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -585,6 +599,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->list_application_keys: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -601,6 +616,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -661,6 +677,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->update_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -681,6 +698,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -742,6 +760,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->update_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -762,6 +781,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/Log.md b/docs/v1/Log.md index a3ee1523f3..a045f03d7f 100644 --- a/docs/v1/Log.md +++ b/docs/v1/Log.md @@ -1,6 +1,7 @@ # Log Object describing a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogContent.md b/docs/v1/LogContent.md index 36857041ff..c35b736d44 100644 --- a/docs/v1/LogContent.md +++ b/docs/v1/LogContent.md @@ -1,6 +1,7 @@ # LogContent JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogQueryDefinition.md b/docs/v1/LogQueryDefinition.md index 80277820fa..c044e17d0a 100644 --- a/docs/v1/LogQueryDefinition.md +++ b/docs/v1/LogQueryDefinition.md @@ -1,6 +1,7 @@ # LogQueryDefinition The log query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogQueryDefinitionGroupBy.md b/docs/v1/LogQueryDefinitionGroupBy.md index 41d7991b92..02775bd810 100644 --- a/docs/v1/LogQueryDefinitionGroupBy.md +++ b/docs/v1/LogQueryDefinitionGroupBy.md @@ -1,6 +1,7 @@ # LogQueryDefinitionGroupBy Defined items in the group. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogQueryDefinitionGroupBySort.md b/docs/v1/LogQueryDefinitionGroupBySort.md index 3565b1112a..b75a27a7b7 100644 --- a/docs/v1/LogQueryDefinitionGroupBySort.md +++ b/docs/v1/LogQueryDefinitionGroupBySort.md @@ -1,6 +1,7 @@ # LogQueryDefinitionGroupBySort Define a sorting method. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogQueryDefinitionSearch.md b/docs/v1/LogQueryDefinitionSearch.md index 3f36abd8f2..7cd6db3a17 100644 --- a/docs/v1/LogQueryDefinitionSearch.md +++ b/docs/v1/LogQueryDefinitionSearch.md @@ -1,6 +1,7 @@ # LogQueryDefinitionSearch The query being made on the logs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogStreamWidgetDefinition.md b/docs/v1/LogStreamWidgetDefinition.md index 7db6b917ca..7f54310ff3 100644 --- a/docs/v1/LogStreamWidgetDefinition.md +++ b/docs/v1/LogStreamWidgetDefinition.md @@ -1,6 +1,7 @@ # LogStreamWidgetDefinition The Log Stream displays a log flow matching the defined query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogStreamWidgetDefinitionType.md b/docs/v1/LogStreamWidgetDefinitionType.md index de515f62c6..5df4c4f49a 100644 --- a/docs/v1/LogStreamWidgetDefinitionType.md +++ b/docs/v1/LogStreamWidgetDefinitionType.md @@ -1,6 +1,7 @@ # LogStreamWidgetDefinitionType Type of the log stream widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsAPIError.md b/docs/v1/LogsAPIError.md index 8626f5146e..5bce92653d 100644 --- a/docs/v1/LogsAPIError.md +++ b/docs/v1/LogsAPIError.md @@ -1,6 +1,7 @@ # LogsAPIError Error returned by the Logs API + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsAPIErrorResponse.md b/docs/v1/LogsAPIErrorResponse.md index 68d2a62d05..bd312a82de 100644 --- a/docs/v1/LogsAPIErrorResponse.md +++ b/docs/v1/LogsAPIErrorResponse.md @@ -1,6 +1,7 @@ # LogsAPIErrorResponse Response returned by the Logs API when errors occur. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsApi.md b/docs/v1/LogsApi.md index a57441c50e..ba7c721a6a 100644 --- a/docs/v1/LogsApi.md +++ b/docs/v1/LogsApi.md @@ -64,6 +64,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsApi->list_logs: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -83,6 +84,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/LogsArithmeticProcessor.md b/docs/v1/LogsArithmeticProcessor.md index 4b9fa90825..2f393fc52e 100644 --- a/docs/v1/LogsArithmeticProcessor.md +++ b/docs/v1/LogsArithmeticProcessor.md @@ -1,6 +1,7 @@ # LogsArithmeticProcessor Use the Arithmetic Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log with the result of the provided formula. This enables you to remap different time attributes with different units into a single attribute, or to compute operations on attributes within the same log. The formula can use parentheses and the basic arithmetic operators `-`, `+`, `*`, `/`. By default, the calculation is skipped if an attribute is missing. Select “Replace missing attribute by 0” to automatically populate missing attribute values with 0 to ensure that the calculation is done. An attribute is missing if it is not found in the log attributes, or if it cannot be converted to a number. *Notes*: - The operator `-` needs to be space split in the formula as it can also be contained in attribute names. - If the target attribute already exists, it is overwritten by the result of the formula. - Results are rounded up to the 9th decimal. For example, if the result of the formula is `0.1234567891`, the actual value stored for the attribute is `0.123456789`. - If you need to scale a unit of measure, see [Scale Filter](https://docs.datadoghq.com/logs/processing/parsing/?tab=filter#matcher-and-filter). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsArithmeticProcessorType.md b/docs/v1/LogsArithmeticProcessorType.md index 948b78de8f..0272f7aaf0 100644 --- a/docs/v1/LogsArithmeticProcessorType.md +++ b/docs/v1/LogsArithmeticProcessorType.md @@ -1,6 +1,7 @@ # LogsArithmeticProcessorType Type of logs arithmetic processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsAttributeRemapper.md b/docs/v1/LogsAttributeRemapper.md index a08fa29dd8..e709485d1e 100644 --- a/docs/v1/LogsAttributeRemapper.md +++ b/docs/v1/LogsAttributeRemapper.md @@ -1,6 +1,7 @@ # LogsAttributeRemapper The remapper processor remaps any source attribute(s) or tag to another target attribute or tag. Constraints on the tag/attribute name are explained in the [Tag Best Practice documentation](https://docs.datadoghq.com/logs/guide/log-parsing-best-practice). Some additional constraints are applied as `:` or `,` are not allowed in the target tag/attribute name. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsAttributeRemapperType.md b/docs/v1/LogsAttributeRemapperType.md index 335ccf0a4b..31188d944d 100644 --- a/docs/v1/LogsAttributeRemapperType.md +++ b/docs/v1/LogsAttributeRemapperType.md @@ -1,6 +1,7 @@ # LogsAttributeRemapperType Type of logs attribute remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsCategoryProcessor.md b/docs/v1/LogsCategoryProcessor.md index 9417dd0f12..ebbc316018 100644 --- a/docs/v1/LogsCategoryProcessor.md +++ b/docs/v1/LogsCategoryProcessor.md @@ -1,6 +1,7 @@ # LogsCategoryProcessor Use the Category Processor to add a new attribute (without spaces or special characters in the new attribute name) to a log matching a provided search query. Use categories to create groups for an analytical view. For example, URL groups, machine groups, environments, and response time buckets. **Notes**: - The syntax of the query is the one of Logs Explorer search bar. The query can be done on any log attribute or tag, whether it is a facet or not. Wildcards can also be used inside your query. - Once the log has matched one of the Processor queries, it stops. Make sure they are properly ordered in case a log could match several queries. - The names of the categories must be unique. - Once defined in the Category Processor, you can map categories to log status using the Log Status Remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsCategoryProcessorCategory.md b/docs/v1/LogsCategoryProcessorCategory.md index 38779573c6..c4a32da83c 100644 --- a/docs/v1/LogsCategoryProcessorCategory.md +++ b/docs/v1/LogsCategoryProcessorCategory.md @@ -1,6 +1,7 @@ # LogsCategoryProcessorCategory Object describing the logs filter. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsCategoryProcessorType.md b/docs/v1/LogsCategoryProcessorType.md index 75f90a653f..37cf5d4ad3 100644 --- a/docs/v1/LogsCategoryProcessorType.md +++ b/docs/v1/LogsCategoryProcessorType.md @@ -1,6 +1,7 @@ # LogsCategoryProcessorType Type of logs category processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsDateRemapper.md b/docs/v1/LogsDateRemapper.md index f2fbcc2fe3..1da2f743e0 100644 --- a/docs/v1/LogsDateRemapper.md +++ b/docs/v1/LogsDateRemapper.md @@ -1,6 +1,7 @@ # LogsDateRemapper As Datadog receives logs, it timestamps them using the value(s) from any of these default attributes. - `timestamp` - `date` - `_timestamp` - `Timestamp` - `eventTime` - `published_date` If your logs put their dates in an attribute not in this list, use the log date Remapper Processor to define their date attribute as the official log timestamp. The recognized date formats are ISO8601, UNIX (the milliseconds EPOCH format), and RFC3164. **Note:** If your logs don’t contain any of the default attributes and you haven’t defined your own date attribute, Datadog timestamps the logs with the date it received them. If multiple log date remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsDateRemapperType.md b/docs/v1/LogsDateRemapperType.md index 6cd11d04db..dd6126ec9d 100644 --- a/docs/v1/LogsDateRemapperType.md +++ b/docs/v1/LogsDateRemapperType.md @@ -1,6 +1,7 @@ # LogsDateRemapperType Type of logs date remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsExclusion.md b/docs/v1/LogsExclusion.md index 1141338eb3..8927f3b0ca 100644 --- a/docs/v1/LogsExclusion.md +++ b/docs/v1/LogsExclusion.md @@ -1,6 +1,7 @@ # LogsExclusion Represents the index exclusion filter object from configuration API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsExclusionFilter.md b/docs/v1/LogsExclusionFilter.md index bce3043cb6..0cc2a54093 100644 --- a/docs/v1/LogsExclusionFilter.md +++ b/docs/v1/LogsExclusionFilter.md @@ -1,6 +1,7 @@ # LogsExclusionFilter Exclusion filter is defined by a query, a sampling rule, and a active/inactive toggle. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsFilter.md b/docs/v1/LogsFilter.md index a57ade26c7..564d489761 100644 --- a/docs/v1/LogsFilter.md +++ b/docs/v1/LogsFilter.md @@ -1,6 +1,7 @@ # LogsFilter Filter for logs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsGeoIPParser.md b/docs/v1/LogsGeoIPParser.md index ca4482def5..5b2737bce2 100644 --- a/docs/v1/LogsGeoIPParser.md +++ b/docs/v1/LogsGeoIPParser.md @@ -1,6 +1,7 @@ # LogsGeoIPParser The GeoIP parser takes an IP address attribute and extracts if available the Continent, Country, Subdivision, and City information in the target attribute path. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsGeoIPParserType.md b/docs/v1/LogsGeoIPParserType.md index 5521bd7c0b..5f9bd42711 100644 --- a/docs/v1/LogsGeoIPParserType.md +++ b/docs/v1/LogsGeoIPParserType.md @@ -1,6 +1,7 @@ # LogsGeoIPParserType Type of GeoIP parser. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsGrokParser.md b/docs/v1/LogsGrokParser.md index 4df8fc48d2..fd4f567e52 100644 --- a/docs/v1/LogsGrokParser.md +++ b/docs/v1/LogsGrokParser.md @@ -1,6 +1,7 @@ # LogsGrokParser Create custom grok rules to parse the full message or [a specific attribute of your raw event](https://docs.datadoghq.com/logs/processing/parsing/#advanced-settings). For more information, see the [parsing section](https://docs.datadoghq.com/logs/processing/parsing). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsGrokParserRules.md b/docs/v1/LogsGrokParserRules.md index 6003438da8..fc8f2085c2 100644 --- a/docs/v1/LogsGrokParserRules.md +++ b/docs/v1/LogsGrokParserRules.md @@ -1,6 +1,7 @@ # LogsGrokParserRules Set of rules for the grok parser. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsGrokParserType.md b/docs/v1/LogsGrokParserType.md index a5f6f606c1..0d262b58fc 100644 --- a/docs/v1/LogsGrokParserType.md +++ b/docs/v1/LogsGrokParserType.md @@ -1,6 +1,7 @@ # LogsGrokParserType Type of logs grok parser. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsIndex.md b/docs/v1/LogsIndex.md index fdccffddd9..4653746fe7 100644 --- a/docs/v1/LogsIndex.md +++ b/docs/v1/LogsIndex.md @@ -1,6 +1,7 @@ # LogsIndex Object describing a Datadog Log index. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsIndexListResponse.md b/docs/v1/LogsIndexListResponse.md index fa489fea97..b0ba7e0684 100644 --- a/docs/v1/LogsIndexListResponse.md +++ b/docs/v1/LogsIndexListResponse.md @@ -1,6 +1,7 @@ # LogsIndexListResponse Object with all Index configurations for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsIndexUpdateRequest.md b/docs/v1/LogsIndexUpdateRequest.md index 8ad008a888..cb95eab898 100644 --- a/docs/v1/LogsIndexUpdateRequest.md +++ b/docs/v1/LogsIndexUpdateRequest.md @@ -1,6 +1,7 @@ # LogsIndexUpdateRequest Object for updating a Datadog Log index. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsIndexesApi.md b/docs/v1/LogsIndexesApi.md index 63cb3b80f2..cafc96d4a7 100644 --- a/docs/v1/LogsIndexesApi.md +++ b/docs/v1/LogsIndexesApi.md @@ -76,6 +76,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->create_logs_index: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -95,6 +96,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -150,6 +152,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->get_logs_index: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -169,6 +172,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -223,6 +227,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->get_logs_index_order: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -239,6 +244,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -292,6 +298,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->list_log_indexes: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -308,6 +315,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -380,6 +388,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->update_logs_index: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -400,6 +409,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -458,6 +468,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsIndexesApi->update_logs_index_order: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -477,6 +488,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/LogsIndexesOrder.md b/docs/v1/LogsIndexesOrder.md index 445871531c..f4e724f8b7 100644 --- a/docs/v1/LogsIndexesOrder.md +++ b/docs/v1/LogsIndexesOrder.md @@ -1,6 +1,7 @@ # LogsIndexesOrder Object containing the ordered list of log index names. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsListRequest.md b/docs/v1/LogsListRequest.md index 4d327069f1..0630ea027e 100644 --- a/docs/v1/LogsListRequest.md +++ b/docs/v1/LogsListRequest.md @@ -1,6 +1,7 @@ # LogsListRequest Object to send with the request to retrieve a list of logs from your Organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsListRequestTime.md b/docs/v1/LogsListRequestTime.md index 1795ecca48..fd81d5ed8e 100644 --- a/docs/v1/LogsListRequestTime.md +++ b/docs/v1/LogsListRequestTime.md @@ -1,6 +1,7 @@ # LogsListRequestTime Timeframe to retrieve the log from. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsListResponse.md b/docs/v1/LogsListResponse.md index 0b90e7e23a..862faafe0d 100644 --- a/docs/v1/LogsListResponse.md +++ b/docs/v1/LogsListResponse.md @@ -1,6 +1,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsLookupProcessor.md b/docs/v1/LogsLookupProcessor.md index 9b24b2eea3..5e0db69870 100644 --- a/docs/v1/LogsLookupProcessor.md +++ b/docs/v1/LogsLookupProcessor.md @@ -1,6 +1,7 @@ # LogsLookupProcessor Use the Lookup Processor to define a mapping between a log attribute and a human readable value saved in the processors mapping table. For example, you can use the Lookup Processor to map an internal service ID into a human readable service name. Alternatively, you could also use it to check if the MAC address that just attempted to connect to the production environment belongs to your list of stolen machines. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsLookupProcessorType.md b/docs/v1/LogsLookupProcessorType.md index c5f5602ad9..66b4784659 100644 --- a/docs/v1/LogsLookupProcessorType.md +++ b/docs/v1/LogsLookupProcessorType.md @@ -1,6 +1,7 @@ # LogsLookupProcessorType Type of logs lookup processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsMessageRemapper.md b/docs/v1/LogsMessageRemapper.md index 3990b12f06..4c2f83fd02 100644 --- a/docs/v1/LogsMessageRemapper.md +++ b/docs/v1/LogsMessageRemapper.md @@ -1,6 +1,7 @@ # LogsMessageRemapper The message is a key attribute in Datadog. It is displayed in the message column of the Log Explorer and you can do full string search on it. Use this Processor to define one or more attributes as the official log message. **Note:** If multiple log message remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsMessageRemapperType.md b/docs/v1/LogsMessageRemapperType.md index 1a49d85622..13d5db22a3 100644 --- a/docs/v1/LogsMessageRemapperType.md +++ b/docs/v1/LogsMessageRemapperType.md @@ -1,6 +1,7 @@ # LogsMessageRemapperType Type of logs message remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsPipeline.md b/docs/v1/LogsPipeline.md index b3b77e2e99..0533414924 100644 --- a/docs/v1/LogsPipeline.md +++ b/docs/v1/LogsPipeline.md @@ -1,6 +1,7 @@ # LogsPipeline Pipelines and processors operate on incoming logs, parsing and transforming them into structured attributes for easier querying. **Note**: These endpoints are only available for admin users. Make sure to use an application key created by an admin. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsPipelineList.md b/docs/v1/LogsPipelineList.md index 39ccb3868b..8629702c65 100644 --- a/docs/v1/LogsPipelineList.md +++ b/docs/v1/LogsPipelineList.md @@ -1,6 +1,7 @@ # LogsPipelineList Array of pipeline ID strings. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsPipelineProcessor.md b/docs/v1/LogsPipelineProcessor.md index c826ef3e25..ac907912e9 100644 --- a/docs/v1/LogsPipelineProcessor.md +++ b/docs/v1/LogsPipelineProcessor.md @@ -1,6 +1,7 @@ # LogsPipelineProcessor Nested Pipelines are pipelines within a pipeline. Use Nested Pipelines to split the processing into two steps. For example, first use a high-level filtering such as team and then a second level of filtering based on the integration, service, or any other tag or attribute. A pipeline can contain Nested Pipelines and Processors whereas a Nested Pipeline can only contain Processors. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsPipelineProcessorType.md b/docs/v1/LogsPipelineProcessorType.md index 4cabfe94c9..4d9ad03f0a 100644 --- a/docs/v1/LogsPipelineProcessorType.md +++ b/docs/v1/LogsPipelineProcessorType.md @@ -1,6 +1,7 @@ # LogsPipelineProcessorType Type of logs pipeline processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsPipelinesApi.md b/docs/v1/LogsPipelinesApi.md index a44e50fbd9..28d5a1be6e 100644 --- a/docs/v1/LogsPipelinesApi.md +++ b/docs/v1/LogsPipelinesApi.md @@ -71,6 +71,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->create_logs_pipeline: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -90,6 +91,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -144,6 +146,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->delete_logs_pipeline: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -163,6 +166,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -218,6 +222,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->get_logs_pipeline: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -237,6 +242,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -291,6 +297,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->get_logs_pipeline_order: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -307,6 +314,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -360,6 +368,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->list_logs_pipelines: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -376,6 +385,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -443,6 +453,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->update_logs_pipeline: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -463,6 +474,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -520,6 +532,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsPipelinesApi->update_logs_pipeline_order: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -539,6 +552,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/LogsPipelinesOrder.md b/docs/v1/LogsPipelinesOrder.md index 6750fce674..7b6887d6fc 100644 --- a/docs/v1/LogsPipelinesOrder.md +++ b/docs/v1/LogsPipelinesOrder.md @@ -1,6 +1,7 @@ # LogsPipelinesOrder Object containing the ordered list of pipeline IDs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsProcessor.md b/docs/v1/LogsProcessor.md index 31aae8926c..25c1ef5840 100644 --- a/docs/v1/LogsProcessor.md +++ b/docs/v1/LogsProcessor.md @@ -1,6 +1,7 @@ # LogsProcessor Definition of a logs processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsQueryCompute.md b/docs/v1/LogsQueryCompute.md index 5f9067c5d4..edf1b0747d 100644 --- a/docs/v1/LogsQueryCompute.md +++ b/docs/v1/LogsQueryCompute.md @@ -1,6 +1,7 @@ # LogsQueryCompute Define computation for a log query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsServiceRemapper.md b/docs/v1/LogsServiceRemapper.md index 5a17ae62a5..9c036c6fb8 100644 --- a/docs/v1/LogsServiceRemapper.md +++ b/docs/v1/LogsServiceRemapper.md @@ -1,6 +1,7 @@ # LogsServiceRemapper Use this processor if you want to assign one or more attributes as the official service. **Note:** If multiple service remapper processors can be applied to a given log, only the first one (according to the pipeline order) is taken into account. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsServiceRemapperType.md b/docs/v1/LogsServiceRemapperType.md index e52398acd7..8f6712f3f0 100644 --- a/docs/v1/LogsServiceRemapperType.md +++ b/docs/v1/LogsServiceRemapperType.md @@ -1,6 +1,7 @@ # LogsServiceRemapperType Type of logs service remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsSort.md b/docs/v1/LogsSort.md index 76e95bb024..4dbab728d9 100644 --- a/docs/v1/LogsSort.md +++ b/docs/v1/LogsSort.md @@ -1,6 +1,7 @@ # LogsSort Time-ascending `asc` or time-descending `desc`results. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsStatusRemapper.md b/docs/v1/LogsStatusRemapper.md index 6ddb7839f8..b30149b303 100644 --- a/docs/v1/LogsStatusRemapper.md +++ b/docs/v1/LogsStatusRemapper.md @@ -1,6 +1,7 @@ # LogsStatusRemapper Use this Processor if you want to assign some attributes as the official status. Each incoming status value is mapped as follows. - Integers from 0 to 7 map to the Syslog severity standards - Strings beginning with `emerg` or f (case-insensitive) map to `emerg` (0) - Strings beginning with `a` (case-insensitive) map to `alert` (1) - Strings beginning with `c` (case-insensitive) map to `critical` (2) - Strings beginning with `err` (case-insensitive) map to `error` (3) - Strings beginning with `w` (case-insensitive) map to `warning` (4) - Strings beginning with `n` (case-insensitive) map to `notice` (5) - Strings beginning with `i` (case-insensitive) map to `info` (6) - Strings beginning with `d`, `trace` or `verbose` (case-insensitive) map to `debug` (7) - Strings beginning with `o` or matching `OK` or `Success` (case-insensitive) map to OK - All others map to `info` (6) **Note:** If multiple log status remapper processors can be applied to a given log, only the first one (according to the pipelines order) is taken into account. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsStatusRemapperType.md b/docs/v1/LogsStatusRemapperType.md index fe33ef9757..f22f2c945b 100644 --- a/docs/v1/LogsStatusRemapperType.md +++ b/docs/v1/LogsStatusRemapperType.md @@ -1,6 +1,7 @@ # LogsStatusRemapperType Type of logs status remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsStringBuilderProcessor.md b/docs/v1/LogsStringBuilderProcessor.md index d24e11f6bb..9fc429d5db 100644 --- a/docs/v1/LogsStringBuilderProcessor.md +++ b/docs/v1/LogsStringBuilderProcessor.md @@ -1,6 +1,7 @@ # LogsStringBuilderProcessor Use the string builder processor to add a new attribute (without spaces or special characters) to a log with the result of the provided template. This enables aggregation of different attributes or raw strings into a single attribute. The template is defined by both raw text and blocks with the syntax `%{attribute_path}`. **Notes**: - The processor only accepts attributes with values or an array of values in the blocks. - If an attribute cannot be used (object or array of object), it is replaced by an empty string or the entire operation is skipped depending on your selection. - If the target attribute already exists, it is overwritten by the result of the template. - Results of the template cannot exceed 256 characters. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsStringBuilderProcessorType.md b/docs/v1/LogsStringBuilderProcessorType.md index 8edff49a9b..8c09ed2a87 100644 --- a/docs/v1/LogsStringBuilderProcessorType.md +++ b/docs/v1/LogsStringBuilderProcessorType.md @@ -1,6 +1,7 @@ # LogsStringBuilderProcessorType Type of logs string builder processor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsTraceRemapper.md b/docs/v1/LogsTraceRemapper.md index 257b20f4c2..d3424e73e0 100644 --- a/docs/v1/LogsTraceRemapper.md +++ b/docs/v1/LogsTraceRemapper.md @@ -1,6 +1,7 @@ # LogsTraceRemapper There are two ways to improve correlation between application traces and logs. 1. Follow the documentation on [how to inject a trace ID in the application logs](https://docs.datadoghq.com/tracing/connect_logs_and_traces) and by default log integrations take care of all the rest of the setup. 2. Use the Trace remapper processor to define a log attribute as its associated trace ID. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsTraceRemapperType.md b/docs/v1/LogsTraceRemapperType.md index a5c3c3e68b..9ddf57d6c1 100644 --- a/docs/v1/LogsTraceRemapperType.md +++ b/docs/v1/LogsTraceRemapperType.md @@ -1,6 +1,7 @@ # LogsTraceRemapperType Type of logs trace remapper. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsURLParser.md b/docs/v1/LogsURLParser.md index 2237d6121b..d7f75a76a6 100644 --- a/docs/v1/LogsURLParser.md +++ b/docs/v1/LogsURLParser.md @@ -1,6 +1,7 @@ # LogsURLParser This processor extracts query parameters and other important parameters from a URL. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsURLParserType.md b/docs/v1/LogsURLParserType.md index 7a6105026b..64c7422d94 100644 --- a/docs/v1/LogsURLParserType.md +++ b/docs/v1/LogsURLParserType.md @@ -1,6 +1,7 @@ # LogsURLParserType Type of logs URL parser. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsUserAgentParser.md b/docs/v1/LogsUserAgentParser.md index d76bbc4db4..361738ad0c 100644 --- a/docs/v1/LogsUserAgentParser.md +++ b/docs/v1/LogsUserAgentParser.md @@ -1,6 +1,7 @@ # LogsUserAgentParser The User-Agent parser takes a User-Agent attribute and extracts the OS, browser, device, and other user data. It recognizes major bots like the Google Bot, Yahoo Slurp, and Bing. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/LogsUserAgentParserType.md b/docs/v1/LogsUserAgentParserType.md index 75c6f79faf..34d92039d0 100644 --- a/docs/v1/LogsUserAgentParserType.md +++ b/docs/v1/LogsUserAgentParserType.md @@ -1,6 +1,7 @@ # LogsUserAgentParserType Type of logs User-Agent parser. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricMetadata.md b/docs/v1/MetricMetadata.md index 169db77ff7..df7ab07f3a 100644 --- a/docs/v1/MetricMetadata.md +++ b/docs/v1/MetricMetadata.md @@ -1,6 +1,7 @@ # MetricMetadata Object with all metric related metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricSearchResponse.md b/docs/v1/MetricSearchResponse.md index c4e94f0864..2a7ca9550b 100644 --- a/docs/v1/MetricSearchResponse.md +++ b/docs/v1/MetricSearchResponse.md @@ -1,6 +1,7 @@ # MetricSearchResponse Object containing the list of metrics matching the search query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricSearchResponseResults.md b/docs/v1/MetricSearchResponseResults.md index da9cbf4409..83e1ed1407 100644 --- a/docs/v1/MetricSearchResponseResults.md +++ b/docs/v1/MetricSearchResponseResults.md @@ -1,6 +1,7 @@ # MetricSearchResponseResults Search result. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricsApi.md b/docs/v1/MetricsApi.md index 21eb16f3f1..ebe586365a 100644 --- a/docs/v1/MetricsApi.md +++ b/docs/v1/MetricsApi.md @@ -57,6 +57,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->get_metric_metadata: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -76,6 +77,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -141,6 +143,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_active_metrics: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -161,6 +164,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -216,6 +220,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_metrics: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -235,6 +240,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -292,6 +298,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->query_metrics: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -313,6 +320,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -377,6 +385,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->update_metric_metadata: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -397,6 +406,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/MetricsListResponse.md b/docs/v1/MetricsListResponse.md index fa99d07307..bda67f2dde 100644 --- a/docs/v1/MetricsListResponse.md +++ b/docs/v1/MetricsListResponse.md @@ -1,6 +1,7 @@ # MetricsListResponse Object listing all metric names stored by Datadog since a given time. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricsQueryMetadata.md b/docs/v1/MetricsQueryMetadata.md index 50ee8443fd..d5d2061172 100644 --- a/docs/v1/MetricsQueryMetadata.md +++ b/docs/v1/MetricsQueryMetadata.md @@ -1,6 +1,7 @@ # MetricsQueryMetadata Object containing all metric names returned and their associated metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricsQueryResponse.md b/docs/v1/MetricsQueryResponse.md index 811fb961de..ed5fed2b63 100644 --- a/docs/v1/MetricsQueryResponse.md +++ b/docs/v1/MetricsQueryResponse.md @@ -1,6 +1,7 @@ # MetricsQueryResponse Response Object that includes your query and the list of metrics retrieved. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MetricsQueryUnit.md b/docs/v1/MetricsQueryUnit.md index 20f8d1029b..013186e96f 100644 --- a/docs/v1/MetricsQueryUnit.md +++ b/docs/v1/MetricsQueryUnit.md @@ -1,6 +1,7 @@ # MetricsQueryUnit Object containing the metric unit family, scale factor, name, and short name. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Monitor.md b/docs/v1/Monitor.md index a73a0a0931..3b9cd33669 100644 --- a/docs/v1/Monitor.md +++ b/docs/v1/Monitor.md @@ -1,6 +1,7 @@ # Monitor Object describing a monitor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorDeviceID.md b/docs/v1/MonitorDeviceID.md index 92f3b6728c..4010d281e7 100644 --- a/docs/v1/MonitorDeviceID.md +++ b/docs/v1/MonitorDeviceID.md @@ -1,6 +1,7 @@ # MonitorDeviceID ID of the device the Synthetics monitor is running on. Same as `SyntheticsDeviceID`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorOptions.md b/docs/v1/MonitorOptions.md index 6a16d44f9d..78ced35032 100644 --- a/docs/v1/MonitorOptions.md +++ b/docs/v1/MonitorOptions.md @@ -1,6 +1,7 @@ # MonitorOptions List of options associated with your monitor. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorOptionsAggregation.md b/docs/v1/MonitorOptionsAggregation.md index 4681ce7118..c9c671dd86 100644 --- a/docs/v1/MonitorOptionsAggregation.md +++ b/docs/v1/MonitorOptionsAggregation.md @@ -1,6 +1,7 @@ # MonitorOptionsAggregation Type of aggregation performed in the monitor query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorOverallStates.md b/docs/v1/MonitorOverallStates.md index b954ed6e9e..e5eaff56e8 100644 --- a/docs/v1/MonitorOverallStates.md +++ b/docs/v1/MonitorOverallStates.md @@ -1,6 +1,7 @@ # MonitorOverallStates The different states your monitor can be in. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorState.md b/docs/v1/MonitorState.md index 2d3798d779..ba61951e28 100644 --- a/docs/v1/MonitorState.md +++ b/docs/v1/MonitorState.md @@ -1,6 +1,7 @@ # MonitorState Wrapper object with the different monitor states. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorStateGroup.md b/docs/v1/MonitorStateGroup.md index 00dc66f178..22af64ad1b 100644 --- a/docs/v1/MonitorStateGroup.md +++ b/docs/v1/MonitorStateGroup.md @@ -1,6 +1,7 @@ # MonitorStateGroup Monitor state for a single group. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorSummaryWidgetDefinition.md b/docs/v1/MonitorSummaryWidgetDefinition.md index 9352d3cfc5..3ecb36d71f 100644 --- a/docs/v1/MonitorSummaryWidgetDefinition.md +++ b/docs/v1/MonitorSummaryWidgetDefinition.md @@ -1,6 +1,7 @@ # MonitorSummaryWidgetDefinition The monitor summary widget displays a summary view of all your Datadog monitors, or a subset based on a query. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorSummaryWidgetDefinitionType.md b/docs/v1/MonitorSummaryWidgetDefinitionType.md index c88d753ed1..6435602096 100644 --- a/docs/v1/MonitorSummaryWidgetDefinitionType.md +++ b/docs/v1/MonitorSummaryWidgetDefinitionType.md @@ -1,6 +1,7 @@ # MonitorSummaryWidgetDefinitionType Type of the monitor summary widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorThresholdWindowOptions.md b/docs/v1/MonitorThresholdWindowOptions.md index f4c5f03caf..438423d3ad 100644 --- a/docs/v1/MonitorThresholdWindowOptions.md +++ b/docs/v1/MonitorThresholdWindowOptions.md @@ -1,6 +1,7 @@ # MonitorThresholdWindowOptions Alerting time window options. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorThresholds.md b/docs/v1/MonitorThresholds.md index e4b6515a80..b1403f4d12 100644 --- a/docs/v1/MonitorThresholds.md +++ b/docs/v1/MonitorThresholds.md @@ -1,6 +1,7 @@ # MonitorThresholds List of the different monitor threshold available. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorType.md b/docs/v1/MonitorType.md index f7e9e83542..2dc4d73828 100644 --- a/docs/v1/MonitorType.md +++ b/docs/v1/MonitorType.md @@ -1,6 +1,7 @@ # MonitorType The type of the monitor. For more information about `type`, see the [monitor options](https://docs.datadoghq.com/monitors/guide/monitor_api_options/) docs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorUpdateRequest.md b/docs/v1/MonitorUpdateRequest.md index a449c2f205..de721b9e24 100644 --- a/docs/v1/MonitorUpdateRequest.md +++ b/docs/v1/MonitorUpdateRequest.md @@ -1,6 +1,7 @@ # MonitorUpdateRequest Object describing a monitor update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/MonitorsApi.md b/docs/v1/MonitorsApi.md index acee115def..1876171132 100644 --- a/docs/v1/MonitorsApi.md +++ b/docs/v1/MonitorsApi.md @@ -61,6 +61,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->check_can_delete_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -80,6 +81,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -212,6 +214,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->create_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -231,6 +234,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -296,6 +300,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->delete_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -316,6 +321,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -383,6 +389,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->get_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -403,6 +410,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -467,6 +475,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->list_monitors: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -493,6 +502,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -625,6 +635,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->update_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -645,6 +656,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -778,6 +790,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MonitorsApi->validate_monitor: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -797,6 +810,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/NoteWidgetDefinition.md b/docs/v1/NoteWidgetDefinition.md index ae3a0c3f3d..39be84a26c 100644 --- a/docs/v1/NoteWidgetDefinition.md +++ b/docs/v1/NoteWidgetDefinition.md @@ -1,6 +1,7 @@ # NoteWidgetDefinition The notes and links widget is similar to free text widget, but allows for more formatting options. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/NoteWidgetDefinitionType.md b/docs/v1/NoteWidgetDefinitionType.md index 24ebc12b8e..d686931861 100644 --- a/docs/v1/NoteWidgetDefinitionType.md +++ b/docs/v1/NoteWidgetDefinitionType.md @@ -1,6 +1,7 @@ # NoteWidgetDefinitionType Type of the note widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Organization.md b/docs/v1/Organization.md index f7b397c105..a933834143 100644 --- a/docs/v1/Organization.md +++ b/docs/v1/Organization.md @@ -1,6 +1,7 @@ # Organization Create, edit, and manage organizations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationBilling.md b/docs/v1/OrganizationBilling.md index 893735a0b0..53747c90e7 100644 --- a/docs/v1/OrganizationBilling.md +++ b/docs/v1/OrganizationBilling.md @@ -1,6 +1,7 @@ # OrganizationBilling A JSON array of billing type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationCreateBody.md b/docs/v1/OrganizationCreateBody.md index e60e45c790..4f79b29321 100644 --- a/docs/v1/OrganizationCreateBody.md +++ b/docs/v1/OrganizationCreateBody.md @@ -1,6 +1,7 @@ # OrganizationCreateBody Object describing an organization to create. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationCreateResponse.md b/docs/v1/OrganizationCreateResponse.md index 4a44dd2d85..02ced763a8 100644 --- a/docs/v1/OrganizationCreateResponse.md +++ b/docs/v1/OrganizationCreateResponse.md @@ -1,6 +1,7 @@ # OrganizationCreateResponse Response object for an organization creation. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationListResponse.md b/docs/v1/OrganizationListResponse.md index 60aaae9a0d..79a7be61ef 100644 --- a/docs/v1/OrganizationListResponse.md +++ b/docs/v1/OrganizationListResponse.md @@ -1,6 +1,7 @@ # OrganizationListResponse Response with the list of organizations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationResponse.md b/docs/v1/OrganizationResponse.md index b35c234ffb..d74bf83190 100644 --- a/docs/v1/OrganizationResponse.md +++ b/docs/v1/OrganizationResponse.md @@ -1,6 +1,7 @@ # OrganizationResponse Response with an organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSettings.md b/docs/v1/OrganizationSettings.md index 49ae37c987..8fa7a62829 100644 --- a/docs/v1/OrganizationSettings.md +++ b/docs/v1/OrganizationSettings.md @@ -1,6 +1,7 @@ # OrganizationSettings A JSON array of settings. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSettingsSaml.md b/docs/v1/OrganizationSettingsSaml.md index 2cbf98e543..1d04260b70 100644 --- a/docs/v1/OrganizationSettingsSaml.md +++ b/docs/v1/OrganizationSettingsSaml.md @@ -1,6 +1,7 @@ # OrganizationSettingsSaml Set the boolean property enabled to enable or disable single sign on with SAML. See the SAML documentation for more information about all SAML settings. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md b/docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md index 3c5d0ccd9c..e51d6a781e 100644 --- a/docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md +++ b/docs/v1/OrganizationSettingsSamlAutocreateUsersDomains.md @@ -1,6 +1,7 @@ # OrganizationSettingsSamlAutocreateUsersDomains Has two properties, `enabled` (boolean) and `domains`, which is a list of domains without the @ symbol. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md b/docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md index 5607fb473f..1fd5258be1 100644 --- a/docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md +++ b/docs/v1/OrganizationSettingsSamlIdpInitiatedLogin.md @@ -1,6 +1,7 @@ # OrganizationSettingsSamlIdpInitiatedLogin Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSettingsSamlStrictMode.md b/docs/v1/OrganizationSettingsSamlStrictMode.md index 419a739e3c..1c05fb1901 100644 --- a/docs/v1/OrganizationSettingsSamlStrictMode.md +++ b/docs/v1/OrganizationSettingsSamlStrictMode.md @@ -1,6 +1,7 @@ # OrganizationSettingsSamlStrictMode Has one property enabled (boolean). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationSubscription.md b/docs/v1/OrganizationSubscription.md index b8bdd57e7e..a11535ba83 100644 --- a/docs/v1/OrganizationSubscription.md +++ b/docs/v1/OrganizationSubscription.md @@ -1,6 +1,7 @@ # OrganizationSubscription Subscription definition. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/OrganizationsApi.md b/docs/v1/OrganizationsApi.md index 5175b33010..938c1cfbd9 100644 --- a/docs/v1/OrganizationsApi.md +++ b/docs/v1/OrganizationsApi.md @@ -65,6 +65,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling OrganizationsApi->create_child_org: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -84,6 +85,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -139,6 +141,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling OrganizationsApi->get_org: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -158,6 +161,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -212,6 +216,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling OrganizationsApi->list_orgs: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -228,6 +233,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -317,6 +323,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling OrganizationsApi->update_org: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -337,6 +344,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -393,6 +401,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling OrganizationsApi->upload_id_p_for_org: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -413,6 +422,7 @@ Name | Type | Description | Notes - **Content-Type**: multipart/form-data - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/PagerDutyIntegrationApi.md b/docs/v1/PagerDutyIntegrationApi.md index f41a2f6663..6cf385e134 100644 --- a/docs/v1/PagerDutyIntegrationApi.md +++ b/docs/v1/PagerDutyIntegrationApi.md @@ -59,6 +59,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling PagerDutyIntegrationApi->create_pager_duty_integration_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -78,6 +79,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -132,6 +134,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling PagerDutyIntegrationApi->delete_pager_duty_integration_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -151,6 +154,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -206,6 +210,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling PagerDutyIntegrationApi->get_pager_duty_integration_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -225,6 +230,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -282,6 +288,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling PagerDutyIntegrationApi->update_pager_duty_integration_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -302,6 +309,7 @@ void (empty response body) - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/PagerDutyService.md b/docs/v1/PagerDutyService.md index 0a756e93bb..05b47ba9c0 100644 --- a/docs/v1/PagerDutyService.md +++ b/docs/v1/PagerDutyService.md @@ -1,6 +1,7 @@ # PagerDutyService The PagerDuty service that is available for integration with Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/PagerDutyServiceKey.md b/docs/v1/PagerDutyServiceKey.md index ca3ae4cdc8..40003e794b 100644 --- a/docs/v1/PagerDutyServiceKey.md +++ b/docs/v1/PagerDutyServiceKey.md @@ -1,6 +1,7 @@ # PagerDutyServiceKey PagerDuty service object key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/PagerDutyServiceName.md b/docs/v1/PagerDutyServiceName.md index f48aff95ca..cc9f0fab63 100644 --- a/docs/v1/PagerDutyServiceName.md +++ b/docs/v1/PagerDutyServiceName.md @@ -1,6 +1,7 @@ # PagerDutyServiceName PagerDuty service object name. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/Point.md b/docs/v1/Point.md index f05557eb83..eb27ee1299 100644 --- a/docs/v1/Point.md +++ b/docs/v1/Point.md @@ -1,6 +1,7 @@ # Point Array of timeseries points. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ProcessQueryDefinition.md b/docs/v1/ProcessQueryDefinition.md index dc9a0095b7..c057a3a9db 100644 --- a/docs/v1/ProcessQueryDefinition.md +++ b/docs/v1/ProcessQueryDefinition.md @@ -1,6 +1,7 @@ # ProcessQueryDefinition The process query to use in the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/QuerySortOrder.md b/docs/v1/QuerySortOrder.md index 3aa30f45d5..286472ed01 100644 --- a/docs/v1/QuerySortOrder.md +++ b/docs/v1/QuerySortOrder.md @@ -1,6 +1,7 @@ # QuerySortOrder Direction of sort. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/QueryValueWidgetDefinition.md b/docs/v1/QueryValueWidgetDefinition.md index 9faa9b2369..85e6e0c2b6 100644 --- a/docs/v1/QueryValueWidgetDefinition.md +++ b/docs/v1/QueryValueWidgetDefinition.md @@ -1,6 +1,7 @@ # QueryValueWidgetDefinition Query values display the current value of a given metric, APM, or log query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/QueryValueWidgetDefinitionType.md b/docs/v1/QueryValueWidgetDefinitionType.md index 8e7a26be4f..f7f2ed9196 100644 --- a/docs/v1/QueryValueWidgetDefinitionType.md +++ b/docs/v1/QueryValueWidgetDefinitionType.md @@ -1,6 +1,7 @@ # QueryValueWidgetDefinitionType Type of the query value widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/QueryValueWidgetRequest.md b/docs/v1/QueryValueWidgetRequest.md index 9d487d6096..1d94041809 100644 --- a/docs/v1/QueryValueWidgetRequest.md +++ b/docs/v1/QueryValueWidgetRequest.md @@ -1,6 +1,7 @@ # QueryValueWidgetRequest Updated query value widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOBulkDelete.md b/docs/v1/SLOBulkDelete.md index 688d141e0c..a76df1229d 100644 --- a/docs/v1/SLOBulkDelete.md +++ b/docs/v1/SLOBulkDelete.md @@ -1,6 +1,7 @@ # SLOBulkDelete A map of service level objective object IDs to arrays of timeframes, which indicate the thresholds to delete for each ID. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOBulkDeleteError.md b/docs/v1/SLOBulkDeleteError.md index 19b802e246..0683597181 100644 --- a/docs/v1/SLOBulkDeleteError.md +++ b/docs/v1/SLOBulkDeleteError.md @@ -1,6 +1,7 @@ # SLOBulkDeleteError Object describing the error. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOBulkDeleteResponse.md b/docs/v1/SLOBulkDeleteResponse.md index 2512e7d1c3..56b49f34a3 100644 --- a/docs/v1/SLOBulkDeleteResponse.md +++ b/docs/v1/SLOBulkDeleteResponse.md @@ -1,6 +1,7 @@ # SLOBulkDeleteResponse The bulk partial delete service level objective object endpoint response. This endpoint operates on multiple service level objective objects, so it may be partially successful. In such cases, the \"data\" and \"error\" fields in this response indicate which deletions succeeded and failed. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOBulkDeleteResponseData.md b/docs/v1/SLOBulkDeleteResponseData.md index f2aea7b7e6..8c071fbe5e 100644 --- a/docs/v1/SLOBulkDeleteResponseData.md +++ b/docs/v1/SLOBulkDeleteResponseData.md @@ -1,6 +1,7 @@ # SLOBulkDeleteResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrection.md b/docs/v1/SLOCorrection.md index 76f9c45b23..9008d8256c 100644 --- a/docs/v1/SLOCorrection.md +++ b/docs/v1/SLOCorrection.md @@ -1,6 +1,7 @@ # SLOCorrection The response object of a list of SLO corrections + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionCategory.md b/docs/v1/SLOCorrectionCategory.md index 038f4e72df..375c2cf973 100644 --- a/docs/v1/SLOCorrectionCategory.md +++ b/docs/v1/SLOCorrectionCategory.md @@ -1,6 +1,7 @@ # SLOCorrectionCategory Category the SLO correction belongs to + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionCreateData.md b/docs/v1/SLOCorrectionCreateData.md index 4545cee242..4bfe0edce7 100644 --- a/docs/v1/SLOCorrectionCreateData.md +++ b/docs/v1/SLOCorrectionCreateData.md @@ -1,6 +1,7 @@ # SLOCorrectionCreateData The data object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionCreateRequest.md b/docs/v1/SLOCorrectionCreateRequest.md index 82f2cd6b9d..2f74974d00 100644 --- a/docs/v1/SLOCorrectionCreateRequest.md +++ b/docs/v1/SLOCorrectionCreateRequest.md @@ -1,6 +1,7 @@ # SLOCorrectionCreateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionCreateRequestAttributes.md b/docs/v1/SLOCorrectionCreateRequestAttributes.md index f40bf225fd..877ab2cdcb 100644 --- a/docs/v1/SLOCorrectionCreateRequestAttributes.md +++ b/docs/v1/SLOCorrectionCreateRequestAttributes.md @@ -1,6 +1,7 @@ # SLOCorrectionCreateRequestAttributes The attribute object associated with the SLO correction to be created + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionListResponse.md b/docs/v1/SLOCorrectionListResponse.md index 7f10a243c0..3d524dfcd5 100644 --- a/docs/v1/SLOCorrectionListResponse.md +++ b/docs/v1/SLOCorrectionListResponse.md @@ -1,6 +1,7 @@ # SLOCorrectionListResponse A list of SLO correction objects + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionResponse.md b/docs/v1/SLOCorrectionResponse.md index b59c9b7a41..ae05ec9690 100644 --- a/docs/v1/SLOCorrectionResponse.md +++ b/docs/v1/SLOCorrectionResponse.md @@ -1,6 +1,7 @@ # SLOCorrectionResponse The response object of an SLO correction + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionResponseAttributes.md b/docs/v1/SLOCorrectionResponseAttributes.md index 8b7466bad8..e3791c5c92 100644 --- a/docs/v1/SLOCorrectionResponseAttributes.md +++ b/docs/v1/SLOCorrectionResponseAttributes.md @@ -1,6 +1,7 @@ # SLOCorrectionResponseAttributes The attribute object associated with the SLO correction + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionType.md b/docs/v1/SLOCorrectionType.md index 54583e7b18..5fd4066672 100644 --- a/docs/v1/SLOCorrectionType.md +++ b/docs/v1/SLOCorrectionType.md @@ -1,6 +1,7 @@ # SLOCorrectionType SLO correction resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionUpdateData.md b/docs/v1/SLOCorrectionUpdateData.md index 6656b4a3fa..9f50add8d8 100644 --- a/docs/v1/SLOCorrectionUpdateData.md +++ b/docs/v1/SLOCorrectionUpdateData.md @@ -1,6 +1,7 @@ # SLOCorrectionUpdateData The data object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionUpdateRequest.md b/docs/v1/SLOCorrectionUpdateRequest.md index d16c49c963..bbb815ab13 100644 --- a/docs/v1/SLOCorrectionUpdateRequest.md +++ b/docs/v1/SLOCorrectionUpdateRequest.md @@ -1,6 +1,7 @@ # SLOCorrectionUpdateRequest An object that defines a correction to be applied to an SLO + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOCorrectionUpdateRequestAttributes.md b/docs/v1/SLOCorrectionUpdateRequestAttributes.md index e3343ea50c..10904c1a74 100644 --- a/docs/v1/SLOCorrectionUpdateRequestAttributes.md +++ b/docs/v1/SLOCorrectionUpdateRequestAttributes.md @@ -1,6 +1,7 @@ # SLOCorrectionUpdateRequestAttributes The attribute object associated with the SLO correction to be updated + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLODeleteResponse.md b/docs/v1/SLODeleteResponse.md index 318d3ca4d8..fe25c57f2e 100644 --- a/docs/v1/SLODeleteResponse.md +++ b/docs/v1/SLODeleteResponse.md @@ -1,6 +1,7 @@ # SLODeleteResponse A response list of all service level objective deleted. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOErrorBudgetRemainingData.md b/docs/v1/SLOErrorBudgetRemainingData.md index a4ea32903d..76f6461112 100644 --- a/docs/v1/SLOErrorBudgetRemainingData.md +++ b/docs/v1/SLOErrorBudgetRemainingData.md @@ -1,6 +1,7 @@ # SLOErrorBudgetRemainingData A mapping of threshold `timeframe` to the remaining error budget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOErrorTimeframe.md b/docs/v1/SLOErrorTimeframe.md index 19a30ed727..b6d9c26368 100644 --- a/docs/v1/SLOErrorTimeframe.md +++ b/docs/v1/SLOErrorTimeframe.md @@ -1,6 +1,7 @@ # SLOErrorTimeframe The timeframe of the threshold associated with this error or \"all\" if all thresholds are affected. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryMetrics.md b/docs/v1/SLOHistoryMetrics.md index fca8954e07..040b26f8e2 100644 --- a/docs/v1/SLOHistoryMetrics.md +++ b/docs/v1/SLOHistoryMetrics.md @@ -1,6 +1,7 @@ # SLOHistoryMetrics A `metric` based SLO history response. This is not included in responses for `monitor` based SLOs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryMetricsSeries.md b/docs/v1/SLOHistoryMetricsSeries.md index bf46c7270d..4906d8b992 100644 --- a/docs/v1/SLOHistoryMetricsSeries.md +++ b/docs/v1/SLOHistoryMetricsSeries.md @@ -1,6 +1,7 @@ # SLOHistoryMetricsSeries A representation of `metric` based SLO time series for the provided queries. This is the same response type from `batch_query` endpoint. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryMetricsSeriesMetadata.md b/docs/v1/SLOHistoryMetricsSeriesMetadata.md index 3f5cfd44b3..6a22b05792 100644 --- a/docs/v1/SLOHistoryMetricsSeriesMetadata.md +++ b/docs/v1/SLOHistoryMetricsSeriesMetadata.md @@ -1,6 +1,7 @@ # SLOHistoryMetricsSeriesMetadata Query metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md b/docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md index b3d2ccf4a1..7c30f47432 100644 --- a/docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md +++ b/docs/v1/SLOHistoryMetricsSeriesMetadataUnit.md @@ -1,6 +1,7 @@ # SLOHistoryMetricsSeriesMetadataUnit An Object of metric units. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryResponse.md b/docs/v1/SLOHistoryResponse.md index cdf2ad194e..58d9ed4af7 100644 --- a/docs/v1/SLOHistoryResponse.md +++ b/docs/v1/SLOHistoryResponse.md @@ -1,6 +1,7 @@ # SLOHistoryResponse A service level objective history response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryResponseData.md b/docs/v1/SLOHistoryResponseData.md index 0e0a6f56ef..c37414ebf7 100644 --- a/docs/v1/SLOHistoryResponseData.md +++ b/docs/v1/SLOHistoryResponseData.md @@ -1,6 +1,7 @@ # SLOHistoryResponseData An array of service level objective objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistoryResponseError.md b/docs/v1/SLOHistoryResponseError.md index 8a4555af2d..62597db9ae 100644 --- a/docs/v1/SLOHistoryResponseError.md +++ b/docs/v1/SLOHistoryResponseError.md @@ -1,6 +1,7 @@ # SLOHistoryResponseError A service level objective response containing the requested history. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOHistorySLIData.md b/docs/v1/SLOHistorySLIData.md index 61e33038d8..90dc71595c 100644 --- a/docs/v1/SLOHistorySLIData.md +++ b/docs/v1/SLOHistorySLIData.md @@ -1,6 +1,7 @@ # SLOHistorySLIData An object that holds an SLI value and its associated data. It can represent an SLO's overall SLI value. This can also represent the SLI value for a specific monitor in multi-monitor SLOs, or a group in grouped SLOs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOListResponse.md b/docs/v1/SLOListResponse.md index 1c3755e81d..9eaeeb6cac 100644 --- a/docs/v1/SLOListResponse.md +++ b/docs/v1/SLOListResponse.md @@ -1,6 +1,7 @@ # SLOListResponse A response with one or more service level objective. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOResponse.md b/docs/v1/SLOResponse.md index 80dceda662..d32fc8c5ae 100644 --- a/docs/v1/SLOResponse.md +++ b/docs/v1/SLOResponse.md @@ -1,6 +1,7 @@ # SLOResponse A service level objective response containing a single service level objective. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOThreshold.md b/docs/v1/SLOThreshold.md index 625e1d96c8..4c47c85373 100644 --- a/docs/v1/SLOThreshold.md +++ b/docs/v1/SLOThreshold.md @@ -1,6 +1,7 @@ # SLOThreshold SLO thresholds (target and optionally warning) for a single time window. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOTimeframe.md b/docs/v1/SLOTimeframe.md index a9257efb6e..fb3225c2bf 100644 --- a/docs/v1/SLOTimeframe.md +++ b/docs/v1/SLOTimeframe.md @@ -1,6 +1,7 @@ # SLOTimeframe The SLO time window options. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOType.md b/docs/v1/SLOType.md index b50372a00a..46b8d8e8a0 100644 --- a/docs/v1/SLOType.md +++ b/docs/v1/SLOType.md @@ -1,6 +1,7 @@ # SLOType The type of the service level objective. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOTypeNumeric.md b/docs/v1/SLOTypeNumeric.md index 33b91a64ec..6ce75424aa 100644 --- a/docs/v1/SLOTypeNumeric.md +++ b/docs/v1/SLOTypeNumeric.md @@ -1,6 +1,7 @@ # SLOTypeNumeric A numeric representation of the type of the service level objective (`0` for monitor, `1` for metric). Always included in service level objective responses. Ignored in create/update requests. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOWidgetDefinition.md b/docs/v1/SLOWidgetDefinition.md index 8fc9503e87..8bb2e22518 100644 --- a/docs/v1/SLOWidgetDefinition.md +++ b/docs/v1/SLOWidgetDefinition.md @@ -1,6 +1,7 @@ # SLOWidgetDefinition Use the SLO and uptime widget to track your SLOs (Service Level Objectives) and uptime on screenboards and timeboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SLOWidgetDefinitionType.md b/docs/v1/SLOWidgetDefinitionType.md index 349553d954..a87837ab5f 100644 --- a/docs/v1/SLOWidgetDefinitionType.md +++ b/docs/v1/SLOWidgetDefinitionType.md @@ -1,6 +1,7 @@ # SLOWidgetDefinitionType Type of the SLO widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ScatterPlotRequest.md b/docs/v1/ScatterPlotRequest.md index 6a65d5b476..25a1ec5f12 100644 --- a/docs/v1/ScatterPlotRequest.md +++ b/docs/v1/ScatterPlotRequest.md @@ -1,6 +1,7 @@ # ScatterPlotRequest Updated scatter plot. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ScatterPlotWidgetDefinition.md b/docs/v1/ScatterPlotWidgetDefinition.md index 4a155e30cb..f4d3eb2bf7 100644 --- a/docs/v1/ScatterPlotWidgetDefinition.md +++ b/docs/v1/ScatterPlotWidgetDefinition.md @@ -1,6 +1,7 @@ # ScatterPlotWidgetDefinition The scatter plot visualization allows you to graph a chosen scope over two different metrics with their respective aggregation. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ScatterPlotWidgetDefinitionRequests.md b/docs/v1/ScatterPlotWidgetDefinitionRequests.md index fd348acf8a..3ae535c4ba 100644 --- a/docs/v1/ScatterPlotWidgetDefinitionRequests.md +++ b/docs/v1/ScatterPlotWidgetDefinitionRequests.md @@ -1,6 +1,7 @@ # ScatterPlotWidgetDefinitionRequests Widget definition. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ScatterPlotWidgetDefinitionType.md b/docs/v1/ScatterPlotWidgetDefinitionType.md index 9c3ba5c0e2..e3b305cb53 100644 --- a/docs/v1/ScatterPlotWidgetDefinitionType.md +++ b/docs/v1/ScatterPlotWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ScatterPlotWidgetDefinitionType Type of the scatter plot widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceLevelObjective.md b/docs/v1/ServiceLevelObjective.md index c52a4f7e23..77cf2c3d8c 100644 --- a/docs/v1/ServiceLevelObjective.md +++ b/docs/v1/ServiceLevelObjective.md @@ -1,6 +1,7 @@ # ServiceLevelObjective A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceLevelObjectiveCorrectionsApi.md b/docs/v1/ServiceLevelObjectiveCorrectionsApi.md index 76124e910b..4045d562b5 100644 --- a/docs/v1/ServiceLevelObjectiveCorrectionsApi.md +++ b/docs/v1/ServiceLevelObjectiveCorrectionsApi.md @@ -70,6 +70,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectiveCorrectionsApi->create_slo_correction: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -89,6 +90,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -144,6 +146,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectiveCorrectionsApi->delete_slo_correction: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -163,6 +166,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -219,6 +223,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectiveCorrectionsApi->get_slo_correction: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -238,6 +243,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -293,6 +299,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectiveCorrectionsApi->list_slo_correction: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -309,6 +316,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -376,6 +384,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectiveCorrectionsApi->update_slo_correction: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -396,6 +405,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/ServiceLevelObjectiveQuery.md b/docs/v1/ServiceLevelObjectiveQuery.md index 89e3693a05..2f14bba1a3 100644 --- a/docs/v1/ServiceLevelObjectiveQuery.md +++ b/docs/v1/ServiceLevelObjectiveQuery.md @@ -1,6 +1,7 @@ # ServiceLevelObjectiveQuery A metric SLI query. **Required if type is `metric`**. Note that Datadog only allows the sum by aggregator to be used because this will sum up all request counts instead of averaging them, or taking the max or min of all of those requests. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceLevelObjectiveRequest.md b/docs/v1/ServiceLevelObjectiveRequest.md index c79175dfbd..39121dea80 100644 --- a/docs/v1/ServiceLevelObjectiveRequest.md +++ b/docs/v1/ServiceLevelObjectiveRequest.md @@ -1,6 +1,7 @@ # ServiceLevelObjectiveRequest A service level objective object includes a service level indicator, thresholds for one or more timeframes, and metadata (`name`, `description`, `tags`, etc.). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceLevelObjectivesApi.md b/docs/v1/ServiceLevelObjectivesApi.md index 7823f5fc39..07f663ffe7 100644 --- a/docs/v1/ServiceLevelObjectivesApi.md +++ b/docs/v1/ServiceLevelObjectivesApi.md @@ -60,6 +60,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->check_can_delete_slo: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -79,6 +80,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -157,6 +159,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->create_slo: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -176,6 +179,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -241,6 +245,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->delete_slo: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -261,6 +266,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -321,6 +327,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->delete_slo_timeframe_in_bulk: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -340,6 +347,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -395,6 +403,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->get_slo: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -414,6 +423,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -472,6 +482,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->get_slo_history: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -493,6 +504,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -553,6 +565,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->list_slos: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -575,6 +588,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -657,6 +671,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ServiceLevelObjectivesApi->update_slo: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -677,6 +692,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/ServiceMapWidgetDefinition.md b/docs/v1/ServiceMapWidgetDefinition.md index 36707c1100..acbd8e6802 100644 --- a/docs/v1/ServiceMapWidgetDefinition.md +++ b/docs/v1/ServiceMapWidgetDefinition.md @@ -1,6 +1,7 @@ # ServiceMapWidgetDefinition This widget displays a map of a service to all of the services that call it, and all of the services that it calls. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceMapWidgetDefinitionType.md b/docs/v1/ServiceMapWidgetDefinitionType.md index 2fcb1b7ebf..04bc621267 100644 --- a/docs/v1/ServiceMapWidgetDefinitionType.md +++ b/docs/v1/ServiceMapWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ServiceMapWidgetDefinitionType Type of the service map widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceSummaryWidgetDefinition.md b/docs/v1/ServiceSummaryWidgetDefinition.md index 1bf2581e20..3670a210b9 100644 --- a/docs/v1/ServiceSummaryWidgetDefinition.md +++ b/docs/v1/ServiceSummaryWidgetDefinition.md @@ -1,6 +1,7 @@ # ServiceSummaryWidgetDefinition The service summary displays the graphs of a chosen service in your screenboard. Only available on FREE layout dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ServiceSummaryWidgetDefinitionType.md b/docs/v1/ServiceSummaryWidgetDefinitionType.md index 7ad879d7cc..be32f02010 100644 --- a/docs/v1/ServiceSummaryWidgetDefinitionType.md +++ b/docs/v1/ServiceSummaryWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ServiceSummaryWidgetDefinitionType Type of the service summary widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SlackIntegrationApi.md b/docs/v1/SlackIntegrationApi.md index 320c8e6fa8..2e856e4ba1 100644 --- a/docs/v1/SlackIntegrationApi.md +++ b/docs/v1/SlackIntegrationApi.md @@ -66,6 +66,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SlackIntegrationApi->create_slack_integration_channel: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -86,6 +87,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -143,6 +145,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SlackIntegrationApi->get_slack_integration_channel: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -163,6 +166,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -219,6 +223,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SlackIntegrationApi->get_slack_integration_channels: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -238,6 +243,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -294,6 +300,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SlackIntegrationApi->remove_slack_integration_channel: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -314,6 +321,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -380,6 +388,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SlackIntegrationApi->update_slack_integration_channel: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -401,6 +410,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/SlackIntegrationChannel.md b/docs/v1/SlackIntegrationChannel.md index 6be7fceb12..43a535623f 100644 --- a/docs/v1/SlackIntegrationChannel.md +++ b/docs/v1/SlackIntegrationChannel.md @@ -1,6 +1,7 @@ # SlackIntegrationChannel The Slack channel configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SlackIntegrationChannelDisplay.md b/docs/v1/SlackIntegrationChannelDisplay.md index bdef41e2d7..2089c86bfb 100644 --- a/docs/v1/SlackIntegrationChannelDisplay.md +++ b/docs/v1/SlackIntegrationChannelDisplay.md @@ -1,6 +1,7 @@ # SlackIntegrationChannelDisplay Configuration options for what is shown in an alert event message. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SlackIntegrationChannels.md b/docs/v1/SlackIntegrationChannels.md index 01a09598c0..1cfdbb4baf 100644 --- a/docs/v1/SlackIntegrationChannels.md +++ b/docs/v1/SlackIntegrationChannels.md @@ -1,6 +1,7 @@ # SlackIntegrationChannels A list of configured Slack channels. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SnapshotsApi.md b/docs/v1/SnapshotsApi.md index a6c61ff44d..57d1ddb167 100644 --- a/docs/v1/SnapshotsApi.md +++ b/docs/v1/SnapshotsApi.md @@ -67,6 +67,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SnapshotsApi->get_graph_snapshot: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -91,6 +92,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/SyntheticsAPIStep.md b/docs/v1/SyntheticsAPIStep.md index 171f2e3b3d..dbb4749807 100644 --- a/docs/v1/SyntheticsAPIStep.md +++ b/docs/v1/SyntheticsAPIStep.md @@ -1,6 +1,7 @@ # SyntheticsAPIStep The steps used in a Synthetics multistep API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPIStepSubtype.md b/docs/v1/SyntheticsAPIStepSubtype.md index 2dcfa51253..6863591942 100644 --- a/docs/v1/SyntheticsAPIStepSubtype.md +++ b/docs/v1/SyntheticsAPIStepSubtype.md @@ -1,6 +1,7 @@ # SyntheticsAPIStepSubtype The subtype of the Synthetic multistep API test step, currently only supporting `http`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITest.md b/docs/v1/SyntheticsAPITest.md index b3888d71d3..3f08265b36 100644 --- a/docs/v1/SyntheticsAPITest.md +++ b/docs/v1/SyntheticsAPITest.md @@ -1,6 +1,7 @@ # SyntheticsAPITest Object containing details about a Synthetic API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestConfig.md b/docs/v1/SyntheticsAPITestConfig.md index 1984b6c275..c85176a837 100644 --- a/docs/v1/SyntheticsAPITestConfig.md +++ b/docs/v1/SyntheticsAPITestConfig.md @@ -1,6 +1,7 @@ # SyntheticsAPITestConfig Configuration object for a Synthetic API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestResultData.md b/docs/v1/SyntheticsAPITestResultData.md index 5af1906f9e..a7875050ee 100644 --- a/docs/v1/SyntheticsAPITestResultData.md +++ b/docs/v1/SyntheticsAPITestResultData.md @@ -1,6 +1,7 @@ # SyntheticsAPITestResultData Object containing results for your Synthetic API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestResultFull.md b/docs/v1/SyntheticsAPITestResultFull.md index 0608052902..624f1244b4 100644 --- a/docs/v1/SyntheticsAPITestResultFull.md +++ b/docs/v1/SyntheticsAPITestResultFull.md @@ -1,6 +1,7 @@ # SyntheticsAPITestResultFull Object returned describing a API test result. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestResultFullCheck.md b/docs/v1/SyntheticsAPITestResultFullCheck.md index ae0db88662..d19154da18 100644 --- a/docs/v1/SyntheticsAPITestResultFullCheck.md +++ b/docs/v1/SyntheticsAPITestResultFullCheck.md @@ -1,6 +1,7 @@ # SyntheticsAPITestResultFullCheck Object describing the API test configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestResultShort.md b/docs/v1/SyntheticsAPITestResultShort.md index b85b319f17..8d7d5da005 100644 --- a/docs/v1/SyntheticsAPITestResultShort.md +++ b/docs/v1/SyntheticsAPITestResultShort.md @@ -1,6 +1,7 @@ # SyntheticsAPITestResultShort Object with the results of a single Synthetic API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestResultShortResult.md b/docs/v1/SyntheticsAPITestResultShortResult.md index b60692fd9a..d8ba901094 100644 --- a/docs/v1/SyntheticsAPITestResultShortResult.md +++ b/docs/v1/SyntheticsAPITestResultShortResult.md @@ -1,6 +1,7 @@ # SyntheticsAPITestResultShortResult Result of the last API test run. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAPITestType.md b/docs/v1/SyntheticsAPITestType.md index 3332e86ce0..58afc87011 100644 --- a/docs/v1/SyntheticsAPITestType.md +++ b/docs/v1/SyntheticsAPITestType.md @@ -1,6 +1,7 @@ # SyntheticsAPITestType Type of the Synthetic test, `api`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsApi.md b/docs/v1/SyntheticsApi.md index 720cc1854a..aa440104a5 100644 --- a/docs/v1/SyntheticsApi.md +++ b/docs/v1/SyntheticsApi.md @@ -95,6 +95,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->create_global_variable: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -114,6 +115,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -183,6 +185,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->create_private_location: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -202,6 +205,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -374,6 +378,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->create_synthetics_api_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -393,6 +398,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -530,6 +536,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->create_synthetics_browser_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -549,6 +556,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -695,6 +703,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->create_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -714,6 +723,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -769,6 +779,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->delete_global_variable: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -788,6 +799,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -843,6 +855,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->delete_private_location: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -862,6 +875,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -918,6 +932,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->delete_tests: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -937,6 +952,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1012,6 +1028,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->edit_global_variable: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1032,6 +1049,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1101,6 +1119,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_api_test_latest_results: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1123,6 +1142,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1179,6 +1199,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_api_test_result: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1199,6 +1220,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1254,6 +1276,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_browser_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1273,6 +1296,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1342,6 +1366,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_browser_test_latest_results: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1364,6 +1389,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1420,6 +1446,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_browser_test_result: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1440,6 +1467,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1495,6 +1523,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_global_variable: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1514,6 +1543,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1569,6 +1599,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_private_location: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1588,6 +1619,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1642,6 +1674,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->get_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1661,6 +1694,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1715,6 +1749,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->list_locations: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -1731,6 +1766,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1783,6 +1819,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->list_tests: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -1799,6 +1836,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1896,6 +1934,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->trigger_ci_tests: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1915,6 +1954,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2087,6 +2127,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->update_api_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2107,6 +2148,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2245,6 +2287,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->update_browser_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2265,6 +2308,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2336,6 +2380,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->update_private_location: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2356,6 +2401,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2501,6 +2547,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->update_test: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2521,6 +2568,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2580,6 +2628,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SyntheticsApi->update_test_pause_status: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2600,6 +2649,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/SyntheticsAssertion.md b/docs/v1/SyntheticsAssertion.md index 12ef4143e1..b9b3217bcf 100644 --- a/docs/v1/SyntheticsAssertion.md +++ b/docs/v1/SyntheticsAssertion.md @@ -1,6 +1,7 @@ # SyntheticsAssertion Object describing the assertions type, their associated operator, which property they apply, and upon which target. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionJSONPathOperator.md b/docs/v1/SyntheticsAssertionJSONPathOperator.md index 1e3c300bbd..12102d5159 100644 --- a/docs/v1/SyntheticsAssertionJSONPathOperator.md +++ b/docs/v1/SyntheticsAssertionJSONPathOperator.md @@ -1,6 +1,7 @@ # SyntheticsAssertionJSONPathOperator Assertion operator to apply. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionJSONPathTarget.md b/docs/v1/SyntheticsAssertionJSONPathTarget.md index 4fe7dbc47f..bb0fc0472a 100644 --- a/docs/v1/SyntheticsAssertionJSONPathTarget.md +++ b/docs/v1/SyntheticsAssertionJSONPathTarget.md @@ -1,6 +1,7 @@ # SyntheticsAssertionJSONPathTarget An assertion for the `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionJSONPathTargetTarget.md b/docs/v1/SyntheticsAssertionJSONPathTargetTarget.md index b4ab83060c..1a3bf98da9 100644 --- a/docs/v1/SyntheticsAssertionJSONPathTargetTarget.md +++ b/docs/v1/SyntheticsAssertionJSONPathTargetTarget.md @@ -1,6 +1,7 @@ # SyntheticsAssertionJSONPathTargetTarget Composed target for `validatesJSONPath` operator. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionOperator.md b/docs/v1/SyntheticsAssertionOperator.md index 9a58c2594a..5ccc82e926 100644 --- a/docs/v1/SyntheticsAssertionOperator.md +++ b/docs/v1/SyntheticsAssertionOperator.md @@ -1,6 +1,7 @@ # SyntheticsAssertionOperator Assertion operator to apply. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionTarget.md b/docs/v1/SyntheticsAssertionTarget.md index 2f94bee287..cbe08b5c5b 100644 --- a/docs/v1/SyntheticsAssertionTarget.md +++ b/docs/v1/SyntheticsAssertionTarget.md @@ -1,6 +1,7 @@ # SyntheticsAssertionTarget An assertion which uses a simple target. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsAssertionType.md b/docs/v1/SyntheticsAssertionType.md index 138be13cb1..6d8c1b94e0 100644 --- a/docs/v1/SyntheticsAssertionType.md +++ b/docs/v1/SyntheticsAssertionType.md @@ -1,6 +1,7 @@ # SyntheticsAssertionType Type of the assertion. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBasicAuth.md b/docs/v1/SyntheticsBasicAuth.md index ac9ae21b58..222dd6b20d 100644 --- a/docs/v1/SyntheticsBasicAuth.md +++ b/docs/v1/SyntheticsBasicAuth.md @@ -1,6 +1,7 @@ # SyntheticsBasicAuth Object to handle basic authentication when performing the test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserError.md b/docs/v1/SyntheticsBrowserError.md index 64b656850f..788f77324f 100644 --- a/docs/v1/SyntheticsBrowserError.md +++ b/docs/v1/SyntheticsBrowserError.md @@ -1,6 +1,7 @@ # SyntheticsBrowserError Error response object for a browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserErrorType.md b/docs/v1/SyntheticsBrowserErrorType.md index fc15b156d6..04a63e054e 100644 --- a/docs/v1/SyntheticsBrowserErrorType.md +++ b/docs/v1/SyntheticsBrowserErrorType.md @@ -1,6 +1,7 @@ # SyntheticsBrowserErrorType Error type returned by a browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTest.md b/docs/v1/SyntheticsBrowserTest.md index 8756cb5d58..369c56d6bd 100644 --- a/docs/v1/SyntheticsBrowserTest.md +++ b/docs/v1/SyntheticsBrowserTest.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTest Object containing details about a Synthetic browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestConfig.md b/docs/v1/SyntheticsBrowserTestConfig.md index 2fa8681fbb..9505707f8f 100644 --- a/docs/v1/SyntheticsBrowserTestConfig.md +++ b/docs/v1/SyntheticsBrowserTestConfig.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestConfig Configuration object for a Synthetic browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestResultData.md b/docs/v1/SyntheticsBrowserTestResultData.md index fc699ce373..62e57cc309 100644 --- a/docs/v1/SyntheticsBrowserTestResultData.md +++ b/docs/v1/SyntheticsBrowserTestResultData.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestResultData Object containing results for your Synthetic browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestResultFull.md b/docs/v1/SyntheticsBrowserTestResultFull.md index c1397760ab..5b95596a64 100644 --- a/docs/v1/SyntheticsBrowserTestResultFull.md +++ b/docs/v1/SyntheticsBrowserTestResultFull.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestResultFull Object returned describing a browser test result. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestResultFullCheck.md b/docs/v1/SyntheticsBrowserTestResultFullCheck.md index 5822e50526..6ad5cd1bc7 100644 --- a/docs/v1/SyntheticsBrowserTestResultFullCheck.md +++ b/docs/v1/SyntheticsBrowserTestResultFullCheck.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestResultFullCheck Object describing the browser test configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestResultShort.md b/docs/v1/SyntheticsBrowserTestResultShort.md index d30f6a91cc..335a64e1c0 100644 --- a/docs/v1/SyntheticsBrowserTestResultShort.md +++ b/docs/v1/SyntheticsBrowserTestResultShort.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestResultShort Object with the results of a single Synthetic browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestResultShortResult.md b/docs/v1/SyntheticsBrowserTestResultShortResult.md index 0764651195..0125d957e3 100644 --- a/docs/v1/SyntheticsBrowserTestResultShortResult.md +++ b/docs/v1/SyntheticsBrowserTestResultShortResult.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestResultShortResult Object with the result of the last browser test run. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserTestType.md b/docs/v1/SyntheticsBrowserTestType.md index fb70b8d889..cea3a5c92b 100644 --- a/docs/v1/SyntheticsBrowserTestType.md +++ b/docs/v1/SyntheticsBrowserTestType.md @@ -1,6 +1,7 @@ # SyntheticsBrowserTestType Type of the Synthetic test, `browser`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserVariable.md b/docs/v1/SyntheticsBrowserVariable.md index fad61ee7f5..627204b7a0 100644 --- a/docs/v1/SyntheticsBrowserVariable.md +++ b/docs/v1/SyntheticsBrowserVariable.md @@ -1,6 +1,7 @@ # SyntheticsBrowserVariable Object defining a variable that can be used in your browser test. Learn more in the [Browser test Actions documentation](https://docs.datadoghq.com/synthetics/browser_tests/actions#variable). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsBrowserVariableType.md b/docs/v1/SyntheticsBrowserVariableType.md index b195b91666..d5bc54dc0c 100644 --- a/docs/v1/SyntheticsBrowserVariableType.md +++ b/docs/v1/SyntheticsBrowserVariableType.md @@ -1,6 +1,7 @@ # SyntheticsBrowserVariableType Type of browser test variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCITest.md b/docs/v1/SyntheticsCITest.md index 30eaea710e..d02c15f970 100644 --- a/docs/v1/SyntheticsCITest.md +++ b/docs/v1/SyntheticsCITest.md @@ -1,6 +1,7 @@ # SyntheticsCITest Test configuration for Synthetics CI + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCITestBody.md b/docs/v1/SyntheticsCITestBody.md index 820fa6af3a..89909331e4 100644 --- a/docs/v1/SyntheticsCITestBody.md +++ b/docs/v1/SyntheticsCITestBody.md @@ -1,6 +1,7 @@ # SyntheticsCITestBody Object describing the synthetics tests to trigger. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCITestMetadata.md b/docs/v1/SyntheticsCITestMetadata.md index a96f503aae..9c1571b309 100644 --- a/docs/v1/SyntheticsCITestMetadata.md +++ b/docs/v1/SyntheticsCITestMetadata.md @@ -1,6 +1,7 @@ # SyntheticsCITestMetadata Metadata for the Synthetics tests run + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCITestMetadataCi.md b/docs/v1/SyntheticsCITestMetadataCi.md index 66236cc6f1..1e96bec7f0 100644 --- a/docs/v1/SyntheticsCITestMetadataCi.md +++ b/docs/v1/SyntheticsCITestMetadataCi.md @@ -1,6 +1,7 @@ # SyntheticsCITestMetadataCi Describe CI provider. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCITestMetadataGit.md b/docs/v1/SyntheticsCITestMetadataGit.md index 09597f5054..590d4181de 100644 --- a/docs/v1/SyntheticsCITestMetadataGit.md +++ b/docs/v1/SyntheticsCITestMetadataGit.md @@ -1,6 +1,7 @@ # SyntheticsCITestMetadataGit Git information. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCheckType.md b/docs/v1/SyntheticsCheckType.md index 06aaf4c28b..ad0072cdc1 100644 --- a/docs/v1/SyntheticsCheckType.md +++ b/docs/v1/SyntheticsCheckType.md @@ -1,6 +1,7 @@ # SyntheticsCheckType Type of assertion to apply in an API test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsConfigVariable.md b/docs/v1/SyntheticsConfigVariable.md index 2f7cff8b8f..71f85658d8 100644 --- a/docs/v1/SyntheticsConfigVariable.md +++ b/docs/v1/SyntheticsConfigVariable.md @@ -1,6 +1,7 @@ # SyntheticsConfigVariable Object defining a variable that can be used in your test configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsConfigVariableType.md b/docs/v1/SyntheticsConfigVariableType.md index cb867b416e..16d2ffa025 100644 --- a/docs/v1/SyntheticsConfigVariableType.md +++ b/docs/v1/SyntheticsConfigVariableType.md @@ -1,6 +1,7 @@ # SyntheticsConfigVariableType Type of the configuration variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsCoreWebVitals.md b/docs/v1/SyntheticsCoreWebVitals.md index 534e30610c..14cf24e63f 100644 --- a/docs/v1/SyntheticsCoreWebVitals.md +++ b/docs/v1/SyntheticsCoreWebVitals.md @@ -1,6 +1,7 @@ # SyntheticsCoreWebVitals Core Web Vitals attached to a browser test step. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsDeleteTestsPayload.md b/docs/v1/SyntheticsDeleteTestsPayload.md index 2673a6e475..fab53f28b7 100644 --- a/docs/v1/SyntheticsDeleteTestsPayload.md +++ b/docs/v1/SyntheticsDeleteTestsPayload.md @@ -1,6 +1,7 @@ # SyntheticsDeleteTestsPayload A JSON list of the ID or IDs of the Synthetic tests that you want to delete. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsDeleteTestsResponse.md b/docs/v1/SyntheticsDeleteTestsResponse.md index f5aab867e5..b1131d567a 100644 --- a/docs/v1/SyntheticsDeleteTestsResponse.md +++ b/docs/v1/SyntheticsDeleteTestsResponse.md @@ -1,6 +1,7 @@ # SyntheticsDeleteTestsResponse Response object for deleting Synthetic tests. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsDeletedTest.md b/docs/v1/SyntheticsDeletedTest.md index 5bad4f1ded..8b6aec3def 100644 --- a/docs/v1/SyntheticsDeletedTest.md +++ b/docs/v1/SyntheticsDeletedTest.md @@ -1,6 +1,7 @@ # SyntheticsDeletedTest Object containing a deleted Synthetic test ID with the associated deletion timestamp. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsDevice.md b/docs/v1/SyntheticsDevice.md index 778e8c4e56..cc0790376f 100644 --- a/docs/v1/SyntheticsDevice.md +++ b/docs/v1/SyntheticsDevice.md @@ -1,6 +1,7 @@ # SyntheticsDevice Object describing the device used to perform the Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsDeviceID.md b/docs/v1/SyntheticsDeviceID.md index fea55ce527..601fae53fd 100644 --- a/docs/v1/SyntheticsDeviceID.md +++ b/docs/v1/SyntheticsDeviceID.md @@ -1,6 +1,7 @@ # SyntheticsDeviceID The device ID. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsErrorCode.md b/docs/v1/SyntheticsErrorCode.md index e5e859ebc6..a302eef0d1 100644 --- a/docs/v1/SyntheticsErrorCode.md +++ b/docs/v1/SyntheticsErrorCode.md @@ -1,6 +1,7 @@ # SyntheticsErrorCode Error code that can be returned by a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGetAPITestLatestResultsResponse.md b/docs/v1/SyntheticsGetAPITestLatestResultsResponse.md index 9d335b8f80..7a59f15ace 100644 --- a/docs/v1/SyntheticsGetAPITestLatestResultsResponse.md +++ b/docs/v1/SyntheticsGetAPITestLatestResultsResponse.md @@ -1,6 +1,7 @@ # SyntheticsGetAPITestLatestResultsResponse Object with the latest Synthetic API test run. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md b/docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md index 4288b0997b..b4807f2571 100644 --- a/docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md +++ b/docs/v1/SyntheticsGetBrowserTestLatestResultsResponse.md @@ -1,6 +1,7 @@ # SyntheticsGetBrowserTestLatestResultsResponse Object with the latest Synthetic browser test run. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGlobalVariable.md b/docs/v1/SyntheticsGlobalVariable.md index b1169d0645..b611cb75f7 100644 --- a/docs/v1/SyntheticsGlobalVariable.md +++ b/docs/v1/SyntheticsGlobalVariable.md @@ -1,6 +1,7 @@ # SyntheticsGlobalVariable Synthetics global variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGlobalVariableParseTestOptions.md b/docs/v1/SyntheticsGlobalVariableParseTestOptions.md index 0186682b3c..e59e337b9b 100644 --- a/docs/v1/SyntheticsGlobalVariableParseTestOptions.md +++ b/docs/v1/SyntheticsGlobalVariableParseTestOptions.md @@ -1,6 +1,7 @@ # SyntheticsGlobalVariableParseTestOptions Parser options to use for retrieving a Synthetics global variable from a Synthetics Test. Used in conjunction with `parse_test_public_id`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGlobalVariableParseTestOptionsType.md b/docs/v1/SyntheticsGlobalVariableParseTestOptionsType.md index fce00322a2..4f3684ec2e 100644 --- a/docs/v1/SyntheticsGlobalVariableParseTestOptionsType.md +++ b/docs/v1/SyntheticsGlobalVariableParseTestOptionsType.md @@ -1,6 +1,7 @@ # SyntheticsGlobalVariableParseTestOptionsType Property of the Synthetics Test Response to use for a Synthetics global variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGlobalVariableParserType.md b/docs/v1/SyntheticsGlobalVariableParserType.md index ebf983b096..2386fd81f0 100644 --- a/docs/v1/SyntheticsGlobalVariableParserType.md +++ b/docs/v1/SyntheticsGlobalVariableParserType.md @@ -1,6 +1,7 @@ # SyntheticsGlobalVariableParserType Type of parser for a Synthetics global variable from a synthetics test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsGlobalVariableValue.md b/docs/v1/SyntheticsGlobalVariableValue.md index 65c12fcc43..b7a362a576 100644 --- a/docs/v1/SyntheticsGlobalVariableValue.md +++ b/docs/v1/SyntheticsGlobalVariableValue.md @@ -1,6 +1,7 @@ # SyntheticsGlobalVariableValue Value of the global variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsListTestsResponse.md b/docs/v1/SyntheticsListTestsResponse.md index c82590f18f..e2a4125457 100644 --- a/docs/v1/SyntheticsListTestsResponse.md +++ b/docs/v1/SyntheticsListTestsResponse.md @@ -1,6 +1,7 @@ # SyntheticsListTestsResponse Object containing an array of Synthetic tests configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsLocation.md b/docs/v1/SyntheticsLocation.md index c827f8a954..451d299301 100644 --- a/docs/v1/SyntheticsLocation.md +++ b/docs/v1/SyntheticsLocation.md @@ -1,6 +1,7 @@ # SyntheticsLocation Synthetic location that can be used when creating or editing a test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsLocations.md b/docs/v1/SyntheticsLocations.md index 3953ce7d58..14b498a89a 100644 --- a/docs/v1/SyntheticsLocations.md +++ b/docs/v1/SyntheticsLocations.md @@ -1,6 +1,7 @@ # SyntheticsLocations List of Synthetics locations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsParsingOptions.md b/docs/v1/SyntheticsParsingOptions.md index 8653e76768..5151528301 100644 --- a/docs/v1/SyntheticsParsingOptions.md +++ b/docs/v1/SyntheticsParsingOptions.md @@ -1,6 +1,7 @@ # SyntheticsParsingOptions Parsing options for variables to extract. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPlayingTab.md b/docs/v1/SyntheticsPlayingTab.md index 740c01101d..1fdd5b2b65 100644 --- a/docs/v1/SyntheticsPlayingTab.md +++ b/docs/v1/SyntheticsPlayingTab.md @@ -1,6 +1,7 @@ # SyntheticsPlayingTab Navigate between different tabs for your browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocation.md b/docs/v1/SyntheticsPrivateLocation.md index ea42fcd450..2bddb04a91 100644 --- a/docs/v1/SyntheticsPrivateLocation.md +++ b/docs/v1/SyntheticsPrivateLocation.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocation Object containing information about the private location to create. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocationCreationResponse.md b/docs/v1/SyntheticsPrivateLocationCreationResponse.md index 720d722ef1..bdae0b575a 100644 --- a/docs/v1/SyntheticsPrivateLocationCreationResponse.md +++ b/docs/v1/SyntheticsPrivateLocationCreationResponse.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocationCreationResponse Object that contains the new private location, the public key for result encryption, and the configuration skeleton. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md b/docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md index 09839d434f..ecb1f993b7 100644 --- a/docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md +++ b/docs/v1/SyntheticsPrivateLocationCreationResponseResultEncryption.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocationCreationResponseResultEncryption Public key for the result encryption. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocationSecrets.md b/docs/v1/SyntheticsPrivateLocationSecrets.md index 221e2caf8d..66a63079f5 100644 --- a/docs/v1/SyntheticsPrivateLocationSecrets.md +++ b/docs/v1/SyntheticsPrivateLocationSecrets.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocationSecrets Secrets for the private location. Only present in the response when creating the private location. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md b/docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md index 9a286ca86f..3b7e07f1c8 100644 --- a/docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md +++ b/docs/v1/SyntheticsPrivateLocationSecretsAuthentication.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocationSecretsAuthentication Authentication part of the secrets. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md b/docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md index 937219f7be..ba352668a2 100644 --- a/docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md +++ b/docs/v1/SyntheticsPrivateLocationSecretsConfigDecryption.md @@ -1,6 +1,7 @@ # SyntheticsPrivateLocationSecretsConfigDecryption Private key for the private location. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsSSLCertificate.md b/docs/v1/SyntheticsSSLCertificate.md index 3b284ac054..38d07f3219 100644 --- a/docs/v1/SyntheticsSSLCertificate.md +++ b/docs/v1/SyntheticsSSLCertificate.md @@ -1,6 +1,7 @@ # SyntheticsSSLCertificate Object describing the SSL certificate used for a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsSSLCertificateIssuer.md b/docs/v1/SyntheticsSSLCertificateIssuer.md index 0dc0f15df7..141ce83fc0 100644 --- a/docs/v1/SyntheticsSSLCertificateIssuer.md +++ b/docs/v1/SyntheticsSSLCertificateIssuer.md @@ -1,6 +1,7 @@ # SyntheticsSSLCertificateIssuer Object describing the issuer of a SSL certificate. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsSSLCertificateSubject.md b/docs/v1/SyntheticsSSLCertificateSubject.md index 85e8cf6e2c..5fbbed88bf 100644 --- a/docs/v1/SyntheticsSSLCertificateSubject.md +++ b/docs/v1/SyntheticsSSLCertificateSubject.md @@ -1,6 +1,7 @@ # SyntheticsSSLCertificateSubject Object describing the SSL certificate used for the test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsStep.md b/docs/v1/SyntheticsStep.md index 05c4fc4a2e..dcfb8740db 100644 --- a/docs/v1/SyntheticsStep.md +++ b/docs/v1/SyntheticsStep.md @@ -1,6 +1,7 @@ # SyntheticsStep The steps used in a Synthetics browser test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsStepDetail.md b/docs/v1/SyntheticsStepDetail.md index 2ba3580b1b..72f5f52441 100644 --- a/docs/v1/SyntheticsStepDetail.md +++ b/docs/v1/SyntheticsStepDetail.md @@ -1,6 +1,7 @@ # SyntheticsStepDetail Object describing a step for a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsStepDetailWarning.md b/docs/v1/SyntheticsStepDetailWarning.md index c791f658b5..0f5534624d 100644 --- a/docs/v1/SyntheticsStepDetailWarning.md +++ b/docs/v1/SyntheticsStepDetailWarning.md @@ -1,6 +1,7 @@ # SyntheticsStepDetailWarning Object collecting warnings for a given step. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsStepType.md b/docs/v1/SyntheticsStepType.md index f083d46e59..83feae5a6e 100644 --- a/docs/v1/SyntheticsStepType.md +++ b/docs/v1/SyntheticsStepType.md @@ -1,6 +1,7 @@ # SyntheticsStepType Step type used in your Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestConfig.md b/docs/v1/SyntheticsTestConfig.md index 4aa7e25703..03d3a4767d 100644 --- a/docs/v1/SyntheticsTestConfig.md +++ b/docs/v1/SyntheticsTestConfig.md @@ -1,6 +1,7 @@ # SyntheticsTestConfig Configuration object for a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestDetails.md b/docs/v1/SyntheticsTestDetails.md index 77806dd116..b77382c93d 100644 --- a/docs/v1/SyntheticsTestDetails.md +++ b/docs/v1/SyntheticsTestDetails.md @@ -1,6 +1,7 @@ # SyntheticsTestDetails Object containing details about your Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestDetailsSubType.md b/docs/v1/SyntheticsTestDetailsSubType.md index 9b2eaddf9f..0adca7025e 100644 --- a/docs/v1/SyntheticsTestDetailsSubType.md +++ b/docs/v1/SyntheticsTestDetailsSubType.md @@ -1,6 +1,7 @@ # SyntheticsTestDetailsSubType The subtype of the Synthetic API test, `http`, `ssl`, `tcp`, `dns` or `multi`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestDetailsType.md b/docs/v1/SyntheticsTestDetailsType.md index 6e18f79d96..051b6f9be4 100644 --- a/docs/v1/SyntheticsTestDetailsType.md +++ b/docs/v1/SyntheticsTestDetailsType.md @@ -1,6 +1,7 @@ # SyntheticsTestDetailsType Type of the Synthetic test, either `api` or `browser`. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestHeaders.md b/docs/v1/SyntheticsTestHeaders.md index ef8871eac5..093e51f3ed 100644 --- a/docs/v1/SyntheticsTestHeaders.md +++ b/docs/v1/SyntheticsTestHeaders.md @@ -1,6 +1,7 @@ # SyntheticsTestHeaders Headers to include when performing the test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestMonitorStatus.md b/docs/v1/SyntheticsTestMonitorStatus.md index 7893c9dfa7..1de96cdbe8 100644 --- a/docs/v1/SyntheticsTestMonitorStatus.md +++ b/docs/v1/SyntheticsTestMonitorStatus.md @@ -1,6 +1,7 @@ # SyntheticsTestMonitorStatus The status of your Synthetic monitor. * `O` for not triggered * `1` for triggered * `2` for no data + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestOptions.md b/docs/v1/SyntheticsTestOptions.md index cde16b7b87..5963490ed8 100644 --- a/docs/v1/SyntheticsTestOptions.md +++ b/docs/v1/SyntheticsTestOptions.md @@ -1,6 +1,7 @@ # SyntheticsTestOptions Object describing the extra options for a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestOptionsMonitorOptions.md b/docs/v1/SyntheticsTestOptionsMonitorOptions.md index ba385fd37d..c5a9792588 100644 --- a/docs/v1/SyntheticsTestOptionsMonitorOptions.md +++ b/docs/v1/SyntheticsTestOptionsMonitorOptions.md @@ -1,6 +1,7 @@ # SyntheticsTestOptionsMonitorOptions Object containing the options for a Synthetic test as a monitor (for example, renotification). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestOptionsRetry.md b/docs/v1/SyntheticsTestOptionsRetry.md index 7f28e7683e..33d0dd4165 100644 --- a/docs/v1/SyntheticsTestOptionsRetry.md +++ b/docs/v1/SyntheticsTestOptionsRetry.md @@ -1,6 +1,7 @@ # SyntheticsTestOptionsRetry Object describing the retry strategy to apply to a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestPauseStatus.md b/docs/v1/SyntheticsTestPauseStatus.md index 4546c6640f..74df3ac4ad 100644 --- a/docs/v1/SyntheticsTestPauseStatus.md +++ b/docs/v1/SyntheticsTestPauseStatus.md @@ -1,6 +1,7 @@ # SyntheticsTestPauseStatus Define whether you want to start (`live`) or pause (`paused`) a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestProcessStatus.md b/docs/v1/SyntheticsTestProcessStatus.md index 60324e5e52..047e4ec8ae 100644 --- a/docs/v1/SyntheticsTestProcessStatus.md +++ b/docs/v1/SyntheticsTestProcessStatus.md @@ -1,6 +1,7 @@ # SyntheticsTestProcessStatus Status of a Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestRequest.md b/docs/v1/SyntheticsTestRequest.md index ef1ab47b29..e407208ae0 100644 --- a/docs/v1/SyntheticsTestRequest.md +++ b/docs/v1/SyntheticsTestRequest.md @@ -1,6 +1,7 @@ # SyntheticsTestRequest Object describing the Synthetic test request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestRequestCertificate.md b/docs/v1/SyntheticsTestRequestCertificate.md index 8feccd4b1f..85b11ccca7 100644 --- a/docs/v1/SyntheticsTestRequestCertificate.md +++ b/docs/v1/SyntheticsTestRequestCertificate.md @@ -1,6 +1,7 @@ # SyntheticsTestRequestCertificate Client certificate to use when performing the test request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTestRequestCertificateItem.md b/docs/v1/SyntheticsTestRequestCertificateItem.md index 90f2891589..6f32248bbf 100644 --- a/docs/v1/SyntheticsTestRequestCertificateItem.md +++ b/docs/v1/SyntheticsTestRequestCertificateItem.md @@ -1,6 +1,7 @@ # SyntheticsTestRequestCertificateItem Define a request certificate. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTickInterval.md b/docs/v1/SyntheticsTickInterval.md index 50bb4a3108..9ce6da9a18 100644 --- a/docs/v1/SyntheticsTickInterval.md +++ b/docs/v1/SyntheticsTickInterval.md @@ -1,6 +1,7 @@ # SyntheticsTickInterval The frequency at which to run the Synthetic test (in seconds). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTiming.md b/docs/v1/SyntheticsTiming.md index 4dbccd3b43..6b1bcce92f 100644 --- a/docs/v1/SyntheticsTiming.md +++ b/docs/v1/SyntheticsTiming.md @@ -1,6 +1,7 @@ # SyntheticsTiming Object containing all metrics and their values collected for a Synthetic API test. Learn more about those metrics in [Synthetics documentation](https://docs.datadoghq.com/synthetics/#metrics). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTriggerCITestLocation.md b/docs/v1/SyntheticsTriggerCITestLocation.md index f5e290cd4f..653a5f6470 100644 --- a/docs/v1/SyntheticsTriggerCITestLocation.md +++ b/docs/v1/SyntheticsTriggerCITestLocation.md @@ -1,6 +1,7 @@ # SyntheticsTriggerCITestLocation Synthetics location. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTriggerCITestRunResult.md b/docs/v1/SyntheticsTriggerCITestRunResult.md index 70c25c730c..2231af64ec 100644 --- a/docs/v1/SyntheticsTriggerCITestRunResult.md +++ b/docs/v1/SyntheticsTriggerCITestRunResult.md @@ -1,6 +1,7 @@ # SyntheticsTriggerCITestRunResult Information about a single test run. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsTriggerCITestsResponse.md b/docs/v1/SyntheticsTriggerCITestsResponse.md index a2a1afd2ce..7037240ede 100644 --- a/docs/v1/SyntheticsTriggerCITestsResponse.md +++ b/docs/v1/SyntheticsTriggerCITestsResponse.md @@ -1,6 +1,7 @@ # SyntheticsTriggerCITestsResponse Object containing information about the tests triggered. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsUpdateTestPauseStatusPayload.md b/docs/v1/SyntheticsUpdateTestPauseStatusPayload.md index b656ae0e11..bc8bb4632a 100644 --- a/docs/v1/SyntheticsUpdateTestPauseStatusPayload.md +++ b/docs/v1/SyntheticsUpdateTestPauseStatusPayload.md @@ -1,6 +1,7 @@ # SyntheticsUpdateTestPauseStatusPayload Object to start or pause an existing Synthetic test. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsVariableParser.md b/docs/v1/SyntheticsVariableParser.md index d450dacf37..564ecc21ee 100644 --- a/docs/v1/SyntheticsVariableParser.md +++ b/docs/v1/SyntheticsVariableParser.md @@ -1,6 +1,7 @@ # SyntheticsVariableParser Details of the parser to use for the global variable. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/SyntheticsWarningType.md b/docs/v1/SyntheticsWarningType.md index 51ba630d6d..2055a69fca 100644 --- a/docs/v1/SyntheticsWarningType.md +++ b/docs/v1/SyntheticsWarningType.md @@ -1,6 +1,7 @@ # SyntheticsWarningType User locator used. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TableWidgetCellDisplayMode.md b/docs/v1/TableWidgetCellDisplayMode.md index 1cfcf9a1da..580632366f 100644 --- a/docs/v1/TableWidgetCellDisplayMode.md +++ b/docs/v1/TableWidgetCellDisplayMode.md @@ -1,6 +1,7 @@ # TableWidgetCellDisplayMode Define a display mode for the table cell. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TableWidgetDefinition.md b/docs/v1/TableWidgetDefinition.md index b535bae077..377568a134 100644 --- a/docs/v1/TableWidgetDefinition.md +++ b/docs/v1/TableWidgetDefinition.md @@ -1,6 +1,7 @@ # TableWidgetDefinition The table visualization is available on timeboards and screenboards. It displays columns of metrics grouped by tag key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TableWidgetDefinitionType.md b/docs/v1/TableWidgetDefinitionType.md index 90f1f01a0b..ff7593a212 100644 --- a/docs/v1/TableWidgetDefinitionType.md +++ b/docs/v1/TableWidgetDefinitionType.md @@ -1,6 +1,7 @@ # TableWidgetDefinitionType Type of the table widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TableWidgetHasSearchBar.md b/docs/v1/TableWidgetHasSearchBar.md index c9406342d2..0105ec0c05 100644 --- a/docs/v1/TableWidgetHasSearchBar.md +++ b/docs/v1/TableWidgetHasSearchBar.md @@ -1,6 +1,7 @@ # TableWidgetHasSearchBar Controls the display of the search bar. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TableWidgetRequest.md b/docs/v1/TableWidgetRequest.md index eccd060b03..c7431524c3 100644 --- a/docs/v1/TableWidgetRequest.md +++ b/docs/v1/TableWidgetRequest.md @@ -1,6 +1,7 @@ # TableWidgetRequest Updated table widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TagToHosts.md b/docs/v1/TagToHosts.md index 47c0891495..43a8a19f86 100644 --- a/docs/v1/TagToHosts.md +++ b/docs/v1/TagToHosts.md @@ -1,6 +1,7 @@ # TagToHosts In this object, the key is the tag, the value is a list of host names that are reporting that tag. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TagsApi.md b/docs/v1/TagsApi.md index b58137bc22..19cecef8cc 100644 --- a/docs/v1/TagsApi.md +++ b/docs/v1/TagsApi.md @@ -73,6 +73,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling TagsApi->create_host_tags: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -94,6 +95,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -157,6 +159,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling TagsApi->delete_host_tags: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -177,6 +180,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -242,6 +246,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling TagsApi->get_host_tags: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -262,6 +267,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -318,6 +324,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling TagsApi->list_host_tags: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -337,6 +344,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -408,6 +416,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling TagsApi->update_host_tags: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -429,6 +438,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/TargetFormatType.md b/docs/v1/TargetFormatType.md index 0836e4cd6d..66940d9fda 100644 --- a/docs/v1/TargetFormatType.md +++ b/docs/v1/TargetFormatType.md @@ -1,6 +1,7 @@ # TargetFormatType If the `target_type` of the remapper is `attribute`, try to cast the value to a new specific type. If the cast is not possible, the original type is kept. `string`, `integer`, or `double` are the possible types. If the `target_type` is `tag`, this parameter may not be specified. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetDefinition.md b/docs/v1/TimeseriesWidgetDefinition.md index cc08fd2672..f87927a894 100644 --- a/docs/v1/TimeseriesWidgetDefinition.md +++ b/docs/v1/TimeseriesWidgetDefinition.md @@ -1,6 +1,7 @@ # TimeseriesWidgetDefinition The timeseries visualization allows you to display the evolution of one or more metrics, log events, or Indexed Spans over time. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetDefinitionType.md b/docs/v1/TimeseriesWidgetDefinitionType.md index 9d5e9ec5c3..59e424dd3b 100644 --- a/docs/v1/TimeseriesWidgetDefinitionType.md +++ b/docs/v1/TimeseriesWidgetDefinitionType.md @@ -1,6 +1,7 @@ # TimeseriesWidgetDefinitionType Type of the timeseries widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetExpressionAlias.md b/docs/v1/TimeseriesWidgetExpressionAlias.md index 4a5a0ac426..3280570c51 100644 --- a/docs/v1/TimeseriesWidgetExpressionAlias.md +++ b/docs/v1/TimeseriesWidgetExpressionAlias.md @@ -1,6 +1,7 @@ # TimeseriesWidgetExpressionAlias Define an expression alias. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetLegendColumn.md b/docs/v1/TimeseriesWidgetLegendColumn.md index 2040d84442..2877dde1cb 100644 --- a/docs/v1/TimeseriesWidgetLegendColumn.md +++ b/docs/v1/TimeseriesWidgetLegendColumn.md @@ -1,6 +1,7 @@ # TimeseriesWidgetLegendColumn Legend column. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetLegendLayout.md b/docs/v1/TimeseriesWidgetLegendLayout.md index 14a44a4199..955494a709 100644 --- a/docs/v1/TimeseriesWidgetLegendLayout.md +++ b/docs/v1/TimeseriesWidgetLegendLayout.md @@ -1,6 +1,7 @@ # TimeseriesWidgetLegendLayout Layout of the legend. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/TimeseriesWidgetRequest.md b/docs/v1/TimeseriesWidgetRequest.md index c79417f4fc..b079e12a21 100644 --- a/docs/v1/TimeseriesWidgetRequest.md +++ b/docs/v1/TimeseriesWidgetRequest.md @@ -1,6 +1,7 @@ # TimeseriesWidgetRequest Updated timeseries widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ToplistWidgetDefinition.md b/docs/v1/ToplistWidgetDefinition.md index fa583c7aa3..9c61264973 100644 --- a/docs/v1/ToplistWidgetDefinition.md +++ b/docs/v1/ToplistWidgetDefinition.md @@ -1,6 +1,7 @@ # ToplistWidgetDefinition The top list visualization enables you to display a list of Tag value like hostname or service with the most or least of any metric value, such as highest consumers of CPU, hosts with the least disk space, etc. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ToplistWidgetDefinitionType.md b/docs/v1/ToplistWidgetDefinitionType.md index 87f078c814..6582ed5fcf 100644 --- a/docs/v1/ToplistWidgetDefinitionType.md +++ b/docs/v1/ToplistWidgetDefinitionType.md @@ -1,6 +1,7 @@ # ToplistWidgetDefinitionType Type of the top list widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/ToplistWidgetRequest.md b/docs/v1/ToplistWidgetRequest.md index 729e0f5f97..2b9cece2a1 100644 --- a/docs/v1/ToplistWidgetRequest.md +++ b/docs/v1/ToplistWidgetRequest.md @@ -1,6 +1,7 @@ # ToplistWidgetRequest Updated top list widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAnalyzedLogsHour.md b/docs/v1/UsageAnalyzedLogsHour.md index e5f21989cf..05af0e13bb 100644 --- a/docs/v1/UsageAnalyzedLogsHour.md +++ b/docs/v1/UsageAnalyzedLogsHour.md @@ -1,6 +1,7 @@ # UsageAnalyzedLogsHour The number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAnalyzedLogsResponse.md b/docs/v1/UsageAnalyzedLogsResponse.md index dd47099582..1045561261 100644 --- a/docs/v1/UsageAnalyzedLogsResponse.md +++ b/docs/v1/UsageAnalyzedLogsResponse.md @@ -1,6 +1,7 @@ # UsageAnalyzedLogsResponse A response containing the number of analyzed logs for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionAggregates.md b/docs/v1/UsageAttributionAggregates.md index 02730a72c0..ecaf169de6 100644 --- a/docs/v1/UsageAttributionAggregates.md +++ b/docs/v1/UsageAttributionAggregates.md @@ -1,6 +1,7 @@ # UsageAttributionAggregates An array of available aggregates. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionAggregatesBody.md b/docs/v1/UsageAttributionAggregatesBody.md index fd4e7d2572..d63a430c78 100644 --- a/docs/v1/UsageAttributionAggregatesBody.md +++ b/docs/v1/UsageAttributionAggregatesBody.md @@ -1,6 +1,7 @@ # UsageAttributionAggregatesBody The object containing the aggregates. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionBody.md b/docs/v1/UsageAttributionBody.md index 3236537dec..979621a4c7 100644 --- a/docs/v1/UsageAttributionBody.md +++ b/docs/v1/UsageAttributionBody.md @@ -1,6 +1,7 @@ # UsageAttributionBody Usage Summary by tag for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionMetadata.md b/docs/v1/UsageAttributionMetadata.md index 7de54a1e9f..ef6d2b772e 100644 --- a/docs/v1/UsageAttributionMetadata.md +++ b/docs/v1/UsageAttributionMetadata.md @@ -1,6 +1,7 @@ # UsageAttributionMetadata The object containing document metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionPagination.md b/docs/v1/UsageAttributionPagination.md index 3a28933454..bdcb420a35 100644 --- a/docs/v1/UsageAttributionPagination.md +++ b/docs/v1/UsageAttributionPagination.md @@ -1,6 +1,7 @@ # UsageAttributionPagination The page count for the current pagination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionResponse.md b/docs/v1/UsageAttributionResponse.md index 9d7bb8aa64..1507b8cd5c 100644 --- a/docs/v1/UsageAttributionResponse.md +++ b/docs/v1/UsageAttributionResponse.md @@ -1,6 +1,7 @@ # UsageAttributionResponse Response containing the Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionSort.md b/docs/v1/UsageAttributionSort.md index 57795ca831..e5bcf1763a 100644 --- a/docs/v1/UsageAttributionSort.md +++ b/docs/v1/UsageAttributionSort.md @@ -1,6 +1,7 @@ # UsageAttributionSort The field to sort by. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionTagNames.md b/docs/v1/UsageAttributionTagNames.md index 5b815ce44e..9e9e20fe5d 100644 --- a/docs/v1/UsageAttributionTagNames.md +++ b/docs/v1/UsageAttributionTagNames.md @@ -1,6 +1,7 @@ # UsageAttributionTagNames Usage Summary by tag name. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageAttributionValues.md b/docs/v1/UsageAttributionValues.md index bea2503dff..8e13863599 100644 --- a/docs/v1/UsageAttributionValues.md +++ b/docs/v1/UsageAttributionValues.md @@ -1,6 +1,7 @@ # UsageAttributionValues Fields in Usage Summary by tag(s). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageBillableSummaryBody.md b/docs/v1/UsageBillableSummaryBody.md index 4ba2000ac1..9b53a733a8 100644 --- a/docs/v1/UsageBillableSummaryBody.md +++ b/docs/v1/UsageBillableSummaryBody.md @@ -1,6 +1,7 @@ # UsageBillableSummaryBody Response with properties for each aggregated usage type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageBillableSummaryHour.md b/docs/v1/UsageBillableSummaryHour.md index a43626d9f5..1e0164e740 100644 --- a/docs/v1/UsageBillableSummaryHour.md +++ b/docs/v1/UsageBillableSummaryHour.md @@ -1,6 +1,7 @@ # UsageBillableSummaryHour Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageBillableSummaryKeys.md b/docs/v1/UsageBillableSummaryKeys.md index a93119eeeb..5a2ffefbb8 100644 --- a/docs/v1/UsageBillableSummaryKeys.md +++ b/docs/v1/UsageBillableSummaryKeys.md @@ -1,6 +1,7 @@ # UsageBillableSummaryKeys Response with aggregated usage types. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageBillableSummaryResponse.md b/docs/v1/UsageBillableSummaryResponse.md index b1f6632208..2309300d81 100644 --- a/docs/v1/UsageBillableSummaryResponse.md +++ b/docs/v1/UsageBillableSummaryResponse.md @@ -1,6 +1,7 @@ # UsageBillableSummaryResponse Response with monthly summary of data billed by Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageCustomReportsAttributes.md b/docs/v1/UsageCustomReportsAttributes.md index 95d420bab1..0a56e3e9ca 100644 --- a/docs/v1/UsageCustomReportsAttributes.md +++ b/docs/v1/UsageCustomReportsAttributes.md @@ -1,6 +1,7 @@ # UsageCustomReportsAttributes The response containing attributes for custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageCustomReportsData.md b/docs/v1/UsageCustomReportsData.md index 8f7351fc69..fc53cc4b64 100644 --- a/docs/v1/UsageCustomReportsData.md +++ b/docs/v1/UsageCustomReportsData.md @@ -1,6 +1,7 @@ # UsageCustomReportsData The response containing the date and type for custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageCustomReportsMeta.md b/docs/v1/UsageCustomReportsMeta.md index 74a46b7fbd..fa970f47cf 100644 --- a/docs/v1/UsageCustomReportsMeta.md +++ b/docs/v1/UsageCustomReportsMeta.md @@ -1,6 +1,7 @@ # UsageCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageCustomReportsPage.md b/docs/v1/UsageCustomReportsPage.md index 5ba077a55d..be6a2ed1a6 100644 --- a/docs/v1/UsageCustomReportsPage.md +++ b/docs/v1/UsageCustomReportsPage.md @@ -1,6 +1,7 @@ # UsageCustomReportsPage The object containing page total count. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageCustomReportsResponse.md b/docs/v1/UsageCustomReportsResponse.md index 04f8682434..e931ef640e 100644 --- a/docs/v1/UsageCustomReportsResponse.md +++ b/docs/v1/UsageCustomReportsResponse.md @@ -1,6 +1,7 @@ # UsageCustomReportsResponse Response containing available custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageFargateHour.md b/docs/v1/UsageFargateHour.md index cfa50c6cba..cb69f38d0e 100644 --- a/docs/v1/UsageFargateHour.md +++ b/docs/v1/UsageFargateHour.md @@ -1,6 +1,7 @@ # UsageFargateHour Number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageFargateResponse.md b/docs/v1/UsageFargateResponse.md index 2504009cda..48a9337f6d 100644 --- a/docs/v1/UsageFargateResponse.md +++ b/docs/v1/UsageFargateResponse.md @@ -1,6 +1,7 @@ # UsageFargateResponse Response containing the number of Fargate tasks run and hourly usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageHostHour.md b/docs/v1/UsageHostHour.md index dc9038cf16..bc6dfd1111 100644 --- a/docs/v1/UsageHostHour.md +++ b/docs/v1/UsageHostHour.md @@ -1,6 +1,7 @@ # UsageHostHour Number of hosts/containers recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageHostsResponse.md b/docs/v1/UsageHostsResponse.md index ccd9aeda77..e1ee9a015a 100644 --- a/docs/v1/UsageHostsResponse.md +++ b/docs/v1/UsageHostsResponse.md @@ -1,6 +1,7 @@ # UsageHostsResponse Host usage response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIncidentManagementHour.md b/docs/v1/UsageIncidentManagementHour.md index fcb734f794..5af55b9089 100644 --- a/docs/v1/UsageIncidentManagementHour.md +++ b/docs/v1/UsageIncidentManagementHour.md @@ -1,6 +1,7 @@ # UsageIncidentManagementHour Incident management usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIncidentManagementResponse.md b/docs/v1/UsageIncidentManagementResponse.md index 8fcc5ac7a0..1a9060b48c 100644 --- a/docs/v1/UsageIncidentManagementResponse.md +++ b/docs/v1/UsageIncidentManagementResponse.md @@ -1,6 +1,7 @@ # UsageIncidentManagementResponse Response containing the incident management usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIndexedSpansHour.md b/docs/v1/UsageIndexedSpansHour.md index d68c09a096..2df815aac4 100644 --- a/docs/v1/UsageIndexedSpansHour.md +++ b/docs/v1/UsageIndexedSpansHour.md @@ -1,6 +1,7 @@ # UsageIndexedSpansHour The hours of indexed spans usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIndexedSpansResponse.md b/docs/v1/UsageIndexedSpansResponse.md index ab6279c8a1..debf570bec 100644 --- a/docs/v1/UsageIndexedSpansResponse.md +++ b/docs/v1/UsageIndexedSpansResponse.md @@ -1,6 +1,7 @@ # UsageIndexedSpansResponse A response containing indexed spans usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIngestedSpansHour.md b/docs/v1/UsageIngestedSpansHour.md index 373a4d3794..bcd795c89e 100644 --- a/docs/v1/UsageIngestedSpansHour.md +++ b/docs/v1/UsageIngestedSpansHour.md @@ -1,6 +1,7 @@ # UsageIngestedSpansHour Ingested spans usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIngestedSpansResponse.md b/docs/v1/UsageIngestedSpansResponse.md index f2e3ce11f1..378dd1f15b 100644 --- a/docs/v1/UsageIngestedSpansResponse.md +++ b/docs/v1/UsageIngestedSpansResponse.md @@ -1,6 +1,7 @@ # UsageIngestedSpansResponse Response containing the ingested spans usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIoTHour.md b/docs/v1/UsageIoTHour.md index 94a8a27ba3..6487975fcd 100644 --- a/docs/v1/UsageIoTHour.md +++ b/docs/v1/UsageIoTHour.md @@ -1,6 +1,7 @@ # UsageIoTHour IoT usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageIoTResponse.md b/docs/v1/UsageIoTResponse.md index b571a38fae..39a0f4c4ae 100644 --- a/docs/v1/UsageIoTResponse.md +++ b/docs/v1/UsageIoTResponse.md @@ -1,6 +1,7 @@ # UsageIoTResponse Response containing the IoT usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLambdaHour.md b/docs/v1/UsageLambdaHour.md index 74c569483d..662c0de9c8 100644 --- a/docs/v1/UsageLambdaHour.md +++ b/docs/v1/UsageLambdaHour.md @@ -1,6 +1,7 @@ # UsageLambdaHour Number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLambdaResponse.md b/docs/v1/UsageLambdaResponse.md index c73a204537..47717dfc41 100644 --- a/docs/v1/UsageLambdaResponse.md +++ b/docs/v1/UsageLambdaResponse.md @@ -1,6 +1,7 @@ # UsageLambdaResponse Response containing the number of lambda functions and sum of the invocations of all lambda functions for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLogsByIndexHour.md b/docs/v1/UsageLogsByIndexHour.md index 20cb60e3ae..661148cb30 100644 --- a/docs/v1/UsageLogsByIndexHour.md +++ b/docs/v1/UsageLogsByIndexHour.md @@ -1,6 +1,7 @@ # UsageLogsByIndexHour Number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLogsByIndexResponse.md b/docs/v1/UsageLogsByIndexResponse.md index f1133aa19c..5640c0f01d 100644 --- a/docs/v1/UsageLogsByIndexResponse.md +++ b/docs/v1/UsageLogsByIndexResponse.md @@ -1,6 +1,7 @@ # UsageLogsByIndexResponse Response containing the number of indexed logs for each hour and index for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLogsHour.md b/docs/v1/UsageLogsHour.md index e3ff5526e1..51e6e63dfd 100644 --- a/docs/v1/UsageLogsHour.md +++ b/docs/v1/UsageLogsHour.md @@ -1,6 +1,7 @@ # UsageLogsHour Hour usage for logs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageLogsResponse.md b/docs/v1/UsageLogsResponse.md index f40db8cad6..1fdc8b075e 100644 --- a/docs/v1/UsageLogsResponse.md +++ b/docs/v1/UsageLogsResponse.md @@ -1,6 +1,7 @@ # UsageLogsResponse Response containing the number of logs for each hour. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageMeteringApi.md b/docs/v1/UsageMeteringApi.md index 52072c7a7e..24cc35ede4 100644 --- a/docs/v1/UsageMeteringApi.md +++ b/docs/v1/UsageMeteringApi.md @@ -86,6 +86,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_daily_custom_reports: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -108,6 +109,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -172,6 +174,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_incident_management: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -192,6 +195,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -257,6 +261,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_ingested_spans: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -277,6 +282,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -337,6 +343,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_monthly_custom_reports: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -359,6 +366,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -414,6 +422,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_specified_daily_custom_reports: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -433,6 +442,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -489,6 +499,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_specified_monthly_custom_reports: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -508,6 +519,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -574,6 +586,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_tracing_without_limits: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -594,6 +607,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -659,6 +673,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_analyzed_logs: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -679,6 +694,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -748,6 +764,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_attribution: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -771,6 +788,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -826,6 +844,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_billable_summary: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -845,6 +864,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -910,6 +930,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_fargate: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -930,6 +951,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -995,6 +1017,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_hosts: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1015,6 +1038,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1080,6 +1104,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_indexed_spans: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1100,6 +1125,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1165,6 +1191,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_internet_of_things: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1185,6 +1212,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1250,6 +1278,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_lambda: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1270,6 +1299,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1335,6 +1365,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_logs: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1355,6 +1386,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1423,6 +1455,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_logs_by_index: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1444,6 +1477,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1509,6 +1543,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_network_flows: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1529,6 +1564,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1594,6 +1630,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_network_hosts: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1614,6 +1651,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1679,6 +1717,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_profiling: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1699,6 +1738,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1765,6 +1805,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_rum_sessions: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1786,6 +1827,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1851,6 +1893,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_snmp: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1871,6 +1914,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1937,6 +1981,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_summary: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1958,6 +2003,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2023,6 +2069,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_synthetics: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2043,6 +2090,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2108,6 +2156,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_synthetics_api: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2128,6 +2177,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2193,6 +2243,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_synthetics_browser: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2213,6 +2264,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2278,6 +2330,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_timeseries: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2298,6 +2351,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2366,6 +2420,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_top_avg_metrics: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2387,6 +2442,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -2452,6 +2508,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsageMeteringApi->get_usage_trace: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -2472,6 +2529,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json;datetime-format=rfc3339 + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/UsageMetricCategory.md b/docs/v1/UsageMetricCategory.md index 9c911e7a16..b4476aea1f 100644 --- a/docs/v1/UsageMetricCategory.md +++ b/docs/v1/UsageMetricCategory.md @@ -1,6 +1,7 @@ # UsageMetricCategory Contains the metric category. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageNetworkFlowsHour.md b/docs/v1/UsageNetworkFlowsHour.md index 15cc45d9d0..ca0b09f382 100644 --- a/docs/v1/UsageNetworkFlowsHour.md +++ b/docs/v1/UsageNetworkFlowsHour.md @@ -1,6 +1,7 @@ # UsageNetworkFlowsHour Number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageNetworkFlowsResponse.md b/docs/v1/UsageNetworkFlowsResponse.md index 6b88d0c8a2..60af34be9d 100644 --- a/docs/v1/UsageNetworkFlowsResponse.md +++ b/docs/v1/UsageNetworkFlowsResponse.md @@ -1,6 +1,7 @@ # UsageNetworkFlowsResponse Response containing the number of netflow events indexed for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageNetworkHostsHour.md b/docs/v1/UsageNetworkHostsHour.md index a504c7e41a..65b3f02c31 100644 --- a/docs/v1/UsageNetworkHostsHour.md +++ b/docs/v1/UsageNetworkHostsHour.md @@ -1,6 +1,7 @@ # UsageNetworkHostsHour Number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageNetworkHostsResponse.md b/docs/v1/UsageNetworkHostsResponse.md index 8aea0e044c..1b4615f74f 100644 --- a/docs/v1/UsageNetworkHostsResponse.md +++ b/docs/v1/UsageNetworkHostsResponse.md @@ -1,6 +1,7 @@ # UsageNetworkHostsResponse Response containing the number of active NPM hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageProfilingHour.md b/docs/v1/UsageProfilingHour.md index 2d7350fcbe..30fd6f4040 100644 --- a/docs/v1/UsageProfilingHour.md +++ b/docs/v1/UsageProfilingHour.md @@ -1,6 +1,7 @@ # UsageProfilingHour The number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageProfilingResponse.md b/docs/v1/UsageProfilingResponse.md index 4d972716d3..23947c0e9d 100644 --- a/docs/v1/UsageProfilingResponse.md +++ b/docs/v1/UsageProfilingResponse.md @@ -1,6 +1,7 @@ # UsageProfilingResponse Response containing the number of profiled hosts for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageReportsType.md b/docs/v1/UsageReportsType.md index ada9b04008..c20bf70605 100644 --- a/docs/v1/UsageReportsType.md +++ b/docs/v1/UsageReportsType.md @@ -1,6 +1,7 @@ # UsageReportsType The type of reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageRumSessionsHour.md b/docs/v1/UsageRumSessionsHour.md index d6df8039b5..668a3d9fab 100644 --- a/docs/v1/UsageRumSessionsHour.md +++ b/docs/v1/UsageRumSessionsHour.md @@ -1,6 +1,7 @@ # UsageRumSessionsHour Number of RUM Sessions recorded for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageRumSessionsResponse.md b/docs/v1/UsageRumSessionsResponse.md index 64130786a3..6cbace88fc 100644 --- a/docs/v1/UsageRumSessionsResponse.md +++ b/docs/v1/UsageRumSessionsResponse.md @@ -1,6 +1,7 @@ # UsageRumSessionsResponse Response containing the number of RUM Sessions for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSNMPHour.md b/docs/v1/UsageSNMPHour.md index 7c9f3aae9c..ea653e0b1d 100644 --- a/docs/v1/UsageSNMPHour.md +++ b/docs/v1/UsageSNMPHour.md @@ -1,6 +1,7 @@ # UsageSNMPHour The number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSNMPResponse.md b/docs/v1/UsageSNMPResponse.md index 6e65a521f7..9eac0bb8b5 100644 --- a/docs/v1/UsageSNMPResponse.md +++ b/docs/v1/UsageSNMPResponse.md @@ -1,6 +1,7 @@ # UsageSNMPResponse Response containing the number of SNMP devices for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSort.md b/docs/v1/UsageSort.md index 174de460b2..83e8d72c24 100644 --- a/docs/v1/UsageSort.md +++ b/docs/v1/UsageSort.md @@ -1,6 +1,7 @@ # UsageSort The field to sort by. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSortDirection.md b/docs/v1/UsageSortDirection.md index b3a5a675a0..6145ac42c1 100644 --- a/docs/v1/UsageSortDirection.md +++ b/docs/v1/UsageSortDirection.md @@ -1,6 +1,7 @@ # UsageSortDirection The direction to sort by. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSpecifiedCustomReportsAttributes.md b/docs/v1/UsageSpecifiedCustomReportsAttributes.md index 5e665c0b80..e43e34941a 100644 --- a/docs/v1/UsageSpecifiedCustomReportsAttributes.md +++ b/docs/v1/UsageSpecifiedCustomReportsAttributes.md @@ -1,6 +1,7 @@ # UsageSpecifiedCustomReportsAttributes The response containing attributes for specified custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSpecifiedCustomReportsData.md b/docs/v1/UsageSpecifiedCustomReportsData.md index 5d89d337db..f710e0706e 100644 --- a/docs/v1/UsageSpecifiedCustomReportsData.md +++ b/docs/v1/UsageSpecifiedCustomReportsData.md @@ -1,6 +1,7 @@ # UsageSpecifiedCustomReportsData Response containing date and type for specified custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSpecifiedCustomReportsMeta.md b/docs/v1/UsageSpecifiedCustomReportsMeta.md index 2498e94035..d0f95e2c60 100644 --- a/docs/v1/UsageSpecifiedCustomReportsMeta.md +++ b/docs/v1/UsageSpecifiedCustomReportsMeta.md @@ -1,6 +1,7 @@ # UsageSpecifiedCustomReportsMeta The object containing document metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSpecifiedCustomReportsPage.md b/docs/v1/UsageSpecifiedCustomReportsPage.md index 7025bbfd87..99a260dc4e 100644 --- a/docs/v1/UsageSpecifiedCustomReportsPage.md +++ b/docs/v1/UsageSpecifiedCustomReportsPage.md @@ -1,6 +1,7 @@ # UsageSpecifiedCustomReportsPage The object containing page total count for specified ID. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSpecifiedCustomReportsResponse.md b/docs/v1/UsageSpecifiedCustomReportsResponse.md index bf60b09f03..06ea770817 100644 --- a/docs/v1/UsageSpecifiedCustomReportsResponse.md +++ b/docs/v1/UsageSpecifiedCustomReportsResponse.md @@ -1,6 +1,7 @@ # UsageSpecifiedCustomReportsResponse Returns available specified custom reports. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSummaryDate.md b/docs/v1/UsageSummaryDate.md index c3a36e61df..8aa746ed1c 100644 --- a/docs/v1/UsageSummaryDate.md +++ b/docs/v1/UsageSummaryDate.md @@ -1,6 +1,7 @@ # UsageSummaryDate Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSummaryDateOrg.md b/docs/v1/UsageSummaryDateOrg.md index a9a909d48f..e4f1dc5ff2 100644 --- a/docs/v1/UsageSummaryDateOrg.md +++ b/docs/v1/UsageSummaryDateOrg.md @@ -1,6 +1,7 @@ # UsageSummaryDateOrg Global hourly report of all data billed by Datadog for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSummaryResponse.md b/docs/v1/UsageSummaryResponse.md index 4761dda848..d1c71b014e 100644 --- a/docs/v1/UsageSummaryResponse.md +++ b/docs/v1/UsageSummaryResponse.md @@ -1,6 +1,7 @@ # UsageSummaryResponse Response with hourly report of all data billed by Datadog all organizations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsAPIHour.md b/docs/v1/UsageSyntheticsAPIHour.md index 80c999979e..a6bc7e9886 100644 --- a/docs/v1/UsageSyntheticsAPIHour.md +++ b/docs/v1/UsageSyntheticsAPIHour.md @@ -1,6 +1,7 @@ # UsageSyntheticsAPIHour Number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsAPIResponse.md b/docs/v1/UsageSyntheticsAPIResponse.md index 62ba612fe4..65294c93ae 100644 --- a/docs/v1/UsageSyntheticsAPIResponse.md +++ b/docs/v1/UsageSyntheticsAPIResponse.md @@ -1,6 +1,7 @@ # UsageSyntheticsAPIResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsBrowserHour.md b/docs/v1/UsageSyntheticsBrowserHour.md index 49b63a32e4..f31058efef 100644 --- a/docs/v1/UsageSyntheticsBrowserHour.md +++ b/docs/v1/UsageSyntheticsBrowserHour.md @@ -1,6 +1,7 @@ # UsageSyntheticsBrowserHour Number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsBrowserResponse.md b/docs/v1/UsageSyntheticsBrowserResponse.md index 26365daae2..fde99d6e92 100644 --- a/docs/v1/UsageSyntheticsBrowserResponse.md +++ b/docs/v1/UsageSyntheticsBrowserResponse.md @@ -1,6 +1,7 @@ # UsageSyntheticsBrowserResponse Response containing the number of Synthetics Browser tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsHour.md b/docs/v1/UsageSyntheticsHour.md index 2266f16cf9..8b26be18f3 100644 --- a/docs/v1/UsageSyntheticsHour.md +++ b/docs/v1/UsageSyntheticsHour.md @@ -1,6 +1,7 @@ # UsageSyntheticsHour The number of synthetics tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageSyntheticsResponse.md b/docs/v1/UsageSyntheticsResponse.md index 675f205fd4..e04e9ba2d6 100644 --- a/docs/v1/UsageSyntheticsResponse.md +++ b/docs/v1/UsageSyntheticsResponse.md @@ -1,6 +1,7 @@ # UsageSyntheticsResponse Response containing the number of Synthetics API tests run for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTimeseriesHour.md b/docs/v1/UsageTimeseriesHour.md index 1aab7fb3a2..1f5a4d2937 100644 --- a/docs/v1/UsageTimeseriesHour.md +++ b/docs/v1/UsageTimeseriesHour.md @@ -1,6 +1,7 @@ # UsageTimeseriesHour The hourly usage of timeseries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTimeseriesResponse.md b/docs/v1/UsageTimeseriesResponse.md index 3f10b93013..13699d0b69 100644 --- a/docs/v1/UsageTimeseriesResponse.md +++ b/docs/v1/UsageTimeseriesResponse.md @@ -1,6 +1,7 @@ # UsageTimeseriesResponse Response containing hourly usage of timeseries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTopAvgMetricsHour.md b/docs/v1/UsageTopAvgMetricsHour.md index 7eb0ce35b3..138626734c 100644 --- a/docs/v1/UsageTopAvgMetricsHour.md +++ b/docs/v1/UsageTopAvgMetricsHour.md @@ -1,6 +1,7 @@ # UsageTopAvgMetricsHour Number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTopAvgMetricsResponse.md b/docs/v1/UsageTopAvgMetricsResponse.md index 1b30f94967..39f587c757 100644 --- a/docs/v1/UsageTopAvgMetricsResponse.md +++ b/docs/v1/UsageTopAvgMetricsResponse.md @@ -1,6 +1,7 @@ # UsageTopAvgMetricsResponse Response containing the number of hourly recorded custom metrics for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTraceHour.md b/docs/v1/UsageTraceHour.md index ee9bf0c89c..0ecb69c27a 100644 --- a/docs/v1/UsageTraceHour.md +++ b/docs/v1/UsageTraceHour.md @@ -1,6 +1,7 @@ # UsageTraceHour The hours of trace usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTraceResponse.md b/docs/v1/UsageTraceResponse.md index 052e3a7aaf..3f8521690a 100644 --- a/docs/v1/UsageTraceResponse.md +++ b/docs/v1/UsageTraceResponse.md @@ -1,6 +1,7 @@ # UsageTraceResponse A response containing trace usage. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTracingWithoutLimitsHour.md b/docs/v1/UsageTracingWithoutLimitsHour.md index f8bbe87a3d..22770fb364 100644 --- a/docs/v1/UsageTracingWithoutLimitsHour.md +++ b/docs/v1/UsageTracingWithoutLimitsHour.md @@ -1,6 +1,7 @@ # UsageTracingWithoutLimitsHour Tracing without limits usage for a given organization for a given hour. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsageTracingWithoutLimitsResponse.md b/docs/v1/UsageTracingWithoutLimitsResponse.md index 8bf1b5204c..d808b9d28d 100644 --- a/docs/v1/UsageTracingWithoutLimitsResponse.md +++ b/docs/v1/UsageTracingWithoutLimitsResponse.md @@ -1,6 +1,7 @@ # UsageTracingWithoutLimitsResponse Response containing the tracing without limits usage for each hour for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/User.md b/docs/v1/User.md index f576125586..f59aabb2d0 100644 --- a/docs/v1/User.md +++ b/docs/v1/User.md @@ -1,6 +1,7 @@ # User Create, edit, and disable users. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UserDisableResponse.md b/docs/v1/UserDisableResponse.md index b25e2b7300..6dd4ab6cec 100644 --- a/docs/v1/UserDisableResponse.md +++ b/docs/v1/UserDisableResponse.md @@ -1,6 +1,7 @@ # UserDisableResponse Array of user disabled for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UserListResponse.md b/docs/v1/UserListResponse.md index 788d8be355..bc6d5feb74 100644 --- a/docs/v1/UserListResponse.md +++ b/docs/v1/UserListResponse.md @@ -1,6 +1,7 @@ # UserListResponse Array of Datadog users for a given organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UserResponse.md b/docs/v1/UserResponse.md index aebc86a69c..9aece1b8c7 100644 --- a/docs/v1/UserResponse.md +++ b/docs/v1/UserResponse.md @@ -1,6 +1,7 @@ # UserResponse A Datadog User. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/UsersApi.md b/docs/v1/UsersApi.md index eb8b633ee5..eae95d47a3 100644 --- a/docs/v1/UsersApi.md +++ b/docs/v1/UsersApi.md @@ -65,6 +65,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->create_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -84,6 +85,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -140,6 +142,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->disable_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -159,6 +162,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -215,6 +219,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->get_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -234,6 +239,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -288,6 +294,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->list_users: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -304,6 +311,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -367,6 +375,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->update_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -387,6 +396,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v1/Widget.md b/docs/v1/Widget.md index 88b0336067..440ccbf1f0 100644 --- a/docs/v1/Widget.md +++ b/docs/v1/Widget.md @@ -1,6 +1,7 @@ # Widget Information about widget. Note: The `layout` property is required for widgets in dashboards with `free` `layout_type` only. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetAggregator.md b/docs/v1/WidgetAggregator.md index 38e623a90e..c15b836259 100644 --- a/docs/v1/WidgetAggregator.md +++ b/docs/v1/WidgetAggregator.md @@ -1,6 +1,7 @@ # WidgetAggregator Aggregator used for the request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetAxis.md b/docs/v1/WidgetAxis.md index 51c47dc81b..653e2b0e40 100644 --- a/docs/v1/WidgetAxis.md +++ b/docs/v1/WidgetAxis.md @@ -1,6 +1,7 @@ # WidgetAxis Axis controls for the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetChangeType.md b/docs/v1/WidgetChangeType.md index 543e07690c..9cd88c3263 100644 --- a/docs/v1/WidgetChangeType.md +++ b/docs/v1/WidgetChangeType.md @@ -1,6 +1,7 @@ # WidgetChangeType Show the absolute or the relative change. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetColorPreference.md b/docs/v1/WidgetColorPreference.md index 194dd0e2b4..919a9f9416 100644 --- a/docs/v1/WidgetColorPreference.md +++ b/docs/v1/WidgetColorPreference.md @@ -1,6 +1,7 @@ # WidgetColorPreference Which color to use on the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetComparator.md b/docs/v1/WidgetComparator.md index 5cc9c57029..47fbebdd7d 100644 --- a/docs/v1/WidgetComparator.md +++ b/docs/v1/WidgetComparator.md @@ -1,6 +1,7 @@ # WidgetComparator Comparator to apply. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetCompareTo.md b/docs/v1/WidgetCompareTo.md index d07e564289..ff8ba0c629 100644 --- a/docs/v1/WidgetCompareTo.md +++ b/docs/v1/WidgetCompareTo.md @@ -1,6 +1,7 @@ # WidgetCompareTo Timeframe used for the change comparison. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetConditionalFormat.md b/docs/v1/WidgetConditionalFormat.md index 2e4ae93e68..1d76f8b942 100644 --- a/docs/v1/WidgetConditionalFormat.md +++ b/docs/v1/WidgetConditionalFormat.md @@ -1,6 +1,7 @@ # WidgetConditionalFormat Define a conditional format for the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetCustomLink.md b/docs/v1/WidgetCustomLink.md index 4d1b1a8b94..b9bc75bbf1 100644 --- a/docs/v1/WidgetCustomLink.md +++ b/docs/v1/WidgetCustomLink.md @@ -1,6 +1,7 @@ # WidgetCustomLink Custom links help you connect a data value to a URL, like a Datadog page or your AWS console. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetDefinition.md b/docs/v1/WidgetDefinition.md index 46cd88b4b2..f7237ebf22 100644 --- a/docs/v1/WidgetDefinition.md +++ b/docs/v1/WidgetDefinition.md @@ -1,6 +1,7 @@ # WidgetDefinition [Definition of the widget](https://docs.datadoghq.com/dashboards/widgets/). + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetDisplayType.md b/docs/v1/WidgetDisplayType.md index 098c640eef..3cdbdaa4e5 100644 --- a/docs/v1/WidgetDisplayType.md +++ b/docs/v1/WidgetDisplayType.md @@ -1,6 +1,7 @@ # WidgetDisplayType Type of display to use for the request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetEvent.md b/docs/v1/WidgetEvent.md index e513f14036..1c4dba6f6f 100644 --- a/docs/v1/WidgetEvent.md +++ b/docs/v1/WidgetEvent.md @@ -1,6 +1,7 @@ # WidgetEvent Event overlay control options. See the dedicated [Events JSON schema documentation](https://docs.datadoghq.com/dashboards/graphing_json/widget_json/#events-schema) to learn how to build the ``. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetEventSize.md b/docs/v1/WidgetEventSize.md index 02ee96ef1f..6d33d5819a 100644 --- a/docs/v1/WidgetEventSize.md +++ b/docs/v1/WidgetEventSize.md @@ -1,6 +1,7 @@ # WidgetEventSize Size to use to display an event. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetFieldSort.md b/docs/v1/WidgetFieldSort.md index 02799537b0..94cb303244 100644 --- a/docs/v1/WidgetFieldSort.md +++ b/docs/v1/WidgetFieldSort.md @@ -1,6 +1,7 @@ # WidgetFieldSort Which column and order to sort by + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetFormula.md b/docs/v1/WidgetFormula.md index a1961f5b76..68fa17f5e0 100644 --- a/docs/v1/WidgetFormula.md +++ b/docs/v1/WidgetFormula.md @@ -1,6 +1,7 @@ # WidgetFormula Formula to be used in a widget query. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetFormulaLimit.md b/docs/v1/WidgetFormulaLimit.md index 35b7bca627..d101a0549f 100644 --- a/docs/v1/WidgetFormulaLimit.md +++ b/docs/v1/WidgetFormulaLimit.md @@ -1,6 +1,7 @@ # WidgetFormulaLimit Options for limiting results returned. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetGrouping.md b/docs/v1/WidgetGrouping.md index 889acb15d4..6b00a65d19 100644 --- a/docs/v1/WidgetGrouping.md +++ b/docs/v1/WidgetGrouping.md @@ -1,6 +1,7 @@ # WidgetGrouping The kind of grouping to use. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetImageSizing.md b/docs/v1/WidgetImageSizing.md index e0480a215f..bfffa3315c 100644 --- a/docs/v1/WidgetImageSizing.md +++ b/docs/v1/WidgetImageSizing.md @@ -1,6 +1,7 @@ # WidgetImageSizing How to size the image on the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetLayout.md b/docs/v1/WidgetLayout.md index 4782d433ce..7a685ef2d1 100644 --- a/docs/v1/WidgetLayout.md +++ b/docs/v1/WidgetLayout.md @@ -1,6 +1,7 @@ # WidgetLayout The layout for a widget on a free dashboard. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetLayoutType.md b/docs/v1/WidgetLayoutType.md index ec672d53e7..4b659bd6db 100644 --- a/docs/v1/WidgetLayoutType.md +++ b/docs/v1/WidgetLayoutType.md @@ -1,6 +1,7 @@ # WidgetLayoutType Layout type of the group. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetLineType.md b/docs/v1/WidgetLineType.md index 039b100924..949ce00a20 100644 --- a/docs/v1/WidgetLineType.md +++ b/docs/v1/WidgetLineType.md @@ -1,6 +1,7 @@ # WidgetLineType Type of lines displayed. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetLineWidth.md b/docs/v1/WidgetLineWidth.md index 91217fabb3..59874ec7bf 100644 --- a/docs/v1/WidgetLineWidth.md +++ b/docs/v1/WidgetLineWidth.md @@ -1,6 +1,7 @@ # WidgetLineWidth Width of line displayed. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetLiveSpan.md b/docs/v1/WidgetLiveSpan.md index e43dd2b7b8..d47dbed15d 100644 --- a/docs/v1/WidgetLiveSpan.md +++ b/docs/v1/WidgetLiveSpan.md @@ -1,6 +1,7 @@ # WidgetLiveSpan The available timeframes depend on the widget you are using. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetMargin.md b/docs/v1/WidgetMargin.md index 3f446f4867..234374f7c2 100644 --- a/docs/v1/WidgetMargin.md +++ b/docs/v1/WidgetMargin.md @@ -1,6 +1,7 @@ # WidgetMargin Size of the margins around the image. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetMarker.md b/docs/v1/WidgetMarker.md index 152f8577a7..075786f456 100644 --- a/docs/v1/WidgetMarker.md +++ b/docs/v1/WidgetMarker.md @@ -1,6 +1,7 @@ # WidgetMarker Markers allow you to add visual conditional formatting for your graphs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetMessageDisplay.md b/docs/v1/WidgetMessageDisplay.md index 9e74d5dfa4..cd5a1cc8af 100644 --- a/docs/v1/WidgetMessageDisplay.md +++ b/docs/v1/WidgetMessageDisplay.md @@ -1,6 +1,7 @@ # WidgetMessageDisplay Amount of log lines to display + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetMonitorSummaryDisplayFormat.md b/docs/v1/WidgetMonitorSummaryDisplayFormat.md index fd6d8f9135..26f0ffa744 100644 --- a/docs/v1/WidgetMonitorSummaryDisplayFormat.md +++ b/docs/v1/WidgetMonitorSummaryDisplayFormat.md @@ -1,6 +1,7 @@ # WidgetMonitorSummaryDisplayFormat What to display on the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetMonitorSummarySort.md b/docs/v1/WidgetMonitorSummarySort.md index 0c4aaecd05..b5e0096aa6 100644 --- a/docs/v1/WidgetMonitorSummarySort.md +++ b/docs/v1/WidgetMonitorSummarySort.md @@ -1,6 +1,7 @@ # WidgetMonitorSummarySort Widget sorting methods. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetNodeType.md b/docs/v1/WidgetNodeType.md index 5deac04872..c5ec7e6fdc 100644 --- a/docs/v1/WidgetNodeType.md +++ b/docs/v1/WidgetNodeType.md @@ -1,6 +1,7 @@ # WidgetNodeType Which type of node to use in the map. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetOrderBy.md b/docs/v1/WidgetOrderBy.md index fa8ffa57f2..18112e7139 100644 --- a/docs/v1/WidgetOrderBy.md +++ b/docs/v1/WidgetOrderBy.md @@ -1,6 +1,7 @@ # WidgetOrderBy What to order by. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetPalette.md b/docs/v1/WidgetPalette.md index d0cb154137..6e49a3f1d0 100644 --- a/docs/v1/WidgetPalette.md +++ b/docs/v1/WidgetPalette.md @@ -1,6 +1,7 @@ # WidgetPalette Color palette to apply. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetRequestStyle.md b/docs/v1/WidgetRequestStyle.md index 03dbfce987..bd4cf38d69 100644 --- a/docs/v1/WidgetRequestStyle.md +++ b/docs/v1/WidgetRequestStyle.md @@ -1,6 +1,7 @@ # WidgetRequestStyle Define request widget style. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetServiceSummaryDisplayFormat.md b/docs/v1/WidgetServiceSummaryDisplayFormat.md index 74ad1f0300..164f75803a 100644 --- a/docs/v1/WidgetServiceSummaryDisplayFormat.md +++ b/docs/v1/WidgetServiceSummaryDisplayFormat.md @@ -1,6 +1,7 @@ # WidgetServiceSummaryDisplayFormat Number of columns to display. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetSizeFormat.md b/docs/v1/WidgetSizeFormat.md index 2efc8d0e51..876e32ede6 100644 --- a/docs/v1/WidgetSizeFormat.md +++ b/docs/v1/WidgetSizeFormat.md @@ -1,6 +1,7 @@ # WidgetSizeFormat Size of the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetSort.md b/docs/v1/WidgetSort.md index bb8a6a597a..28d6bca389 100644 --- a/docs/v1/WidgetSort.md +++ b/docs/v1/WidgetSort.md @@ -1,6 +1,7 @@ # WidgetSort Widget sorting methods. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetStyle.md b/docs/v1/WidgetStyle.md index c8a403d5ad..ad7f58015f 100644 --- a/docs/v1/WidgetStyle.md +++ b/docs/v1/WidgetStyle.md @@ -1,6 +1,7 @@ # WidgetStyle Widget style definition. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetSummaryType.md b/docs/v1/WidgetSummaryType.md index 433f5307d6..c2e0271339 100644 --- a/docs/v1/WidgetSummaryType.md +++ b/docs/v1/WidgetSummaryType.md @@ -1,6 +1,7 @@ # WidgetSummaryType Which summary type should be used. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetTextAlign.md b/docs/v1/WidgetTextAlign.md index e2e8425bea..ea6477fac3 100644 --- a/docs/v1/WidgetTextAlign.md +++ b/docs/v1/WidgetTextAlign.md @@ -1,6 +1,7 @@ # WidgetTextAlign How to align the text on the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetTickEdge.md b/docs/v1/WidgetTickEdge.md index 254e91068f..bd549ae310 100644 --- a/docs/v1/WidgetTickEdge.md +++ b/docs/v1/WidgetTickEdge.md @@ -1,6 +1,7 @@ # WidgetTickEdge Define how you want to align the text on the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetTime.md b/docs/v1/WidgetTime.md index 74299c5cd1..1672787c57 100644 --- a/docs/v1/WidgetTime.md +++ b/docs/v1/WidgetTime.md @@ -1,6 +1,7 @@ # WidgetTime Time setting for the widget. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetTimeWindows.md b/docs/v1/WidgetTimeWindows.md index 8995c8a078..38a0a8b04d 100644 --- a/docs/v1/WidgetTimeWindows.md +++ b/docs/v1/WidgetTimeWindows.md @@ -1,6 +1,7 @@ # WidgetTimeWindows Define a time window. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetViewMode.md b/docs/v1/WidgetViewMode.md index 596af29328..48a4539737 100644 --- a/docs/v1/WidgetViewMode.md +++ b/docs/v1/WidgetViewMode.md @@ -1,6 +1,7 @@ # WidgetViewMode Define how you want the SLO to be displayed. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v1/WidgetVizType.md b/docs/v1/WidgetVizType.md index a74864ccba..1720882452 100644 --- a/docs/v1/WidgetVizType.md +++ b/docs/v1/WidgetVizType.md @@ -1,6 +1,7 @@ # WidgetVizType Whether to display the Alert Graph as a timeseries or a top list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIErrorResponse.md b/docs/v2/APIErrorResponse.md index f1f9ad9278..884da9c546 100644 --- a/docs/v2/APIErrorResponse.md +++ b/docs/v2/APIErrorResponse.md @@ -1,6 +1,7 @@ # APIErrorResponse API error response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyCreateAttributes.md b/docs/v2/APIKeyCreateAttributes.md index ce014e8b3f..43365e3ffa 100644 --- a/docs/v2/APIKeyCreateAttributes.md +++ b/docs/v2/APIKeyCreateAttributes.md @@ -1,6 +1,7 @@ # APIKeyCreateAttributes Attributes used to create an API Key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyCreateData.md b/docs/v2/APIKeyCreateData.md index f826af539d..d1d9e60fbb 100644 --- a/docs/v2/APIKeyCreateData.md +++ b/docs/v2/APIKeyCreateData.md @@ -1,6 +1,7 @@ # APIKeyCreateData Object used to create an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyCreateRequest.md b/docs/v2/APIKeyCreateRequest.md index 37bc3954c9..9ce2b43714 100644 --- a/docs/v2/APIKeyCreateRequest.md +++ b/docs/v2/APIKeyCreateRequest.md @@ -1,6 +1,7 @@ # APIKeyCreateRequest Request used to create an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyRelationships.md b/docs/v2/APIKeyRelationships.md index 6d265582e5..8ee83c4bf1 100644 --- a/docs/v2/APIKeyRelationships.md +++ b/docs/v2/APIKeyRelationships.md @@ -1,6 +1,7 @@ # APIKeyRelationships Resources related to the API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyResponse.md b/docs/v2/APIKeyResponse.md index 67722ea49a..9ec08f2a5a 100644 --- a/docs/v2/APIKeyResponse.md +++ b/docs/v2/APIKeyResponse.md @@ -1,6 +1,7 @@ # APIKeyResponse Response for retrieving an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyResponseIncludedItem.md b/docs/v2/APIKeyResponseIncludedItem.md index 5d4201c849..72de1c5db9 100644 --- a/docs/v2/APIKeyResponseIncludedItem.md +++ b/docs/v2/APIKeyResponseIncludedItem.md @@ -1,6 +1,7 @@ # APIKeyResponseIncludedItem An object related to an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyUpdateAttributes.md b/docs/v2/APIKeyUpdateAttributes.md index af4e2623fa..cbf1f566bd 100644 --- a/docs/v2/APIKeyUpdateAttributes.md +++ b/docs/v2/APIKeyUpdateAttributes.md @@ -1,6 +1,7 @@ # APIKeyUpdateAttributes Attributes used to update an API Key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyUpdateData.md b/docs/v2/APIKeyUpdateData.md index be42e61e01..f93c5c8c75 100644 --- a/docs/v2/APIKeyUpdateData.md +++ b/docs/v2/APIKeyUpdateData.md @@ -1,6 +1,7 @@ # APIKeyUpdateData Object used to update an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeyUpdateRequest.md b/docs/v2/APIKeyUpdateRequest.md index 3792832a0d..3e91f12bcd 100644 --- a/docs/v2/APIKeyUpdateRequest.md +++ b/docs/v2/APIKeyUpdateRequest.md @@ -1,6 +1,7 @@ # APIKeyUpdateRequest Request used to update an API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeysResponse.md b/docs/v2/APIKeysResponse.md index cf80b312b4..81f9f4f42a 100644 --- a/docs/v2/APIKeysResponse.md +++ b/docs/v2/APIKeysResponse.md @@ -1,6 +1,7 @@ # APIKeysResponse Response for a list of API keys. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeysSort.md b/docs/v2/APIKeysSort.md index 9ad198010f..7b0d376a9b 100644 --- a/docs/v2/APIKeysSort.md +++ b/docs/v2/APIKeysSort.md @@ -1,6 +1,7 @@ # APIKeysSort Sorting options + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/APIKeysType.md b/docs/v2/APIKeysType.md index f6275b9a1d..654e21a9ce 100644 --- a/docs/v2/APIKeysType.md +++ b/docs/v2/APIKeysType.md @@ -1,6 +1,7 @@ # APIKeysType API Keys resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyCreateAttributes.md b/docs/v2/ApplicationKeyCreateAttributes.md index b531f9209e..1cae1917a0 100644 --- a/docs/v2/ApplicationKeyCreateAttributes.md +++ b/docs/v2/ApplicationKeyCreateAttributes.md @@ -1,6 +1,7 @@ # ApplicationKeyCreateAttributes Attributes used to create an application Key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyCreateData.md b/docs/v2/ApplicationKeyCreateData.md index c4adad1202..22621ed196 100644 --- a/docs/v2/ApplicationKeyCreateData.md +++ b/docs/v2/ApplicationKeyCreateData.md @@ -1,6 +1,7 @@ # ApplicationKeyCreateData Object used to create an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyCreateRequest.md b/docs/v2/ApplicationKeyCreateRequest.md index 66826bd71f..56572e59d2 100644 --- a/docs/v2/ApplicationKeyCreateRequest.md +++ b/docs/v2/ApplicationKeyCreateRequest.md @@ -1,6 +1,7 @@ # ApplicationKeyCreateRequest Request used to create an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyRelationships.md b/docs/v2/ApplicationKeyRelationships.md index a836e1d89a..99d7a03b92 100644 --- a/docs/v2/ApplicationKeyRelationships.md +++ b/docs/v2/ApplicationKeyRelationships.md @@ -1,6 +1,7 @@ # ApplicationKeyRelationships Resources related to the application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyResponse.md b/docs/v2/ApplicationKeyResponse.md index ff62248c23..44874904ba 100644 --- a/docs/v2/ApplicationKeyResponse.md +++ b/docs/v2/ApplicationKeyResponse.md @@ -1,6 +1,7 @@ # ApplicationKeyResponse Response for retrieving an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyResponseIncludedItem.md b/docs/v2/ApplicationKeyResponseIncludedItem.md index e6c7a854ae..b91d3325a0 100644 --- a/docs/v2/ApplicationKeyResponseIncludedItem.md +++ b/docs/v2/ApplicationKeyResponseIncludedItem.md @@ -1,6 +1,7 @@ # ApplicationKeyResponseIncludedItem An object related to an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyUpdateAttributes.md b/docs/v2/ApplicationKeyUpdateAttributes.md index 9846965d4b..a7f4bfc90c 100644 --- a/docs/v2/ApplicationKeyUpdateAttributes.md +++ b/docs/v2/ApplicationKeyUpdateAttributes.md @@ -1,6 +1,7 @@ # ApplicationKeyUpdateAttributes Attributes used to update an application Key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyUpdateData.md b/docs/v2/ApplicationKeyUpdateData.md index 1f80522c89..4682e3ba1e 100644 --- a/docs/v2/ApplicationKeyUpdateData.md +++ b/docs/v2/ApplicationKeyUpdateData.md @@ -1,6 +1,7 @@ # ApplicationKeyUpdateData Object used to update an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeyUpdateRequest.md b/docs/v2/ApplicationKeyUpdateRequest.md index 70887d8aef..992ff32271 100644 --- a/docs/v2/ApplicationKeyUpdateRequest.md +++ b/docs/v2/ApplicationKeyUpdateRequest.md @@ -1,6 +1,7 @@ # ApplicationKeyUpdateRequest Request used to update an application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeysSort.md b/docs/v2/ApplicationKeysSort.md index 230d4756bd..724d41a765 100644 --- a/docs/v2/ApplicationKeysSort.md +++ b/docs/v2/ApplicationKeysSort.md @@ -1,6 +1,7 @@ # ApplicationKeysSort Sorting options + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ApplicationKeysType.md b/docs/v2/ApplicationKeysType.md index dda5d2202c..becc746baa 100644 --- a/docs/v2/ApplicationKeysType.md +++ b/docs/v2/ApplicationKeysType.md @@ -1,6 +1,7 @@ # ApplicationKeysType Application Keys resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Creator.md b/docs/v2/Creator.md index 210d6874c7..d3cb8596f0 100644 --- a/docs/v2/Creator.md +++ b/docs/v2/Creator.md @@ -1,6 +1,7 @@ # Creator Creator of the object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListAddItemsRequest.md b/docs/v2/DashboardListAddItemsRequest.md index 6adb971111..b00c88323c 100644 --- a/docs/v2/DashboardListAddItemsRequest.md +++ b/docs/v2/DashboardListAddItemsRequest.md @@ -1,6 +1,7 @@ # DashboardListAddItemsRequest Request containing a list of dashboards to add. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListAddItemsResponse.md b/docs/v2/DashboardListAddItemsResponse.md index 1acf8d44ab..0f8990ef54 100644 --- a/docs/v2/DashboardListAddItemsResponse.md +++ b/docs/v2/DashboardListAddItemsResponse.md @@ -1,6 +1,7 @@ # DashboardListAddItemsResponse Response containing a list of added dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListDeleteItemsRequest.md b/docs/v2/DashboardListDeleteItemsRequest.md index bcf5eaf9c9..ec64f49619 100644 --- a/docs/v2/DashboardListDeleteItemsRequest.md +++ b/docs/v2/DashboardListDeleteItemsRequest.md @@ -1,6 +1,7 @@ # DashboardListDeleteItemsRequest Request containing a list of dashboards to delete. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListDeleteItemsResponse.md b/docs/v2/DashboardListDeleteItemsResponse.md index 0196692d6f..7553bc89cc 100644 --- a/docs/v2/DashboardListDeleteItemsResponse.md +++ b/docs/v2/DashboardListDeleteItemsResponse.md @@ -1,6 +1,7 @@ # DashboardListDeleteItemsResponse Response containing a list of deleted dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListItem.md b/docs/v2/DashboardListItem.md index 7b9ad6af38..c370c9d743 100644 --- a/docs/v2/DashboardListItem.md +++ b/docs/v2/DashboardListItem.md @@ -1,6 +1,7 @@ # DashboardListItem A dashboard within a list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListItemRequest.md b/docs/v2/DashboardListItemRequest.md index 0f5105aa01..b6aa9d0284 100644 --- a/docs/v2/DashboardListItemRequest.md +++ b/docs/v2/DashboardListItemRequest.md @@ -1,6 +1,7 @@ # DashboardListItemRequest A dashboard within a list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListItemResponse.md b/docs/v2/DashboardListItemResponse.md index 876de995ac..dcaf3e4700 100644 --- a/docs/v2/DashboardListItemResponse.md +++ b/docs/v2/DashboardListItemResponse.md @@ -1,6 +1,7 @@ # DashboardListItemResponse A dashboard within a list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListItems.md b/docs/v2/DashboardListItems.md index 2347f9a035..31258c83ac 100644 --- a/docs/v2/DashboardListItems.md +++ b/docs/v2/DashboardListItems.md @@ -1,6 +1,7 @@ # DashboardListItems Dashboards within a list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListUpdateItemsRequest.md b/docs/v2/DashboardListUpdateItemsRequest.md index f76b95f83d..a68db523d7 100644 --- a/docs/v2/DashboardListUpdateItemsRequest.md +++ b/docs/v2/DashboardListUpdateItemsRequest.md @@ -1,6 +1,7 @@ # DashboardListUpdateItemsRequest Request containing the list of dashboards to update to. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListUpdateItemsResponse.md b/docs/v2/DashboardListUpdateItemsResponse.md index 855edb3bd6..8cf8105241 100644 --- a/docs/v2/DashboardListUpdateItemsResponse.md +++ b/docs/v2/DashboardListUpdateItemsResponse.md @@ -1,6 +1,7 @@ # DashboardListUpdateItemsResponse Response containing a list of updated dashboards. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/DashboardListsApi.md b/docs/v2/DashboardListsApi.md index a621119f8f..02d43bc51b 100644 --- a/docs/v2/DashboardListsApi.md +++ b/docs/v2/DashboardListsApi.md @@ -64,6 +64,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->create_dashboard_list_items: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -84,6 +85,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -148,6 +150,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->delete_dashboard_list_items: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -168,6 +171,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -224,6 +228,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->get_dashboard_list_items: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -243,6 +248,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -306,6 +312,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling DashboardListsApi->update_dashboard_list_items: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -326,6 +333,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/DashboardType.md b/docs/v2/DashboardType.md index 7bcaa2af3f..241d61bf5d 100644 --- a/docs/v2/DashboardType.md +++ b/docs/v2/DashboardType.md @@ -1,6 +1,7 @@ # DashboardType The type of the dashboard. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/FullAPIKey.md b/docs/v2/FullAPIKey.md index 6f5d1e7314..ea86f3a823 100644 --- a/docs/v2/FullAPIKey.md +++ b/docs/v2/FullAPIKey.md @@ -1,6 +1,7 @@ # FullAPIKey Datadog API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/FullAPIKeyAttributes.md b/docs/v2/FullAPIKeyAttributes.md index e460e53b57..87c66a072f 100644 --- a/docs/v2/FullAPIKeyAttributes.md +++ b/docs/v2/FullAPIKeyAttributes.md @@ -1,6 +1,7 @@ # FullAPIKeyAttributes Attributes of a full API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/FullApplicationKey.md b/docs/v2/FullApplicationKey.md index bf719df70c..36ccd62f35 100644 --- a/docs/v2/FullApplicationKey.md +++ b/docs/v2/FullApplicationKey.md @@ -1,6 +1,7 @@ # FullApplicationKey Datadog application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/FullApplicationKeyAttributes.md b/docs/v2/FullApplicationKeyAttributes.md index 24624eadf0..79384a3e7e 100644 --- a/docs/v2/FullApplicationKeyAttributes.md +++ b/docs/v2/FullApplicationKeyAttributes.md @@ -1,6 +1,7 @@ # FullApplicationKeyAttributes Attributes of a full application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentCreateAttributes.md b/docs/v2/IncidentCreateAttributes.md index d27caa45c0..872bec0d7d 100644 --- a/docs/v2/IncidentCreateAttributes.md +++ b/docs/v2/IncidentCreateAttributes.md @@ -1,6 +1,7 @@ # IncidentCreateAttributes The incident's attributes for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentCreateData.md b/docs/v2/IncidentCreateData.md index d7fe74e185..e3ac8d5844 100644 --- a/docs/v2/IncidentCreateData.md +++ b/docs/v2/IncidentCreateData.md @@ -1,6 +1,7 @@ # IncidentCreateData Incident data for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentCreateRelationships.md b/docs/v2/IncidentCreateRelationships.md index 9f2a72555d..333dd0e6f8 100644 --- a/docs/v2/IncidentCreateRelationships.md +++ b/docs/v2/IncidentCreateRelationships.md @@ -1,6 +1,7 @@ # IncidentCreateRelationships The relationships the incident will have with other resources once created. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentCreateRequest.md b/docs/v2/IncidentCreateRequest.md index dabf9c8a8a..eee8f78117 100644 --- a/docs/v2/IncidentCreateRequest.md +++ b/docs/v2/IncidentCreateRequest.md @@ -1,6 +1,7 @@ # IncidentCreateRequest Create request for an incident. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentFieldAttributes.md b/docs/v2/IncidentFieldAttributes.md index ae09882500..2647af240c 100644 --- a/docs/v2/IncidentFieldAttributes.md +++ b/docs/v2/IncidentFieldAttributes.md @@ -1,6 +1,7 @@ # IncidentFieldAttributes Dynamic fields for which selections can be made, with field names as keys. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentFieldAttributesMultipleValue.md b/docs/v2/IncidentFieldAttributesMultipleValue.md index d068680e3a..19498a6768 100644 --- a/docs/v2/IncidentFieldAttributesMultipleValue.md +++ b/docs/v2/IncidentFieldAttributesMultipleValue.md @@ -1,6 +1,7 @@ # IncidentFieldAttributesMultipleValue A field with potentially multiple values selected. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentFieldAttributesSingleValue.md b/docs/v2/IncidentFieldAttributesSingleValue.md index 388cde7207..bef119b486 100644 --- a/docs/v2/IncidentFieldAttributesSingleValue.md +++ b/docs/v2/IncidentFieldAttributesSingleValue.md @@ -1,6 +1,7 @@ # IncidentFieldAttributesSingleValue A field with a single value selected. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentFieldAttributesSingleValueType.md b/docs/v2/IncidentFieldAttributesSingleValueType.md index 1b5e79af92..af06f50951 100644 --- a/docs/v2/IncidentFieldAttributesSingleValueType.md +++ b/docs/v2/IncidentFieldAttributesSingleValueType.md @@ -1,6 +1,7 @@ # IncidentFieldAttributesSingleValueType Type of the single value field definitions. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentFieldAttributesValueType.md b/docs/v2/IncidentFieldAttributesValueType.md index 3e03f9b92f..40facc43ee 100644 --- a/docs/v2/IncidentFieldAttributesValueType.md +++ b/docs/v2/IncidentFieldAttributesValueType.md @@ -1,6 +1,7 @@ # IncidentFieldAttributesValueType Type of the single value field definitions. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentIntegrationMetadataType.md b/docs/v2/IncidentIntegrationMetadataType.md index 385db4ce70..9abd278a96 100644 --- a/docs/v2/IncidentIntegrationMetadataType.md +++ b/docs/v2/IncidentIntegrationMetadataType.md @@ -1,6 +1,7 @@ # IncidentIntegrationMetadataType Integration metadata resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentPostmortemType.md b/docs/v2/IncidentPostmortemType.md index 9d7011e378..f0e4570a29 100644 --- a/docs/v2/IncidentPostmortemType.md +++ b/docs/v2/IncidentPostmortemType.md @@ -1,6 +1,7 @@ # IncidentPostmortemType Incident postmortem resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentRelatedObject.md b/docs/v2/IncidentRelatedObject.md index ba4542a4bb..b6c94bbffb 100644 --- a/docs/v2/IncidentRelatedObject.md +++ b/docs/v2/IncidentRelatedObject.md @@ -1,6 +1,7 @@ # IncidentRelatedObject Object related to an incident. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentResponse.md b/docs/v2/IncidentResponse.md index c42dc330f8..a315fed1db 100644 --- a/docs/v2/IncidentResponse.md +++ b/docs/v2/IncidentResponse.md @@ -1,6 +1,7 @@ # IncidentResponse Response with an incident. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentResponseAttributes.md b/docs/v2/IncidentResponseAttributes.md index d3e794c293..702d887e51 100644 --- a/docs/v2/IncidentResponseAttributes.md +++ b/docs/v2/IncidentResponseAttributes.md @@ -1,6 +1,7 @@ # IncidentResponseAttributes The incident's attributes from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentResponseData.md b/docs/v2/IncidentResponseData.md index d8f7711651..7084284b38 100644 --- a/docs/v2/IncidentResponseData.md +++ b/docs/v2/IncidentResponseData.md @@ -1,6 +1,7 @@ # IncidentResponseData Incident data from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentResponseIncludedItem.md b/docs/v2/IncidentResponseIncludedItem.md index 8726683fbb..737b34a424 100644 --- a/docs/v2/IncidentResponseIncludedItem.md +++ b/docs/v2/IncidentResponseIncludedItem.md @@ -1,6 +1,7 @@ # IncidentResponseIncludedItem An object related to an incident that is included in the response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentResponseRelationships.md b/docs/v2/IncidentResponseRelationships.md index 79f2fca317..3b6ebb96b0 100644 --- a/docs/v2/IncidentResponseRelationships.md +++ b/docs/v2/IncidentResponseRelationships.md @@ -1,6 +1,7 @@ # IncidentResponseRelationships The incident's relationships from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceCreateAttributes.md b/docs/v2/IncidentServiceCreateAttributes.md index 1d70366956..0ad20a91cb 100644 --- a/docs/v2/IncidentServiceCreateAttributes.md +++ b/docs/v2/IncidentServiceCreateAttributes.md @@ -1,6 +1,7 @@ # IncidentServiceCreateAttributes The incident service's attributes for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceCreateData.md b/docs/v2/IncidentServiceCreateData.md index 0e379aff11..2573d02954 100644 --- a/docs/v2/IncidentServiceCreateData.md +++ b/docs/v2/IncidentServiceCreateData.md @@ -1,6 +1,7 @@ # IncidentServiceCreateData Incident Service payload for create requests. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceCreateRequest.md b/docs/v2/IncidentServiceCreateRequest.md index 6b248756a0..aff3bb7d02 100644 --- a/docs/v2/IncidentServiceCreateRequest.md +++ b/docs/v2/IncidentServiceCreateRequest.md @@ -1,6 +1,7 @@ # IncidentServiceCreateRequest Create request with an incident service payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceIncludedItems.md b/docs/v2/IncidentServiceIncludedItems.md index 908c1e9bd2..e929188564 100644 --- a/docs/v2/IncidentServiceIncludedItems.md +++ b/docs/v2/IncidentServiceIncludedItems.md @@ -1,6 +1,7 @@ # IncidentServiceIncludedItems An object related to an incident service which is present in the included payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceRelationships.md b/docs/v2/IncidentServiceRelationships.md index c25f098831..96368f0f79 100644 --- a/docs/v2/IncidentServiceRelationships.md +++ b/docs/v2/IncidentServiceRelationships.md @@ -1,6 +1,7 @@ # IncidentServiceRelationships The incident service's relationships. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceResponse.md b/docs/v2/IncidentServiceResponse.md index c086c2dfa0..b45f67e827 100644 --- a/docs/v2/IncidentServiceResponse.md +++ b/docs/v2/IncidentServiceResponse.md @@ -1,6 +1,7 @@ # IncidentServiceResponse Response with an incident service payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceResponseAttributes.md b/docs/v2/IncidentServiceResponseAttributes.md index f878abc6ac..63340158c7 100644 --- a/docs/v2/IncidentServiceResponseAttributes.md +++ b/docs/v2/IncidentServiceResponseAttributes.md @@ -1,6 +1,7 @@ # IncidentServiceResponseAttributes The incident service's attributes from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceResponseData.md b/docs/v2/IncidentServiceResponseData.md index 2556d45fa7..b87638aa32 100644 --- a/docs/v2/IncidentServiceResponseData.md +++ b/docs/v2/IncidentServiceResponseData.md @@ -1,6 +1,7 @@ # IncidentServiceResponseData Incident Service data from responses. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceType.md b/docs/v2/IncidentServiceType.md index d42b192ab2..48c4e38123 100644 --- a/docs/v2/IncidentServiceType.md +++ b/docs/v2/IncidentServiceType.md @@ -1,6 +1,7 @@ # IncidentServiceType Incident service resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceUpdateAttributes.md b/docs/v2/IncidentServiceUpdateAttributes.md index 78f82e56e2..7217a5a0f4 100644 --- a/docs/v2/IncidentServiceUpdateAttributes.md +++ b/docs/v2/IncidentServiceUpdateAttributes.md @@ -1,6 +1,7 @@ # IncidentServiceUpdateAttributes The incident service's attributes for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceUpdateData.md b/docs/v2/IncidentServiceUpdateData.md index 18cd9b58f5..911e2fd413 100644 --- a/docs/v2/IncidentServiceUpdateData.md +++ b/docs/v2/IncidentServiceUpdateData.md @@ -1,6 +1,7 @@ # IncidentServiceUpdateData Incident Service payload for update requests. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServiceUpdateRequest.md b/docs/v2/IncidentServiceUpdateRequest.md index 8029a47adb..b504b4f09b 100644 --- a/docs/v2/IncidentServiceUpdateRequest.md +++ b/docs/v2/IncidentServiceUpdateRequest.md @@ -1,6 +1,7 @@ # IncidentServiceUpdateRequest Update request with an incident service payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServicesApi.md b/docs/v2/IncidentServicesApi.md index a482943ae6..36339fd245 100644 --- a/docs/v2/IncidentServicesApi.md +++ b/docs/v2/IncidentServicesApi.md @@ -79,6 +79,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentServicesApi->create_incident_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -98,6 +99,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -155,6 +157,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentServicesApi->delete_incident_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -174,6 +177,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -242,6 +246,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentServicesApi->get_incident_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -262,6 +267,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -324,6 +330,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentServicesApi->list_incident_services: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -346,6 +353,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -427,6 +435,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentServicesApi->update_incident_service: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -447,6 +456,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/IncidentServicesResponse.md b/docs/v2/IncidentServicesResponse.md index 8c4f78cbc3..c0950bdfe5 100644 --- a/docs/v2/IncidentServicesResponse.md +++ b/docs/v2/IncidentServicesResponse.md @@ -1,6 +1,7 @@ # IncidentServicesResponse Response with a list of incident service payloads. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServicesResponseMeta.md b/docs/v2/IncidentServicesResponseMeta.md index f170bc0e43..4dc5586d6c 100644 --- a/docs/v2/IncidentServicesResponseMeta.md +++ b/docs/v2/IncidentServicesResponseMeta.md @@ -1,6 +1,7 @@ # IncidentServicesResponseMeta The metadata object containing pagination metadata. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentServicesResponseMetaPagination.md b/docs/v2/IncidentServicesResponseMetaPagination.md index 6998b11d23..a4f32eb706 100644 --- a/docs/v2/IncidentServicesResponseMetaPagination.md +++ b/docs/v2/IncidentServicesResponseMetaPagination.md @@ -1,6 +1,7 @@ # IncidentServicesResponseMetaPagination Pagination properties. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamCreateAttributes.md b/docs/v2/IncidentTeamCreateAttributes.md index c9478f51e2..aa15f7aa3d 100644 --- a/docs/v2/IncidentTeamCreateAttributes.md +++ b/docs/v2/IncidentTeamCreateAttributes.md @@ -1,6 +1,7 @@ # IncidentTeamCreateAttributes The incident team's attributes for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamCreateData.md b/docs/v2/IncidentTeamCreateData.md index e9c4688b39..929dfe03b2 100644 --- a/docs/v2/IncidentTeamCreateData.md +++ b/docs/v2/IncidentTeamCreateData.md @@ -1,6 +1,7 @@ # IncidentTeamCreateData Incident Team data for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamCreateRequest.md b/docs/v2/IncidentTeamCreateRequest.md index 8da133ea98..0bc922e3dd 100644 --- a/docs/v2/IncidentTeamCreateRequest.md +++ b/docs/v2/IncidentTeamCreateRequest.md @@ -1,6 +1,7 @@ # IncidentTeamCreateRequest Create request with an incident team payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamIncludedItems.md b/docs/v2/IncidentTeamIncludedItems.md index 9fd34f64e2..d9feac3cac 100644 --- a/docs/v2/IncidentTeamIncludedItems.md +++ b/docs/v2/IncidentTeamIncludedItems.md @@ -1,6 +1,7 @@ # IncidentTeamIncludedItems An object related to an incident team which is present in the included payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamRelationships.md b/docs/v2/IncidentTeamRelationships.md index 0c568a21ae..f0d06eb027 100644 --- a/docs/v2/IncidentTeamRelationships.md +++ b/docs/v2/IncidentTeamRelationships.md @@ -1,6 +1,7 @@ # IncidentTeamRelationships The incident team's relationships. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamResponse.md b/docs/v2/IncidentTeamResponse.md index 6b59428ef9..09f1710d40 100644 --- a/docs/v2/IncidentTeamResponse.md +++ b/docs/v2/IncidentTeamResponse.md @@ -1,6 +1,7 @@ # IncidentTeamResponse Response with an incident team payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamResponseAttributes.md b/docs/v2/IncidentTeamResponseAttributes.md index f77843f863..9dbd7ba162 100644 --- a/docs/v2/IncidentTeamResponseAttributes.md +++ b/docs/v2/IncidentTeamResponseAttributes.md @@ -1,6 +1,7 @@ # IncidentTeamResponseAttributes The incident team's attributes from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamResponseData.md b/docs/v2/IncidentTeamResponseData.md index b41c5ddc5a..e87e1f3751 100644 --- a/docs/v2/IncidentTeamResponseData.md +++ b/docs/v2/IncidentTeamResponseData.md @@ -1,6 +1,7 @@ # IncidentTeamResponseData Incident Team data from a response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamType.md b/docs/v2/IncidentTeamType.md index f41b0b3944..be9a80a715 100644 --- a/docs/v2/IncidentTeamType.md +++ b/docs/v2/IncidentTeamType.md @@ -1,6 +1,7 @@ # IncidentTeamType Incident Team resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamUpdateAttributes.md b/docs/v2/IncidentTeamUpdateAttributes.md index fa76191b73..3ad16a2a8c 100644 --- a/docs/v2/IncidentTeamUpdateAttributes.md +++ b/docs/v2/IncidentTeamUpdateAttributes.md @@ -1,6 +1,7 @@ # IncidentTeamUpdateAttributes The incident team's attributes for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamUpdateData.md b/docs/v2/IncidentTeamUpdateData.md index 18898020fc..5672d6521e 100644 --- a/docs/v2/IncidentTeamUpdateData.md +++ b/docs/v2/IncidentTeamUpdateData.md @@ -1,6 +1,7 @@ # IncidentTeamUpdateData Incident Team data for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamUpdateRequest.md b/docs/v2/IncidentTeamUpdateRequest.md index e914f42346..84ba704f10 100644 --- a/docs/v2/IncidentTeamUpdateRequest.md +++ b/docs/v2/IncidentTeamUpdateRequest.md @@ -1,6 +1,7 @@ # IncidentTeamUpdateRequest Update request with an incident team payload. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTeamsApi.md b/docs/v2/IncidentTeamsApi.md index 4ae9a356d9..31c6b09cf7 100644 --- a/docs/v2/IncidentTeamsApi.md +++ b/docs/v2/IncidentTeamsApi.md @@ -79,6 +79,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentTeamsApi->create_incident_team: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -98,6 +99,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -155,6 +157,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentTeamsApi->delete_incident_team: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -174,6 +177,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -242,6 +246,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentTeamsApi->get_incident_team: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -262,6 +267,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -324,6 +330,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentTeamsApi->list_incident_teams: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -346,6 +353,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -427,6 +435,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentTeamsApi->update_incident_team: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -447,6 +456,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/IncidentTeamsResponse.md b/docs/v2/IncidentTeamsResponse.md index 77b5554db7..9c5601e7cb 100644 --- a/docs/v2/IncidentTeamsResponse.md +++ b/docs/v2/IncidentTeamsResponse.md @@ -1,6 +1,7 @@ # IncidentTeamsResponse Response with a list of incident team payloads. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTimelineCellCreateAttributes.md b/docs/v2/IncidentTimelineCellCreateAttributes.md index 3e48367654..e04cc4f95f 100644 --- a/docs/v2/IncidentTimelineCellCreateAttributes.md +++ b/docs/v2/IncidentTimelineCellCreateAttributes.md @@ -1,6 +1,7 @@ # IncidentTimelineCellCreateAttributes The timeline cell's attributes for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTimelineCellMarkdownContentType.md b/docs/v2/IncidentTimelineCellMarkdownContentType.md index 5b6a139650..774c096476 100644 --- a/docs/v2/IncidentTimelineCellMarkdownContentType.md +++ b/docs/v2/IncidentTimelineCellMarkdownContentType.md @@ -1,6 +1,7 @@ # IncidentTimelineCellMarkdownContentType Type of the Markdown timeline cell. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md b/docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md index 0a6706815e..f5b736f2c8 100644 --- a/docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md +++ b/docs/v2/IncidentTimelineCellMarkdownCreateAttributes.md @@ -1,6 +1,7 @@ # IncidentTimelineCellMarkdownCreateAttributes Timeline cell data for Markdown timeline cells for a create request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md b/docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md index 97d3335e98..f3dc7ee146 100644 --- a/docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md +++ b/docs/v2/IncidentTimelineCellMarkdownCreateAttributesContent.md @@ -1,6 +1,7 @@ # IncidentTimelineCellMarkdownCreateAttributesContent The Markdown timeline cell contents. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentType.md b/docs/v2/IncidentType.md index 15a46c3c70..8efc21f6b5 100644 --- a/docs/v2/IncidentType.md +++ b/docs/v2/IncidentType.md @@ -1,6 +1,7 @@ # IncidentType Incident resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentUpdateAttributes.md b/docs/v2/IncidentUpdateAttributes.md index 7ed4f5149a..4a2deb7629 100644 --- a/docs/v2/IncidentUpdateAttributes.md +++ b/docs/v2/IncidentUpdateAttributes.md @@ -1,6 +1,7 @@ # IncidentUpdateAttributes The incident's attributes for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentUpdateData.md b/docs/v2/IncidentUpdateData.md index 43e358d311..7294187938 100644 --- a/docs/v2/IncidentUpdateData.md +++ b/docs/v2/IncidentUpdateData.md @@ -1,6 +1,7 @@ # IncidentUpdateData Incident data for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentUpdateRelationships.md b/docs/v2/IncidentUpdateRelationships.md index d5a3d96b61..845eebb76b 100644 --- a/docs/v2/IncidentUpdateRelationships.md +++ b/docs/v2/IncidentUpdateRelationships.md @@ -1,6 +1,7 @@ # IncidentUpdateRelationships The incident's relationships for an update request. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentUpdateRequest.md b/docs/v2/IncidentUpdateRequest.md index eb1c528e60..f8eab93199 100644 --- a/docs/v2/IncidentUpdateRequest.md +++ b/docs/v2/IncidentUpdateRequest.md @@ -1,6 +1,7 @@ # IncidentUpdateRequest Update request for an incident. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/IncidentsApi.md b/docs/v2/IncidentsApi.md index 2c564190a6..0babcece46 100644 --- a/docs/v2/IncidentsApi.md +++ b/docs/v2/IncidentsApi.md @@ -83,6 +83,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentsApi->create_incident: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -102,6 +103,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -159,6 +161,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentsApi->delete_incident: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -178,6 +181,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -248,6 +252,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentsApi->get_incident: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -268,6 +273,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -331,6 +337,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentsApi->list_incidents: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -352,6 +359,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -460,6 +468,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling IncidentsApi->update_incident: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -480,6 +489,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/IncidentsResponse.md b/docs/v2/IncidentsResponse.md index 8b21b70c43..e1a15628a1 100644 --- a/docs/v2/IncidentsResponse.md +++ b/docs/v2/IncidentsResponse.md @@ -1,6 +1,7 @@ # IncidentsResponse Response with a list of incidents. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/KeyManagementApi.md b/docs/v2/KeyManagementApi.md index ede953c2b5..6e728ec22d 100644 --- a/docs/v2/KeyManagementApi.md +++ b/docs/v2/KeyManagementApi.md @@ -72,6 +72,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->create_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -91,6 +92,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -153,6 +155,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->create_current_user_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -172,6 +175,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -226,6 +230,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->delete_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -245,6 +250,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -299,6 +305,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->delete_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -318,6 +325,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -372,6 +380,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->delete_current_user_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -391,6 +400,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -456,6 +466,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->get_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -476,6 +487,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -531,6 +543,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->get_current_user_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -550,6 +563,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -614,6 +628,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->list_api_keys: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -641,6 +656,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -702,6 +718,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->list_application_keys: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -726,6 +743,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -788,6 +806,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->list_current_user_application_keys: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -812,6 +831,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -877,6 +897,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->update_api_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -897,6 +918,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -962,6 +984,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->update_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -982,6 +1005,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -1047,6 +1071,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling KeyManagementApi->update_current_user_application_key: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -1067,6 +1092,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/ListApplicationKeysResponse.md b/docs/v2/ListApplicationKeysResponse.md index f1b2329016..22b5eb2055 100644 --- a/docs/v2/ListApplicationKeysResponse.md +++ b/docs/v2/ListApplicationKeysResponse.md @@ -1,6 +1,7 @@ # ListApplicationKeysResponse Response for a list of application keys. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Log.md b/docs/v2/Log.md index b7664dc030..ed4c47d38c 100644 --- a/docs/v2/Log.md +++ b/docs/v2/Log.md @@ -1,6 +1,7 @@ # Log Object description of a log after being processed and stored by Datadog. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogAttributes.md b/docs/v2/LogAttributes.md index 34ac52b393..9ecb2300d4 100644 --- a/docs/v2/LogAttributes.md +++ b/docs/v2/LogAttributes.md @@ -1,6 +1,7 @@ # LogAttributes JSON object containing all log attributes and their associated values. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogType.md b/docs/v2/LogType.md index 893f157b7c..f5c4f68213 100644 --- a/docs/v2/LogType.md +++ b/docs/v2/LogType.md @@ -1,6 +1,7 @@ # LogType Type of the event. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateBucket.md b/docs/v2/LogsAggregateBucket.md index ef07cdab0a..ea7b3416d0 100644 --- a/docs/v2/LogsAggregateBucket.md +++ b/docs/v2/LogsAggregateBucket.md @@ -1,6 +1,7 @@ # LogsAggregateBucket A bucket values + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateBucketValue.md b/docs/v2/LogsAggregateBucketValue.md index 616b313fed..1216bf2f84 100644 --- a/docs/v2/LogsAggregateBucketValue.md +++ b/docs/v2/LogsAggregateBucketValue.md @@ -1,6 +1,7 @@ # LogsAggregateBucketValue A bucket value, can be either a timeseries or a single value + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateBucketValueTimeseries.md b/docs/v2/LogsAggregateBucketValueTimeseries.md index 9833f436cd..1095f76895 100644 --- a/docs/v2/LogsAggregateBucketValueTimeseries.md +++ b/docs/v2/LogsAggregateBucketValueTimeseries.md @@ -1,6 +1,7 @@ # LogsAggregateBucketValueTimeseries A timeseries array + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateBucketValueTimeseriesPoint.md b/docs/v2/LogsAggregateBucketValueTimeseriesPoint.md index 7ab2894b20..9b99fb9b43 100644 --- a/docs/v2/LogsAggregateBucketValueTimeseriesPoint.md +++ b/docs/v2/LogsAggregateBucketValueTimeseriesPoint.md @@ -1,6 +1,7 @@ # LogsAggregateBucketValueTimeseriesPoint A timeseries point + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateRequest.md b/docs/v2/LogsAggregateRequest.md index 8ba87aa524..3e24ab6063 100644 --- a/docs/v2/LogsAggregateRequest.md +++ b/docs/v2/LogsAggregateRequest.md @@ -1,6 +1,7 @@ # LogsAggregateRequest The object sent with the request to retrieve a list of logs from your organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateRequestPage.md b/docs/v2/LogsAggregateRequestPage.md index 1a464c4645..7aee59a5e5 100644 --- a/docs/v2/LogsAggregateRequestPage.md +++ b/docs/v2/LogsAggregateRequestPage.md @@ -1,6 +1,7 @@ # LogsAggregateRequestPage Paging settings + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateResponse.md b/docs/v2/LogsAggregateResponse.md index 8ae7115003..116d5997c9 100644 --- a/docs/v2/LogsAggregateResponse.md +++ b/docs/v2/LogsAggregateResponse.md @@ -1,6 +1,7 @@ # LogsAggregateResponse The response object for the logs aggregate API endpoint + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateResponseData.md b/docs/v2/LogsAggregateResponseData.md index 0071e95733..549dd3b2bd 100644 --- a/docs/v2/LogsAggregateResponseData.md +++ b/docs/v2/LogsAggregateResponseData.md @@ -1,6 +1,7 @@ # LogsAggregateResponseData The query results + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateResponseStatus.md b/docs/v2/LogsAggregateResponseStatus.md index 8fce246ae1..ba40980463 100644 --- a/docs/v2/LogsAggregateResponseStatus.md +++ b/docs/v2/LogsAggregateResponseStatus.md @@ -1,6 +1,7 @@ # LogsAggregateResponseStatus The status of the response + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateSort.md b/docs/v2/LogsAggregateSort.md index af02fbaefa..cca2b352ea 100644 --- a/docs/v2/LogsAggregateSort.md +++ b/docs/v2/LogsAggregateSort.md @@ -1,6 +1,7 @@ # LogsAggregateSort A sort rule + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregateSortType.md b/docs/v2/LogsAggregateSortType.md index 97fd94dd4d..04efb36fe9 100644 --- a/docs/v2/LogsAggregateSortType.md +++ b/docs/v2/LogsAggregateSortType.md @@ -1,6 +1,7 @@ # LogsAggregateSortType The type of sorting algorithm + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsAggregationFunction.md b/docs/v2/LogsAggregationFunction.md index 2b6dd29ebf..41cca5594f 100644 --- a/docs/v2/LogsAggregationFunction.md +++ b/docs/v2/LogsAggregationFunction.md @@ -1,6 +1,7 @@ # LogsAggregationFunction An aggregation function + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsApi.md b/docs/v2/LogsApi.md index ec6e91fc68..0414d03da5 100644 --- a/docs/v2/LogsApi.md +++ b/docs/v2/LogsApi.md @@ -96,6 +96,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsApi->aggregate_logs: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -115,6 +116,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -187,6 +189,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsApi->list_logs: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -206,6 +209,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -268,6 +272,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsApi->list_logs_get: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -293,6 +298,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/LogsArchive.md b/docs/v2/LogsArchive.md index 83dadee3d6..6f71e86922 100644 --- a/docs/v2/LogsArchive.md +++ b/docs/v2/LogsArchive.md @@ -1,6 +1,7 @@ # LogsArchive The logs archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveAttributes.md b/docs/v2/LogsArchiveAttributes.md index e1a385a6ac..408901489c 100644 --- a/docs/v2/LogsArchiveAttributes.md +++ b/docs/v2/LogsArchiveAttributes.md @@ -1,6 +1,7 @@ # LogsArchiveAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveCreateRequest.md b/docs/v2/LogsArchiveCreateRequest.md index f60aa5e6ba..84a199cfe0 100644 --- a/docs/v2/LogsArchiveCreateRequest.md +++ b/docs/v2/LogsArchiveCreateRequest.md @@ -1,6 +1,7 @@ # LogsArchiveCreateRequest The logs archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveCreateRequestAttributes.md b/docs/v2/LogsArchiveCreateRequestAttributes.md index 4d8df7a85d..26654b2b6e 100644 --- a/docs/v2/LogsArchiveCreateRequestAttributes.md +++ b/docs/v2/LogsArchiveCreateRequestAttributes.md @@ -1,6 +1,7 @@ # LogsArchiveCreateRequestAttributes The attributes associated with the archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveCreateRequestDefinition.md b/docs/v2/LogsArchiveCreateRequestDefinition.md index ca21f7c6c7..bea71231f6 100644 --- a/docs/v2/LogsArchiveCreateRequestDefinition.md +++ b/docs/v2/LogsArchiveCreateRequestDefinition.md @@ -1,6 +1,7 @@ # LogsArchiveCreateRequestDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveCreateRequestDestination.md b/docs/v2/LogsArchiveCreateRequestDestination.md index b241c557d1..2a70532cf6 100644 --- a/docs/v2/LogsArchiveCreateRequestDestination.md +++ b/docs/v2/LogsArchiveCreateRequestDestination.md @@ -1,6 +1,7 @@ # LogsArchiveCreateRequestDestination An archive's destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDefinition.md b/docs/v2/LogsArchiveDefinition.md index b2ac1f80fc..dd1d5d3e36 100644 --- a/docs/v2/LogsArchiveDefinition.md +++ b/docs/v2/LogsArchiveDefinition.md @@ -1,6 +1,7 @@ # LogsArchiveDefinition The definition of an archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestination.md b/docs/v2/LogsArchiveDestination.md index 7777a630bc..7631b84fce 100644 --- a/docs/v2/LogsArchiveDestination.md +++ b/docs/v2/LogsArchiveDestination.md @@ -1,6 +1,7 @@ # LogsArchiveDestination An archive's destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationAzure.md b/docs/v2/LogsArchiveDestinationAzure.md index fc8a621219..3d1835ca29 100644 --- a/docs/v2/LogsArchiveDestinationAzure.md +++ b/docs/v2/LogsArchiveDestinationAzure.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationAzure The Azure archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationAzureType.md b/docs/v2/LogsArchiveDestinationAzureType.md index 103cfc1cf1..9ad8de780f 100644 --- a/docs/v2/LogsArchiveDestinationAzureType.md +++ b/docs/v2/LogsArchiveDestinationAzureType.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationAzureType Type of the Azure archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationGCS.md b/docs/v2/LogsArchiveDestinationGCS.md index 9d9c43256d..8445ffc388 100644 --- a/docs/v2/LogsArchiveDestinationGCS.md +++ b/docs/v2/LogsArchiveDestinationGCS.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationGCS The GCS archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationGCSType.md b/docs/v2/LogsArchiveDestinationGCSType.md index 3d0fcef9f1..4e407f9b91 100644 --- a/docs/v2/LogsArchiveDestinationGCSType.md +++ b/docs/v2/LogsArchiveDestinationGCSType.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationGCSType Type of the GCS archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationS3.md b/docs/v2/LogsArchiveDestinationS3.md index 35f720a6f7..7c196afd4d 100644 --- a/docs/v2/LogsArchiveDestinationS3.md +++ b/docs/v2/LogsArchiveDestinationS3.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationS3 The S3 archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveDestinationS3Type.md b/docs/v2/LogsArchiveDestinationS3Type.md index c1c900318e..3921b20e52 100644 --- a/docs/v2/LogsArchiveDestinationS3Type.md +++ b/docs/v2/LogsArchiveDestinationS3Type.md @@ -1,6 +1,7 @@ # LogsArchiveDestinationS3Type Type of the S3 archive destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveIntegrationAzure.md b/docs/v2/LogsArchiveIntegrationAzure.md index 4ae0bf3fbf..fd262b5405 100644 --- a/docs/v2/LogsArchiveIntegrationAzure.md +++ b/docs/v2/LogsArchiveIntegrationAzure.md @@ -1,6 +1,7 @@ # LogsArchiveIntegrationAzure The Azure archive's integration destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveIntegrationGCS.md b/docs/v2/LogsArchiveIntegrationGCS.md index 2a1389eaec..0e197d72d6 100644 --- a/docs/v2/LogsArchiveIntegrationGCS.md +++ b/docs/v2/LogsArchiveIntegrationGCS.md @@ -1,6 +1,7 @@ # LogsArchiveIntegrationGCS The GCS archive's integration destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveIntegrationS3.md b/docs/v2/LogsArchiveIntegrationS3.md index 1ff583ca31..8eb69695d6 100644 --- a/docs/v2/LogsArchiveIntegrationS3.md +++ b/docs/v2/LogsArchiveIntegrationS3.md @@ -1,6 +1,7 @@ # LogsArchiveIntegrationS3 The S3 Archive's integration destination. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveOrder.md b/docs/v2/LogsArchiveOrder.md index 23e3e7080e..7b55b1402f 100644 --- a/docs/v2/LogsArchiveOrder.md +++ b/docs/v2/LogsArchiveOrder.md @@ -1,6 +1,7 @@ # LogsArchiveOrder A ordered list of archive IDs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveOrderAttributes.md b/docs/v2/LogsArchiveOrderAttributes.md index 17b39242e8..ff119a4a92 100644 --- a/docs/v2/LogsArchiveOrderAttributes.md +++ b/docs/v2/LogsArchiveOrderAttributes.md @@ -1,6 +1,7 @@ # LogsArchiveOrderAttributes The attributes associated with the archive order. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveOrderDefinition.md b/docs/v2/LogsArchiveOrderDefinition.md index e7e90b9829..191106e2a8 100644 --- a/docs/v2/LogsArchiveOrderDefinition.md +++ b/docs/v2/LogsArchiveOrderDefinition.md @@ -1,6 +1,7 @@ # LogsArchiveOrderDefinition The definition of an archive order. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveOrderDefinitionType.md b/docs/v2/LogsArchiveOrderDefinitionType.md index 2d17dd1877..e8eb465233 100644 --- a/docs/v2/LogsArchiveOrderDefinitionType.md +++ b/docs/v2/LogsArchiveOrderDefinitionType.md @@ -1,6 +1,7 @@ # LogsArchiveOrderDefinitionType Type of the archive order definition. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchiveState.md b/docs/v2/LogsArchiveState.md index ec1e5eaa36..52f7f350f1 100644 --- a/docs/v2/LogsArchiveState.md +++ b/docs/v2/LogsArchiveState.md @@ -1,6 +1,7 @@ # LogsArchiveState The state of the archive. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchives.md b/docs/v2/LogsArchives.md index c82c02c0bd..9909bd74c5 100644 --- a/docs/v2/LogsArchives.md +++ b/docs/v2/LogsArchives.md @@ -1,6 +1,7 @@ # LogsArchives The available archives. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsArchivesApi.md b/docs/v2/LogsArchivesApi.md index 3e8b8d74a8..9dc73c3db5 100644 --- a/docs/v2/LogsArchivesApi.md +++ b/docs/v2/LogsArchivesApi.md @@ -67,6 +67,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->add_read_role_to_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -87,6 +88,7 @@ void (empty response body) - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -154,6 +156,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->create_logs_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -173,6 +176,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -227,6 +231,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->delete_logs_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -246,6 +251,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -302,6 +308,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->get_logs_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -321,6 +328,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -376,6 +384,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->get_logs_archive_order: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -392,6 +401,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -446,6 +456,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->list_archive_read_roles: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -465,6 +476,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -520,6 +532,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->list_logs_archives: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -536,6 +549,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -595,6 +609,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->remove_role_from_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -615,6 +630,7 @@ void (empty response body) - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -683,6 +699,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->update_logs_archive: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -703,6 +720,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -766,6 +784,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsArchivesApi->update_logs_archive_order: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -785,6 +804,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/LogsCompute.md b/docs/v2/LogsCompute.md index 7bc1cd04ba..891b958017 100644 --- a/docs/v2/LogsCompute.md +++ b/docs/v2/LogsCompute.md @@ -1,6 +1,7 @@ # LogsCompute A compute rule to compute metrics or timeseries + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsComputeType.md b/docs/v2/LogsComputeType.md index 92464a5213..1ed39702fc 100644 --- a/docs/v2/LogsComputeType.md +++ b/docs/v2/LogsComputeType.md @@ -1,6 +1,7 @@ # LogsComputeType The type of compute + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsGroupBy.md b/docs/v2/LogsGroupBy.md index fb267e9eb1..0b9e84283a 100644 --- a/docs/v2/LogsGroupBy.md +++ b/docs/v2/LogsGroupBy.md @@ -1,6 +1,7 @@ # LogsGroupBy A group by rule + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsGroupByHistogram.md b/docs/v2/LogsGroupByHistogram.md index 5f46c6f609..805c97c912 100644 --- a/docs/v2/LogsGroupByHistogram.md +++ b/docs/v2/LogsGroupByHistogram.md @@ -1,6 +1,7 @@ # LogsGroupByHistogram Used to perform a histogram computation (only for measure facets). Note: At most 100 buckets are allowed, the number of buckets is (max - min)/interval. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsGroupByMissing.md b/docs/v2/LogsGroupByMissing.md index dd840f4b2e..02f5348c9a 100644 --- a/docs/v2/LogsGroupByMissing.md +++ b/docs/v2/LogsGroupByMissing.md @@ -1,6 +1,7 @@ # LogsGroupByMissing The value to use for logs that don't have the facet used to group by + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsGroupByTotal.md b/docs/v2/LogsGroupByTotal.md index 8b7abe16df..2e799ac261 100644 --- a/docs/v2/LogsGroupByTotal.md +++ b/docs/v2/LogsGroupByTotal.md @@ -1,6 +1,7 @@ # LogsGroupByTotal A resulting object to put the given computes in over all the matching records. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsListRequest.md b/docs/v2/LogsListRequest.md index 30bdb4b2fe..cd5e816bbf 100644 --- a/docs/v2/LogsListRequest.md +++ b/docs/v2/LogsListRequest.md @@ -1,6 +1,7 @@ # LogsListRequest The request for a logs list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsListRequestPage.md b/docs/v2/LogsListRequestPage.md index 6861f49bd0..5319446f7f 100644 --- a/docs/v2/LogsListRequestPage.md +++ b/docs/v2/LogsListRequestPage.md @@ -1,6 +1,7 @@ # LogsListRequestPage Paging attributes for listing logs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsListResponse.md b/docs/v2/LogsListResponse.md index f37f9e18a5..288828237f 100644 --- a/docs/v2/LogsListResponse.md +++ b/docs/v2/LogsListResponse.md @@ -1,6 +1,7 @@ # LogsListResponse Response object with all logs matching the request and pagination information. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsListResponseLinks.md b/docs/v2/LogsListResponseLinks.md index 4c176a1a05..41aa141d63 100644 --- a/docs/v2/LogsListResponseLinks.md +++ b/docs/v2/LogsListResponseLinks.md @@ -1,6 +1,7 @@ # LogsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricCompute.md b/docs/v2/LogsMetricCompute.md index a6743de122..db436888db 100644 --- a/docs/v2/LogsMetricCompute.md +++ b/docs/v2/LogsMetricCompute.md @@ -1,6 +1,7 @@ # LogsMetricCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricComputeAggregationType.md b/docs/v2/LogsMetricComputeAggregationType.md index 214a667353..dcab3f0b36 100644 --- a/docs/v2/LogsMetricComputeAggregationType.md +++ b/docs/v2/LogsMetricComputeAggregationType.md @@ -1,6 +1,7 @@ # LogsMetricComputeAggregationType The type of aggregation to use. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricCreateAttributes.md b/docs/v2/LogsMetricCreateAttributes.md index 6fbc481df2..c2762f30cc 100644 --- a/docs/v2/LogsMetricCreateAttributes.md +++ b/docs/v2/LogsMetricCreateAttributes.md @@ -1,6 +1,7 @@ # LogsMetricCreateAttributes The object describing the Datadog log-based metric to create. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricCreateData.md b/docs/v2/LogsMetricCreateData.md index 45d5769b08..dc6c94cd6c 100644 --- a/docs/v2/LogsMetricCreateData.md +++ b/docs/v2/LogsMetricCreateData.md @@ -1,6 +1,7 @@ # LogsMetricCreateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricCreateRequest.md b/docs/v2/LogsMetricCreateRequest.md index 4f0defa4a7..5c04aa5144 100644 --- a/docs/v2/LogsMetricCreateRequest.md +++ b/docs/v2/LogsMetricCreateRequest.md @@ -1,6 +1,7 @@ # LogsMetricCreateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricFilter.md b/docs/v2/LogsMetricFilter.md index 1d604976f6..f6821230dc 100644 --- a/docs/v2/LogsMetricFilter.md +++ b/docs/v2/LogsMetricFilter.md @@ -1,6 +1,7 @@ # LogsMetricFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricGroupBy.md b/docs/v2/LogsMetricGroupBy.md index c9b40dfdba..c64a42b93a 100644 --- a/docs/v2/LogsMetricGroupBy.md +++ b/docs/v2/LogsMetricGroupBy.md @@ -1,6 +1,7 @@ # LogsMetricGroupBy A group by rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponse.md b/docs/v2/LogsMetricResponse.md index 1517da44c6..7141c9f71a 100644 --- a/docs/v2/LogsMetricResponse.md +++ b/docs/v2/LogsMetricResponse.md @@ -1,6 +1,7 @@ # LogsMetricResponse The log-based metric object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseAttributes.md b/docs/v2/LogsMetricResponseAttributes.md index 43bf221961..e80a0608bf 100644 --- a/docs/v2/LogsMetricResponseAttributes.md +++ b/docs/v2/LogsMetricResponseAttributes.md @@ -1,6 +1,7 @@ # LogsMetricResponseAttributes The object describing a Datadog log-based metric. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseCompute.md b/docs/v2/LogsMetricResponseCompute.md index 945c514453..d3aea0d17e 100644 --- a/docs/v2/LogsMetricResponseCompute.md +++ b/docs/v2/LogsMetricResponseCompute.md @@ -1,6 +1,7 @@ # LogsMetricResponseCompute The compute rule to compute the log-based metric. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseComputeAggregationType.md b/docs/v2/LogsMetricResponseComputeAggregationType.md index 945ec1c130..d1ecad5918 100644 --- a/docs/v2/LogsMetricResponseComputeAggregationType.md +++ b/docs/v2/LogsMetricResponseComputeAggregationType.md @@ -1,6 +1,7 @@ # LogsMetricResponseComputeAggregationType The type of aggregation to use. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseData.md b/docs/v2/LogsMetricResponseData.md index 749cbbbd7b..a445940fb9 100644 --- a/docs/v2/LogsMetricResponseData.md +++ b/docs/v2/LogsMetricResponseData.md @@ -1,6 +1,7 @@ # LogsMetricResponseData The log-based metric properties. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseFilter.md b/docs/v2/LogsMetricResponseFilter.md index b719098a36..6abc761b35 100644 --- a/docs/v2/LogsMetricResponseFilter.md +++ b/docs/v2/LogsMetricResponseFilter.md @@ -1,6 +1,7 @@ # LogsMetricResponseFilter The log-based metric filter. Logs matching this filter will be aggregated in this metric. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricResponseGroupBy.md b/docs/v2/LogsMetricResponseGroupBy.md index 2b19d596e7..cd427049fa 100644 --- a/docs/v2/LogsMetricResponseGroupBy.md +++ b/docs/v2/LogsMetricResponseGroupBy.md @@ -1,6 +1,7 @@ # LogsMetricResponseGroupBy A group by rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricType.md b/docs/v2/LogsMetricType.md index 1c3578a02a..9a38faa577 100644 --- a/docs/v2/LogsMetricType.md +++ b/docs/v2/LogsMetricType.md @@ -1,6 +1,7 @@ # LogsMetricType The type of the resource. The value should always be logs_metrics. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricUpdateAttributes.md b/docs/v2/LogsMetricUpdateAttributes.md index aacd9e1f72..35acf2a2d5 100644 --- a/docs/v2/LogsMetricUpdateAttributes.md +++ b/docs/v2/LogsMetricUpdateAttributes.md @@ -1,6 +1,7 @@ # LogsMetricUpdateAttributes The log-based metric properties that will be updated. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricUpdateData.md b/docs/v2/LogsMetricUpdateData.md index c884927418..2b1a81ec81 100644 --- a/docs/v2/LogsMetricUpdateData.md +++ b/docs/v2/LogsMetricUpdateData.md @@ -1,6 +1,7 @@ # LogsMetricUpdateData The new log-based metric properties. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricUpdateRequest.md b/docs/v2/LogsMetricUpdateRequest.md index f9cab86f3a..6502c7c26b 100644 --- a/docs/v2/LogsMetricUpdateRequest.md +++ b/docs/v2/LogsMetricUpdateRequest.md @@ -1,6 +1,7 @@ # LogsMetricUpdateRequest The new log-based metric body. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsMetricsApi.md b/docs/v2/LogsMetricsApi.md index 579c8b2be8..ccba015135 100644 --- a/docs/v2/LogsMetricsApi.md +++ b/docs/v2/LogsMetricsApi.md @@ -77,6 +77,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsMetricsApi->create_logs_metric: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -96,6 +97,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -152,6 +154,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsMetricsApi->delete_logs_metric: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -171,6 +174,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -227,6 +231,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsMetricsApi->get_logs_metric: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -246,6 +251,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -301,6 +307,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsMetricsApi->list_logs_metrics: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -317,6 +324,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -388,6 +396,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling LogsMetricsApi->update_logs_metric: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -408,6 +417,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/LogsMetricsResponse.md b/docs/v2/LogsMetricsResponse.md index 54b1566b92..b936bbf8d1 100644 --- a/docs/v2/LogsMetricsResponse.md +++ b/docs/v2/LogsMetricsResponse.md @@ -1,6 +1,7 @@ # LogsMetricsResponse All the available log-based metric objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsQueryFilter.md b/docs/v2/LogsQueryFilter.md index 6d15c7e6b1..41da7f1724 100644 --- a/docs/v2/LogsQueryFilter.md +++ b/docs/v2/LogsQueryFilter.md @@ -1,6 +1,7 @@ # LogsQueryFilter The search and filter query settings + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsQueryOptions.md b/docs/v2/LogsQueryOptions.md index d6384bf870..4670fbfb68 100644 --- a/docs/v2/LogsQueryOptions.md +++ b/docs/v2/LogsQueryOptions.md @@ -1,6 +1,7 @@ # LogsQueryOptions Global query options that are used during the query. Note: You should only supply timezone or time offset but not both otherwise the query will fail. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsResponseMetadata.md b/docs/v2/LogsResponseMetadata.md index b52ebcfb4e..eff49f7fcd 100644 --- a/docs/v2/LogsResponseMetadata.md +++ b/docs/v2/LogsResponseMetadata.md @@ -1,6 +1,7 @@ # LogsResponseMetadata The metadata associated with a request + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsResponseMetadataPage.md b/docs/v2/LogsResponseMetadataPage.md index 267c3f4f25..6fea739b53 100644 --- a/docs/v2/LogsResponseMetadataPage.md +++ b/docs/v2/LogsResponseMetadataPage.md @@ -1,6 +1,7 @@ # LogsResponseMetadataPage Paging attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsSort.md b/docs/v2/LogsSort.md index b2ad991c06..d034ef1f67 100644 --- a/docs/v2/LogsSort.md +++ b/docs/v2/LogsSort.md @@ -1,6 +1,7 @@ # LogsSort Sort parameters when querying logs. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsSortOrder.md b/docs/v2/LogsSortOrder.md index 8af9706396..765e617fa0 100644 --- a/docs/v2/LogsSortOrder.md +++ b/docs/v2/LogsSortOrder.md @@ -1,6 +1,7 @@ # LogsSortOrder The order to use, ascending or descending + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/LogsWarning.md b/docs/v2/LogsWarning.md index 6a338ad792..c026c2c362 100644 --- a/docs/v2/LogsWarning.md +++ b/docs/v2/LogsWarning.md @@ -1,6 +1,7 @@ # LogsWarning A warning message indicating something that went wrong with the query + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Metric.md b/docs/v2/Metric.md index 81a6e3101c..e5bedd255f 100644 --- a/docs/v2/Metric.md +++ b/docs/v2/Metric.md @@ -1,6 +1,7 @@ # Metric Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricAllTags.md b/docs/v2/MetricAllTags.md index 0eb81e52a6..5f10a1416c 100644 --- a/docs/v2/MetricAllTags.md +++ b/docs/v2/MetricAllTags.md @@ -1,6 +1,7 @@ # MetricAllTags Object for a single metric's indexed tags. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricAllTagsAttributes.md b/docs/v2/MetricAllTagsAttributes.md index 4d90d7e673..43c560a471 100644 --- a/docs/v2/MetricAllTagsAttributes.md +++ b/docs/v2/MetricAllTagsAttributes.md @@ -1,6 +1,7 @@ # MetricAllTagsAttributes Object containing the definition of a metric's tags. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricAllTagsResponse.md b/docs/v2/MetricAllTagsResponse.md index 1b4324edb9..0010e6e8e9 100644 --- a/docs/v2/MetricAllTagsResponse.md +++ b/docs/v2/MetricAllTagsResponse.md @@ -1,6 +1,7 @@ # MetricAllTagsResponse Response object that includes a single metric's indexed tags. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricDistinctVolume.md b/docs/v2/MetricDistinctVolume.md index b4de20cf47..da426faf5b 100644 --- a/docs/v2/MetricDistinctVolume.md +++ b/docs/v2/MetricDistinctVolume.md @@ -1,6 +1,7 @@ # MetricDistinctVolume Object for a single metric's distinct volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricDistinctVolumeAttributes.md b/docs/v2/MetricDistinctVolumeAttributes.md index 5bdcf36f35..9b6a15c75d 100644 --- a/docs/v2/MetricDistinctVolumeAttributes.md +++ b/docs/v2/MetricDistinctVolumeAttributes.md @@ -1,6 +1,7 @@ # MetricDistinctVolumeAttributes Object containing the definition of a metric's distinct volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricDistinctVolumeType.md b/docs/v2/MetricDistinctVolumeType.md index 26d01c7b37..c293046e68 100644 --- a/docs/v2/MetricDistinctVolumeType.md +++ b/docs/v2/MetricDistinctVolumeType.md @@ -1,6 +1,7 @@ # MetricDistinctVolumeType The metric distinct volume type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricIngestedIndexedVolume.md b/docs/v2/MetricIngestedIndexedVolume.md index a02bf72e66..3b05c5194b 100644 --- a/docs/v2/MetricIngestedIndexedVolume.md +++ b/docs/v2/MetricIngestedIndexedVolume.md @@ -1,6 +1,7 @@ # MetricIngestedIndexedVolume Object for a single metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricIngestedIndexedVolumeAttributes.md b/docs/v2/MetricIngestedIndexedVolumeAttributes.md index c008825e8d..b250575069 100644 --- a/docs/v2/MetricIngestedIndexedVolumeAttributes.md +++ b/docs/v2/MetricIngestedIndexedVolumeAttributes.md @@ -1,6 +1,7 @@ # MetricIngestedIndexedVolumeAttributes Object containing the definition of a metric's ingested and indexed volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricIngestedIndexedVolumeType.md b/docs/v2/MetricIngestedIndexedVolumeType.md index 5484ab68b6..275bfebe59 100644 --- a/docs/v2/MetricIngestedIndexedVolumeType.md +++ b/docs/v2/MetricIngestedIndexedVolumeType.md @@ -1,6 +1,7 @@ # MetricIngestedIndexedVolumeType The metric ingested and indexed volume type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfiguration.md b/docs/v2/MetricTagConfiguration.md index 4fa622b4b2..9bb01dc9c9 100644 --- a/docs/v2/MetricTagConfiguration.md +++ b/docs/v2/MetricTagConfiguration.md @@ -1,6 +1,7 @@ # MetricTagConfiguration Object for a single metric tag configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationAttributes.md b/docs/v2/MetricTagConfigurationAttributes.md index 7a9cc28a0f..ac361fafa4 100644 --- a/docs/v2/MetricTagConfigurationAttributes.md +++ b/docs/v2/MetricTagConfigurationAttributes.md @@ -1,6 +1,7 @@ # MetricTagConfigurationAttributes Object containing the definition of a metric tag configuration attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationCreateAttributes.md b/docs/v2/MetricTagConfigurationCreateAttributes.md index 6d6360ecee..05b5a4aea8 100644 --- a/docs/v2/MetricTagConfigurationCreateAttributes.md +++ b/docs/v2/MetricTagConfigurationCreateAttributes.md @@ -1,6 +1,7 @@ # MetricTagConfigurationCreateAttributes Object containing the definition of a metric tag configuration to be created. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationCreateData.md b/docs/v2/MetricTagConfigurationCreateData.md index 0a3c9656c3..ea9202df0b 100644 --- a/docs/v2/MetricTagConfigurationCreateData.md +++ b/docs/v2/MetricTagConfigurationCreateData.md @@ -1,6 +1,7 @@ # MetricTagConfigurationCreateData Object for a single metric to be configure tags on. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationCreateRequest.md b/docs/v2/MetricTagConfigurationCreateRequest.md index cd64bddcc5..b9749a8610 100644 --- a/docs/v2/MetricTagConfigurationCreateRequest.md +++ b/docs/v2/MetricTagConfigurationCreateRequest.md @@ -1,6 +1,7 @@ # MetricTagConfigurationCreateRequest Request object that includes the metric that you would like to configure tags for. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationMetricTypes.md b/docs/v2/MetricTagConfigurationMetricTypes.md index b836ef120c..2ec987f7a6 100644 --- a/docs/v2/MetricTagConfigurationMetricTypes.md +++ b/docs/v2/MetricTagConfigurationMetricTypes.md @@ -1,6 +1,7 @@ # MetricTagConfigurationMetricTypes The metric's type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationResponse.md b/docs/v2/MetricTagConfigurationResponse.md index 89bbb27b9f..d544244656 100644 --- a/docs/v2/MetricTagConfigurationResponse.md +++ b/docs/v2/MetricTagConfigurationResponse.md @@ -1,6 +1,7 @@ # MetricTagConfigurationResponse Response object which includes a single metric's tag configuration. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationType.md b/docs/v2/MetricTagConfigurationType.md index 562bbd4dbc..33e0d67e72 100644 --- a/docs/v2/MetricTagConfigurationType.md +++ b/docs/v2/MetricTagConfigurationType.md @@ -1,6 +1,7 @@ # MetricTagConfigurationType The metric tag configuration resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationUpdateAttributes.md b/docs/v2/MetricTagConfigurationUpdateAttributes.md index 23f39da17f..48eec6f873 100644 --- a/docs/v2/MetricTagConfigurationUpdateAttributes.md +++ b/docs/v2/MetricTagConfigurationUpdateAttributes.md @@ -1,6 +1,7 @@ # MetricTagConfigurationUpdateAttributes Object containing the definition of a metric tag configuration to be updated. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationUpdateData.md b/docs/v2/MetricTagConfigurationUpdateData.md index 1625d5636d..fd9f736566 100644 --- a/docs/v2/MetricTagConfigurationUpdateData.md +++ b/docs/v2/MetricTagConfigurationUpdateData.md @@ -1,6 +1,7 @@ # MetricTagConfigurationUpdateData Object for a single tag configuration to be edited. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricTagConfigurationUpdateRequest.md b/docs/v2/MetricTagConfigurationUpdateRequest.md index 9a34da555b..10d1558c28 100644 --- a/docs/v2/MetricTagConfigurationUpdateRequest.md +++ b/docs/v2/MetricTagConfigurationUpdateRequest.md @@ -1,6 +1,7 @@ # MetricTagConfigurationUpdateRequest Request object that includes the metric that you would like to edit the tag configuration on. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricType.md b/docs/v2/MetricType.md index f02d73806a..1ca5d8afa5 100644 --- a/docs/v2/MetricType.md +++ b/docs/v2/MetricType.md @@ -1,6 +1,7 @@ # MetricType The metric resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricVolumes.md b/docs/v2/MetricVolumes.md index 5cdb850c05..e2690f9e47 100644 --- a/docs/v2/MetricVolumes.md +++ b/docs/v2/MetricVolumes.md @@ -1,6 +1,7 @@ # MetricVolumes Possible response objects for a metric's volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricVolumesResponse.md b/docs/v2/MetricVolumesResponse.md index dd9a6e226a..2169a885c0 100644 --- a/docs/v2/MetricVolumesResponse.md +++ b/docs/v2/MetricVolumesResponse.md @@ -1,6 +1,7 @@ # MetricVolumesResponse Response object which includes a single metric's volume. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricsAndMetricTagConfigurations.md b/docs/v2/MetricsAndMetricTagConfigurations.md index 95219695bc..fa79f858e3 100644 --- a/docs/v2/MetricsAndMetricTagConfigurations.md +++ b/docs/v2/MetricsAndMetricTagConfigurations.md @@ -1,6 +1,7 @@ # MetricsAndMetricTagConfigurations Object for a metrics and metric tag configurations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricsAndMetricTagConfigurationsResponse.md b/docs/v2/MetricsAndMetricTagConfigurationsResponse.md index 5569afa7bf..f47a2d04b1 100644 --- a/docs/v2/MetricsAndMetricTagConfigurationsResponse.md +++ b/docs/v2/MetricsAndMetricTagConfigurationsResponse.md @@ -1,6 +1,7 @@ # MetricsAndMetricTagConfigurationsResponse Response object that includes metrics and metric tag configurations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/MetricsApi.md b/docs/v2/MetricsApi.md index d74e5b861e..91279cf6ef 100644 --- a/docs/v2/MetricsApi.md +++ b/docs/v2/MetricsApi.md @@ -71,6 +71,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->create_tag_configuration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -91,6 +92,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -148,6 +150,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->delete_tag_configuration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -167,6 +170,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -224,6 +228,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_tag_configuration_by_name: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -243,6 +248,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -304,6 +310,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_tag_configurations: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -326,6 +333,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -383,6 +391,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_tags_by_metric_name: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -402,6 +411,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -460,6 +470,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->list_volumes_by_metric_name: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -479,6 +490,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -547,6 +559,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling MetricsApi->update_tag_configuration: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -567,6 +580,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/Organization.md b/docs/v2/Organization.md index 79fb0d6edc..b75b7ba4e6 100644 --- a/docs/v2/Organization.md +++ b/docs/v2/Organization.md @@ -1,6 +1,7 @@ # Organization Organization object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/OrganizationAttributes.md b/docs/v2/OrganizationAttributes.md index 72f701c9ef..9ae9b035a4 100644 --- a/docs/v2/OrganizationAttributes.md +++ b/docs/v2/OrganizationAttributes.md @@ -1,6 +1,7 @@ # OrganizationAttributes Attributes of the organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/OrganizationsType.md b/docs/v2/OrganizationsType.md index 8442a5ec97..acae5e5cff 100644 --- a/docs/v2/OrganizationsType.md +++ b/docs/v2/OrganizationsType.md @@ -1,6 +1,7 @@ # OrganizationsType Organizations resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Pagination.md b/docs/v2/Pagination.md index 335319a127..ed882c10a2 100644 --- a/docs/v2/Pagination.md +++ b/docs/v2/Pagination.md @@ -1,6 +1,7 @@ # Pagination Pagination object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PartialAPIKey.md b/docs/v2/PartialAPIKey.md index ba950947e3..6d2a30cdd7 100644 --- a/docs/v2/PartialAPIKey.md +++ b/docs/v2/PartialAPIKey.md @@ -1,6 +1,7 @@ # PartialAPIKey Partial Datadog API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PartialAPIKeyAttributes.md b/docs/v2/PartialAPIKeyAttributes.md index f570a2937c..7987e98e98 100644 --- a/docs/v2/PartialAPIKeyAttributes.md +++ b/docs/v2/PartialAPIKeyAttributes.md @@ -1,6 +1,7 @@ # PartialAPIKeyAttributes Attributes of a partial API key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PartialApplicationKey.md b/docs/v2/PartialApplicationKey.md index 224045d0ba..52593f6385 100644 --- a/docs/v2/PartialApplicationKey.md +++ b/docs/v2/PartialApplicationKey.md @@ -1,6 +1,7 @@ # PartialApplicationKey Partial Datadog application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PartialApplicationKeyAttributes.md b/docs/v2/PartialApplicationKeyAttributes.md index 35f895927a..b7a4b8f1e2 100644 --- a/docs/v2/PartialApplicationKeyAttributes.md +++ b/docs/v2/PartialApplicationKeyAttributes.md @@ -1,6 +1,7 @@ # PartialApplicationKeyAttributes Attributes of a partial application key. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Permission.md b/docs/v2/Permission.md index 4255a86b98..a069366599 100644 --- a/docs/v2/Permission.md +++ b/docs/v2/Permission.md @@ -1,6 +1,7 @@ # Permission Permission object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PermissionAttributes.md b/docs/v2/PermissionAttributes.md index 6096f90c51..e0e5b2933e 100644 --- a/docs/v2/PermissionAttributes.md +++ b/docs/v2/PermissionAttributes.md @@ -1,6 +1,7 @@ # PermissionAttributes Attributes of a permission. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PermissionsResponse.md b/docs/v2/PermissionsResponse.md index 0ad91324fe..bc030d1688 100644 --- a/docs/v2/PermissionsResponse.md +++ b/docs/v2/PermissionsResponse.md @@ -1,6 +1,7 @@ # PermissionsResponse Payload with API-returned permissions. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/PermissionsType.md b/docs/v2/PermissionsType.md index 2ff10af467..82c1553bc1 100644 --- a/docs/v2/PermissionsType.md +++ b/docs/v2/PermissionsType.md @@ -1,6 +1,7 @@ # PermissionsType Permissions resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummariesMeta.md b/docs/v2/ProcessSummariesMeta.md index 7024ee44bb..aea7e98d27 100644 --- a/docs/v2/ProcessSummariesMeta.md +++ b/docs/v2/ProcessSummariesMeta.md @@ -1,6 +1,7 @@ # ProcessSummariesMeta Response metadata object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummariesMetaPage.md b/docs/v2/ProcessSummariesMetaPage.md index 6118871e6e..8ce5ba6e3a 100644 --- a/docs/v2/ProcessSummariesMetaPage.md +++ b/docs/v2/ProcessSummariesMetaPage.md @@ -1,6 +1,7 @@ # ProcessSummariesMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummariesResponse.md b/docs/v2/ProcessSummariesResponse.md index 08aa25db56..6840018430 100644 --- a/docs/v2/ProcessSummariesResponse.md +++ b/docs/v2/ProcessSummariesResponse.md @@ -1,6 +1,7 @@ # ProcessSummariesResponse List of process summaries. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummary.md b/docs/v2/ProcessSummary.md index b6a07191e0..27137c6698 100644 --- a/docs/v2/ProcessSummary.md +++ b/docs/v2/ProcessSummary.md @@ -1,6 +1,7 @@ # ProcessSummary Process summary object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummaryAttributes.md b/docs/v2/ProcessSummaryAttributes.md index 2d7082ea74..bd4bc48b17 100644 --- a/docs/v2/ProcessSummaryAttributes.md +++ b/docs/v2/ProcessSummaryAttributes.md @@ -1,6 +1,7 @@ # ProcessSummaryAttributes Attributes for a process summary. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessSummaryType.md b/docs/v2/ProcessSummaryType.md index f690a1130f..099c3d5999 100644 --- a/docs/v2/ProcessSummaryType.md +++ b/docs/v2/ProcessSummaryType.md @@ -1,6 +1,7 @@ # ProcessSummaryType Type of process summary. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ProcessesApi.md b/docs/v2/ProcessesApi.md index 6b8c24ac77..8023bebd2b 100644 --- a/docs/v2/ProcessesApi.md +++ b/docs/v2/ProcessesApi.md @@ -59,6 +59,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling ProcessesApi->list_processes: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -83,6 +84,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/QuerySortOrder.md b/docs/v2/QuerySortOrder.md index 3aa30f45d5..286472ed01 100644 --- a/docs/v2/QuerySortOrder.md +++ b/docs/v2/QuerySortOrder.md @@ -1,6 +1,7 @@ # QuerySortOrder Direction of sort. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToIncidentIntegrationMetadataData.md b/docs/v2/RelationshipToIncidentIntegrationMetadataData.md index 46351cfe00..e7900e49c6 100644 --- a/docs/v2/RelationshipToIncidentIntegrationMetadataData.md +++ b/docs/v2/RelationshipToIncidentIntegrationMetadataData.md @@ -1,6 +1,7 @@ # RelationshipToIncidentIntegrationMetadataData A relationship reference for an integration metadata object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToIncidentIntegrationMetadatas.md b/docs/v2/RelationshipToIncidentIntegrationMetadatas.md index 030de40d1d..9153244f84 100644 --- a/docs/v2/RelationshipToIncidentIntegrationMetadatas.md +++ b/docs/v2/RelationshipToIncidentIntegrationMetadatas.md @@ -1,6 +1,7 @@ # RelationshipToIncidentIntegrationMetadatas A relationship reference for multiple integration metadata objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToIncidentPostmortem.md b/docs/v2/RelationshipToIncidentPostmortem.md index 07e3e45eac..19a2374565 100644 --- a/docs/v2/RelationshipToIncidentPostmortem.md +++ b/docs/v2/RelationshipToIncidentPostmortem.md @@ -1,6 +1,7 @@ # RelationshipToIncidentPostmortem A relationship reference for postmortems. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToIncidentPostmortemData.md b/docs/v2/RelationshipToIncidentPostmortemData.md index 52ec133576..8cb5a5fed7 100644 --- a/docs/v2/RelationshipToIncidentPostmortemData.md +++ b/docs/v2/RelationshipToIncidentPostmortemData.md @@ -1,6 +1,7 @@ # RelationshipToIncidentPostmortemData The postmortem relationship data. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToOrganization.md b/docs/v2/RelationshipToOrganization.md index d94a0ec17a..42b773a510 100644 --- a/docs/v2/RelationshipToOrganization.md +++ b/docs/v2/RelationshipToOrganization.md @@ -1,6 +1,7 @@ # RelationshipToOrganization Relationship to an organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToOrganizationData.md b/docs/v2/RelationshipToOrganizationData.md index 98e6abeae8..d8735ffae2 100644 --- a/docs/v2/RelationshipToOrganizationData.md +++ b/docs/v2/RelationshipToOrganizationData.md @@ -1,6 +1,7 @@ # RelationshipToOrganizationData Relationship to organization object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToOrganizations.md b/docs/v2/RelationshipToOrganizations.md index 55b2321069..8177ab8b33 100644 --- a/docs/v2/RelationshipToOrganizations.md +++ b/docs/v2/RelationshipToOrganizations.md @@ -1,6 +1,7 @@ # RelationshipToOrganizations Relationship to organizations. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToPermission.md b/docs/v2/RelationshipToPermission.md index 1d3c0fbfe9..40bf161891 100644 --- a/docs/v2/RelationshipToPermission.md +++ b/docs/v2/RelationshipToPermission.md @@ -1,6 +1,7 @@ # RelationshipToPermission Relationship to a permissions object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToPermissionData.md b/docs/v2/RelationshipToPermissionData.md index 2cd6279124..8b7149986f 100644 --- a/docs/v2/RelationshipToPermissionData.md +++ b/docs/v2/RelationshipToPermissionData.md @@ -1,6 +1,7 @@ # RelationshipToPermissionData Relationship to permission object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToPermissions.md b/docs/v2/RelationshipToPermissions.md index 993da4a9e7..f8ff4f5df1 100644 --- a/docs/v2/RelationshipToPermissions.md +++ b/docs/v2/RelationshipToPermissions.md @@ -1,6 +1,7 @@ # RelationshipToPermissions Relationship to multiple permissions objects. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToRole.md b/docs/v2/RelationshipToRole.md index efe76e180d..adcaf202a3 100644 --- a/docs/v2/RelationshipToRole.md +++ b/docs/v2/RelationshipToRole.md @@ -1,6 +1,7 @@ # RelationshipToRole Relationship to role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToRoleData.md b/docs/v2/RelationshipToRoleData.md index 88dc4a6516..af1afee2a0 100644 --- a/docs/v2/RelationshipToRoleData.md +++ b/docs/v2/RelationshipToRoleData.md @@ -1,6 +1,7 @@ # RelationshipToRoleData Relationship to role object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToRoles.md b/docs/v2/RelationshipToRoles.md index 45a9332ff2..b7a76868fd 100644 --- a/docs/v2/RelationshipToRoles.md +++ b/docs/v2/RelationshipToRoles.md @@ -1,6 +1,7 @@ # RelationshipToRoles Relationship to roles. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToUser.md b/docs/v2/RelationshipToUser.md index b5d1db35ac..918f1b29e0 100644 --- a/docs/v2/RelationshipToUser.md +++ b/docs/v2/RelationshipToUser.md @@ -1,6 +1,7 @@ # RelationshipToUser Relationship to user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToUserData.md b/docs/v2/RelationshipToUserData.md index b975a0505b..befd857d59 100644 --- a/docs/v2/RelationshipToUserData.md +++ b/docs/v2/RelationshipToUserData.md @@ -1,6 +1,7 @@ # RelationshipToUserData Relationship to user object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RelationshipToUsers.md b/docs/v2/RelationshipToUsers.md index 8316689447..5e678a1272 100644 --- a/docs/v2/RelationshipToUsers.md +++ b/docs/v2/RelationshipToUsers.md @@ -1,6 +1,7 @@ # RelationshipToUsers Relationship to users. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/ResponseMetaAttributes.md b/docs/v2/ResponseMetaAttributes.md index 2a4666a247..6ee5f4e819 100644 --- a/docs/v2/ResponseMetaAttributes.md +++ b/docs/v2/ResponseMetaAttributes.md @@ -1,6 +1,7 @@ # ResponseMetaAttributes Object describing meta attributes of response. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/Role.md b/docs/v2/Role.md index 15d9c7956e..b59f6c0325 100644 --- a/docs/v2/Role.md +++ b/docs/v2/Role.md @@ -1,6 +1,7 @@ # Role Role object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleAttributes.md b/docs/v2/RoleAttributes.md index 1d4e69446e..9f8bb9e687 100644 --- a/docs/v2/RoleAttributes.md +++ b/docs/v2/RoleAttributes.md @@ -1,6 +1,7 @@ # RoleAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleCreateAttributes.md b/docs/v2/RoleCreateAttributes.md index 54b7543328..d3c1ddf5f5 100644 --- a/docs/v2/RoleCreateAttributes.md +++ b/docs/v2/RoleCreateAttributes.md @@ -1,6 +1,7 @@ # RoleCreateAttributes Attributes of the created role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleCreateData.md b/docs/v2/RoleCreateData.md index 67b941882d..aa827b51ed 100644 --- a/docs/v2/RoleCreateData.md +++ b/docs/v2/RoleCreateData.md @@ -1,6 +1,7 @@ # RoleCreateData Data related to the creation of a role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleCreateRequest.md b/docs/v2/RoleCreateRequest.md index f2981a1a84..f630a43171 100644 --- a/docs/v2/RoleCreateRequest.md +++ b/docs/v2/RoleCreateRequest.md @@ -1,6 +1,7 @@ # RoleCreateRequest Create a role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleCreateResponse.md b/docs/v2/RoleCreateResponse.md index 6fa9846334..be5fd9f90b 100644 --- a/docs/v2/RoleCreateResponse.md +++ b/docs/v2/RoleCreateResponse.md @@ -1,6 +1,7 @@ # RoleCreateResponse Response containing information about a created role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleCreateResponseData.md b/docs/v2/RoleCreateResponseData.md index 4b8f41fbdc..b72a706231 100644 --- a/docs/v2/RoleCreateResponseData.md +++ b/docs/v2/RoleCreateResponseData.md @@ -1,6 +1,7 @@ # RoleCreateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleRelationships.md b/docs/v2/RoleRelationships.md index 5a777c8793..de10851445 100644 --- a/docs/v2/RoleRelationships.md +++ b/docs/v2/RoleRelationships.md @@ -1,6 +1,7 @@ # RoleRelationships Relationships of the role object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleResponse.md b/docs/v2/RoleResponse.md index 291d9c9aec..3af83078eb 100644 --- a/docs/v2/RoleResponse.md +++ b/docs/v2/RoleResponse.md @@ -1,6 +1,7 @@ # RoleResponse Response containing information about a single role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleResponseRelationships.md b/docs/v2/RoleResponseRelationships.md index c78d86fe90..b4867a5cba 100644 --- a/docs/v2/RoleResponseRelationships.md +++ b/docs/v2/RoleResponseRelationships.md @@ -1,6 +1,7 @@ # RoleResponseRelationships Relationships of the role object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleUpdateAttributes.md b/docs/v2/RoleUpdateAttributes.md index 7395c160fe..05bace4bbe 100644 --- a/docs/v2/RoleUpdateAttributes.md +++ b/docs/v2/RoleUpdateAttributes.md @@ -1,6 +1,7 @@ # RoleUpdateAttributes Attributes of the role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleUpdateData.md b/docs/v2/RoleUpdateData.md index b9be1b611b..848c9f9772 100644 --- a/docs/v2/RoleUpdateData.md +++ b/docs/v2/RoleUpdateData.md @@ -1,6 +1,7 @@ # RoleUpdateData Data related to the update of a role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleUpdateRequest.md b/docs/v2/RoleUpdateRequest.md index 7634d35eb5..9856d42508 100644 --- a/docs/v2/RoleUpdateRequest.md +++ b/docs/v2/RoleUpdateRequest.md @@ -1,6 +1,7 @@ # RoleUpdateRequest Update a role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleUpdateResponse.md b/docs/v2/RoleUpdateResponse.md index d9101ca49e..63a2797a1f 100644 --- a/docs/v2/RoleUpdateResponse.md +++ b/docs/v2/RoleUpdateResponse.md @@ -1,6 +1,7 @@ # RoleUpdateResponse Response containing information about an updated role. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RoleUpdateResponseData.md b/docs/v2/RoleUpdateResponseData.md index 1a93afc45a..52e0912c94 100644 --- a/docs/v2/RoleUpdateResponseData.md +++ b/docs/v2/RoleUpdateResponseData.md @@ -1,6 +1,7 @@ # RoleUpdateResponseData Role object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RolesApi.md b/docs/v2/RolesApi.md index c7e0683c9d..e109073dd3 100644 --- a/docs/v2/RolesApi.md +++ b/docs/v2/RolesApi.md @@ -70,6 +70,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->add_permission_to_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -90,6 +91,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -152,6 +154,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->add_user_to_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -172,6 +175,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -250,6 +254,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->create_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -269,6 +274,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -323,6 +329,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->delete_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -342,6 +349,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -397,6 +405,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->get_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -416,6 +425,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -470,6 +480,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->list_permissions: %s\n" % e) ``` + ### Parameters This endpoint does not need any parameter. @@ -486,6 +497,7 @@ This endpoint does not need any parameter. - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -541,6 +553,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->list_role_permissions: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -560,6 +573,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -628,6 +642,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->list_role_users: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -651,6 +666,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -710,6 +726,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->list_roles: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -732,6 +749,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -792,6 +810,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->remove_permission_from_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -812,6 +831,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -874,6 +894,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->remove_user_from_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -894,6 +915,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -961,6 +983,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling RolesApi->update_role: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -981,6 +1004,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/RolesResponse.md b/docs/v2/RolesResponse.md index 2c31ca15b4..085a94b305 100644 --- a/docs/v2/RolesResponse.md +++ b/docs/v2/RolesResponse.md @@ -1,6 +1,7 @@ # RolesResponse Response containing information about multiple roles. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RolesSort.md b/docs/v2/RolesSort.md index 9c716da406..0cbc0cc780 100644 --- a/docs/v2/RolesSort.md +++ b/docs/v2/RolesSort.md @@ -1,6 +1,7 @@ # RolesSort Sorting options for roles. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/RolesType.md b/docs/v2/RolesType.md index cc7e30ed1d..b7daccfbb9 100644 --- a/docs/v2/RolesType.md +++ b/docs/v2/RolesType.md @@ -1,6 +1,7 @@ # RolesType Roles type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringApi.md b/docs/v2/SecurityMonitoringApi.md index 94a49b0f2b..72fef54ba0 100644 --- a/docs/v2/SecurityMonitoringApi.md +++ b/docs/v2/SecurityMonitoringApi.md @@ -82,6 +82,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->create_security_monitoring_rule: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -101,6 +102,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -155,6 +157,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->delete_security_monitoring_rule: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -174,6 +177,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -229,6 +233,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->get_security_monitoring_rule: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -248,6 +253,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -304,6 +310,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->list_security_monitoring_rules: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -324,6 +331,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -385,6 +393,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->list_security_monitoring_signals: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -409,6 +418,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -477,6 +487,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->search_security_monitoring_signals: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -496,6 +507,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -599,6 +611,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling SecurityMonitoringApi->update_security_monitoring_rule: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -619,6 +632,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/SecurityMonitoringFilter.md b/docs/v2/SecurityMonitoringFilter.md index 75c4ca4289..e21a609c14 100644 --- a/docs/v2/SecurityMonitoringFilter.md +++ b/docs/v2/SecurityMonitoringFilter.md @@ -1,6 +1,7 @@ # SecurityMonitoringFilter The rule's suppression filter. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringFilterAction.md b/docs/v2/SecurityMonitoringFilterAction.md index 9b56440e44..d6f49f3874 100644 --- a/docs/v2/SecurityMonitoringFilterAction.md +++ b/docs/v2/SecurityMonitoringFilterAction.md @@ -1,6 +1,7 @@ # SecurityMonitoringFilterAction The type of filtering action. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringListRulesResponse.md b/docs/v2/SecurityMonitoringListRulesResponse.md index 5d356776ec..aa15d6e8bf 100644 --- a/docs/v2/SecurityMonitoringListRulesResponse.md +++ b/docs/v2/SecurityMonitoringListRulesResponse.md @@ -1,6 +1,7 @@ # SecurityMonitoringListRulesResponse List of rules. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleCase.md b/docs/v2/SecurityMonitoringRuleCase.md index 1b443c33ff..71097e606d 100644 --- a/docs/v2/SecurityMonitoringRuleCase.md +++ b/docs/v2/SecurityMonitoringRuleCase.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleCase Case when signal is generated. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleCaseCreate.md b/docs/v2/SecurityMonitoringRuleCaseCreate.md index 4ef2282775..3b5ada2688 100644 --- a/docs/v2/SecurityMonitoringRuleCaseCreate.md +++ b/docs/v2/SecurityMonitoringRuleCaseCreate.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleCaseCreate Case when signal is generated. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleCreatePayload.md b/docs/v2/SecurityMonitoringRuleCreatePayload.md index 47f1cb7b87..352ae6904c 100644 --- a/docs/v2/SecurityMonitoringRuleCreatePayload.md +++ b/docs/v2/SecurityMonitoringRuleCreatePayload.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleCreatePayload Create a new rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleDetectionMethod.md b/docs/v2/SecurityMonitoringRuleDetectionMethod.md index 06232bbf01..68a0b551b2 100644 --- a/docs/v2/SecurityMonitoringRuleDetectionMethod.md +++ b/docs/v2/SecurityMonitoringRuleDetectionMethod.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleDetectionMethod The detection method. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleEvaluationWindow.md b/docs/v2/SecurityMonitoringRuleEvaluationWindow.md index bac1cc1927..506c0fea17 100644 --- a/docs/v2/SecurityMonitoringRuleEvaluationWindow.md +++ b/docs/v2/SecurityMonitoringRuleEvaluationWindow.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleEvaluationWindow A time window is specified to match when at least one of the cases matches true. This is a sliding window and evaluates in real time. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleKeepAlive.md b/docs/v2/SecurityMonitoringRuleKeepAlive.md index 7a4fa695bb..775f527ccc 100644 --- a/docs/v2/SecurityMonitoringRuleKeepAlive.md +++ b/docs/v2/SecurityMonitoringRuleKeepAlive.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleKeepAlive Once a signal is generated, the signal will remain “open” if a case is matched at least once within this keep alive window. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleMaxSignalDuration.md b/docs/v2/SecurityMonitoringRuleMaxSignalDuration.md index 9c1f905341..91a2150925 100644 --- a/docs/v2/SecurityMonitoringRuleMaxSignalDuration.md +++ b/docs/v2/SecurityMonitoringRuleMaxSignalDuration.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleMaxSignalDuration A signal will “close” regardless of the query being matched once the time exceeds the maximum duration. This time is calculated from the first seen timestamp. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleNewValueOptions.md b/docs/v2/SecurityMonitoringRuleNewValueOptions.md index 35f3d4b6fa..50fe0836da 100644 --- a/docs/v2/SecurityMonitoringRuleNewValueOptions.md +++ b/docs/v2/SecurityMonitoringRuleNewValueOptions.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleNewValueOptions Options on new value rules. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleNewValueOptionsForgetAfter.md b/docs/v2/SecurityMonitoringRuleNewValueOptionsForgetAfter.md index da4128db7d..177f0c0095 100644 --- a/docs/v2/SecurityMonitoringRuleNewValueOptionsForgetAfter.md +++ b/docs/v2/SecurityMonitoringRuleNewValueOptionsForgetAfter.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleNewValueOptionsForgetAfter The duration in days after which a learned value is forgotten. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleNewValueOptionsLearningDuration.md b/docs/v2/SecurityMonitoringRuleNewValueOptionsLearningDuration.md index 8aaa0f44b8..a04cead6c8 100644 --- a/docs/v2/SecurityMonitoringRuleNewValueOptionsLearningDuration.md +++ b/docs/v2/SecurityMonitoringRuleNewValueOptionsLearningDuration.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleNewValueOptionsLearningDuration The duration in days during which values are learned, and after which signals will be generated for values that weren't learned. If set to 0, a signal will be generated for all new values after the first value is learned. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleOptions.md b/docs/v2/SecurityMonitoringRuleOptions.md index f3ed433c0b..19882aec7d 100644 --- a/docs/v2/SecurityMonitoringRuleOptions.md +++ b/docs/v2/SecurityMonitoringRuleOptions.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleOptions Options on rules. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleQuery.md b/docs/v2/SecurityMonitoringRuleQuery.md index 3c9cd65b71..49b6e8810d 100644 --- a/docs/v2/SecurityMonitoringRuleQuery.md +++ b/docs/v2/SecurityMonitoringRuleQuery.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleQuery Query for matching rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleQueryAggregation.md b/docs/v2/SecurityMonitoringRuleQueryAggregation.md index 91b1d29e02..5a9f3562cb 100644 --- a/docs/v2/SecurityMonitoringRuleQueryAggregation.md +++ b/docs/v2/SecurityMonitoringRuleQueryAggregation.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleQueryAggregation The aggregation type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleQueryCreate.md b/docs/v2/SecurityMonitoringRuleQueryCreate.md index a2d0520864..1e3c808b7f 100644 --- a/docs/v2/SecurityMonitoringRuleQueryCreate.md +++ b/docs/v2/SecurityMonitoringRuleQueryCreate.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleQueryCreate Query for matching rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleResponse.md b/docs/v2/SecurityMonitoringRuleResponse.md index cfd4a3e121..4efa111c5c 100644 --- a/docs/v2/SecurityMonitoringRuleResponse.md +++ b/docs/v2/SecurityMonitoringRuleResponse.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleResponse Detection rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleSeverity.md b/docs/v2/SecurityMonitoringRuleSeverity.md index bf5552c357..3cbc701b78 100644 --- a/docs/v2/SecurityMonitoringRuleSeverity.md +++ b/docs/v2/SecurityMonitoringRuleSeverity.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleSeverity Severity of the Security Signal. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringRuleUpdatePayload.md b/docs/v2/SecurityMonitoringRuleUpdatePayload.md index ac7037b8fe..7ae3d640c4 100644 --- a/docs/v2/SecurityMonitoringRuleUpdatePayload.md +++ b/docs/v2/SecurityMonitoringRuleUpdatePayload.md @@ -1,6 +1,7 @@ # SecurityMonitoringRuleUpdatePayload Update an existing rule. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignal.md b/docs/v2/SecurityMonitoringSignal.md index 066f8bacd1..498cc3e136 100644 --- a/docs/v2/SecurityMonitoringSignal.md +++ b/docs/v2/SecurityMonitoringSignal.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignal Object description of a security signal. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalAttributes.md b/docs/v2/SecurityMonitoringSignalAttributes.md index 7badf70981..71d83cb359 100644 --- a/docs/v2/SecurityMonitoringSignalAttributes.md +++ b/docs/v2/SecurityMonitoringSignalAttributes.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalAttributes The object containing all signal attributes and their associated values. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalListRequest.md b/docs/v2/SecurityMonitoringSignalListRequest.md index 2dde80e068..919c2e5e39 100644 --- a/docs/v2/SecurityMonitoringSignalListRequest.md +++ b/docs/v2/SecurityMonitoringSignalListRequest.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalListRequest The request for a security signal list. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalListRequestFilter.md b/docs/v2/SecurityMonitoringSignalListRequestFilter.md index 6ea6f7c7f3..bcf1973b7b 100644 --- a/docs/v2/SecurityMonitoringSignalListRequestFilter.md +++ b/docs/v2/SecurityMonitoringSignalListRequestFilter.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalListRequestFilter Search filters for listing security signals. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalListRequestPage.md b/docs/v2/SecurityMonitoringSignalListRequestPage.md index cbb2c2af8f..712e8635a8 100644 --- a/docs/v2/SecurityMonitoringSignalListRequestPage.md +++ b/docs/v2/SecurityMonitoringSignalListRequestPage.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalListRequestPage The paging attributes for listing security signals. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalType.md b/docs/v2/SecurityMonitoringSignalType.md index 00c647cf31..db4de333ab 100644 --- a/docs/v2/SecurityMonitoringSignalType.md +++ b/docs/v2/SecurityMonitoringSignalType.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalType The type of event. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalsListResponse.md b/docs/v2/SecurityMonitoringSignalsListResponse.md index 964b4416e8..3a8210d756 100644 --- a/docs/v2/SecurityMonitoringSignalsListResponse.md +++ b/docs/v2/SecurityMonitoringSignalsListResponse.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalsListResponse The response object with all security signals matching the request and pagination information. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalsListResponseLinks.md b/docs/v2/SecurityMonitoringSignalsListResponseLinks.md index be6d1cd7e2..71d3a7122b 100644 --- a/docs/v2/SecurityMonitoringSignalsListResponseLinks.md +++ b/docs/v2/SecurityMonitoringSignalsListResponseLinks.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalsListResponseLinks Links attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalsListResponseMeta.md b/docs/v2/SecurityMonitoringSignalsListResponseMeta.md index d7c5f2546a..b52b957e84 100644 --- a/docs/v2/SecurityMonitoringSignalsListResponseMeta.md +++ b/docs/v2/SecurityMonitoringSignalsListResponseMeta.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalsListResponseMeta Meta attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md b/docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md index ea4490489f..8239da63ec 100644 --- a/docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md +++ b/docs/v2/SecurityMonitoringSignalsListResponseMetaPage.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalsListResponseMetaPage Paging attributes. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/SecurityMonitoringSignalsSort.md b/docs/v2/SecurityMonitoringSignalsSort.md index 37686017a3..aa90d39b08 100644 --- a/docs/v2/SecurityMonitoringSignalsSort.md +++ b/docs/v2/SecurityMonitoringSignalsSort.md @@ -1,6 +1,7 @@ # SecurityMonitoringSignalsSort The sort parameters used for querying security signals. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/User.md b/docs/v2/User.md index 640ab28af8..47ca52e8b0 100644 --- a/docs/v2/User.md +++ b/docs/v2/User.md @@ -1,6 +1,7 @@ # User User object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserAttributes.md b/docs/v2/UserAttributes.md index 060c8915cd..386633257e 100644 --- a/docs/v2/UserAttributes.md +++ b/docs/v2/UserAttributes.md @@ -1,6 +1,7 @@ # UserAttributes Attributes of user object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserCreateAttributes.md b/docs/v2/UserCreateAttributes.md index 8da88321da..173800c3f7 100644 --- a/docs/v2/UserCreateAttributes.md +++ b/docs/v2/UserCreateAttributes.md @@ -1,6 +1,7 @@ # UserCreateAttributes Attributes of the created user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserCreateData.md b/docs/v2/UserCreateData.md index 9e191557ec..f696ace762 100644 --- a/docs/v2/UserCreateData.md +++ b/docs/v2/UserCreateData.md @@ -1,6 +1,7 @@ # UserCreateData Object to create a user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserCreateRequest.md b/docs/v2/UserCreateRequest.md index 474df7baf1..a21eafe076 100644 --- a/docs/v2/UserCreateRequest.md +++ b/docs/v2/UserCreateRequest.md @@ -1,6 +1,7 @@ # UserCreateRequest Create a user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationData.md b/docs/v2/UserInvitationData.md index 27d8ee60fe..8ee9dfe75a 100644 --- a/docs/v2/UserInvitationData.md +++ b/docs/v2/UserInvitationData.md @@ -1,6 +1,7 @@ # UserInvitationData Object to create a user invitation. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationDataAttributes.md b/docs/v2/UserInvitationDataAttributes.md index 957b92729c..b5bcb1b6c9 100644 --- a/docs/v2/UserInvitationDataAttributes.md +++ b/docs/v2/UserInvitationDataAttributes.md @@ -1,6 +1,7 @@ # UserInvitationDataAttributes Attributes of a user invitation. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationRelationships.md b/docs/v2/UserInvitationRelationships.md index 44bcb79c31..0215375692 100644 --- a/docs/v2/UserInvitationRelationships.md +++ b/docs/v2/UserInvitationRelationships.md @@ -1,6 +1,7 @@ # UserInvitationRelationships Relationships data for user invitation. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationResponse.md b/docs/v2/UserInvitationResponse.md index 2455adab05..3f18ce0dc5 100644 --- a/docs/v2/UserInvitationResponse.md +++ b/docs/v2/UserInvitationResponse.md @@ -1,6 +1,7 @@ # UserInvitationResponse User invitation as returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationResponseData.md b/docs/v2/UserInvitationResponseData.md index ed6f76691f..93453a4a01 100644 --- a/docs/v2/UserInvitationResponseData.md +++ b/docs/v2/UserInvitationResponseData.md @@ -1,6 +1,7 @@ # UserInvitationResponseData Object of a user invitation returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationsRequest.md b/docs/v2/UserInvitationsRequest.md index b664845bd4..27901da859 100644 --- a/docs/v2/UserInvitationsRequest.md +++ b/docs/v2/UserInvitationsRequest.md @@ -1,6 +1,7 @@ # UserInvitationsRequest Object to invite users to join the organization. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationsResponse.md b/docs/v2/UserInvitationsResponse.md index f087a9e5ce..90d5d47d2f 100644 --- a/docs/v2/UserInvitationsResponse.md +++ b/docs/v2/UserInvitationsResponse.md @@ -1,6 +1,7 @@ # UserInvitationsResponse User invitations as returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserInvitationsType.md b/docs/v2/UserInvitationsType.md index 3a78c17b07..764b04f63f 100644 --- a/docs/v2/UserInvitationsType.md +++ b/docs/v2/UserInvitationsType.md @@ -1,6 +1,7 @@ # UserInvitationsType User invitations type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserRelationships.md b/docs/v2/UserRelationships.md index 664d047eb1..963b93ff95 100644 --- a/docs/v2/UserRelationships.md +++ b/docs/v2/UserRelationships.md @@ -1,6 +1,7 @@ # UserRelationships Relationships of the user object. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserResponse.md b/docs/v2/UserResponse.md index ff5c74b060..19ea6c75e0 100644 --- a/docs/v2/UserResponse.md +++ b/docs/v2/UserResponse.md @@ -1,6 +1,7 @@ # UserResponse Response containing information about a single user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserResponseIncludedItem.md b/docs/v2/UserResponseIncludedItem.md index ee9f96f7b8..c41b3a4dc8 100644 --- a/docs/v2/UserResponseIncludedItem.md +++ b/docs/v2/UserResponseIncludedItem.md @@ -1,6 +1,7 @@ # UserResponseIncludedItem An object related to a user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserResponseRelationships.md b/docs/v2/UserResponseRelationships.md index 0f4858dc82..e35047f2b6 100644 --- a/docs/v2/UserResponseRelationships.md +++ b/docs/v2/UserResponseRelationships.md @@ -1,6 +1,7 @@ # UserResponseRelationships Relationships of the user object returned by the API. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserUpdateAttributes.md b/docs/v2/UserUpdateAttributes.md index cff63d132f..6d40abb061 100644 --- a/docs/v2/UserUpdateAttributes.md +++ b/docs/v2/UserUpdateAttributes.md @@ -1,6 +1,7 @@ # UserUpdateAttributes Attributes of the edited user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserUpdateData.md b/docs/v2/UserUpdateData.md index e92cd06545..a1d5b8f393 100644 --- a/docs/v2/UserUpdateData.md +++ b/docs/v2/UserUpdateData.md @@ -1,6 +1,7 @@ # UserUpdateData Object to update a user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UserUpdateRequest.md b/docs/v2/UserUpdateRequest.md index c1836f22f1..d108c8cb0e 100644 --- a/docs/v2/UserUpdateRequest.md +++ b/docs/v2/UserUpdateRequest.md @@ -1,6 +1,7 @@ # UserUpdateRequest Update a user. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UsersApi.md b/docs/v2/UsersApi.md index 504d204f5b..a82362c3cc 100644 --- a/docs/v2/UsersApi.md +++ b/docs/v2/UsersApi.md @@ -80,6 +80,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->create_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -99,6 +100,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -153,6 +155,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->disable_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -172,6 +175,7 @@ void (empty response body) - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -227,6 +231,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->get_invitation: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -246,6 +251,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -301,6 +307,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->get_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -320,6 +327,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -375,6 +383,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->list_user_organizations: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -394,6 +403,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -449,6 +459,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->list_user_permissions: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -468,6 +479,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -529,6 +541,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->list_users: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -553,6 +566,7 @@ Name | Type | Description | Notes - **Content-Type**: Not defined - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -610,6 +624,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->send_invitations: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -629,6 +644,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| @@ -695,6 +711,7 @@ with ApiClient(configuration) as api_client: print("Exception when calling UsersApi->update_user: %s\n" % e) ``` + ### Parameters Name | Type | Description | Notes @@ -715,6 +732,7 @@ Name | Type | Description | Notes - **Content-Type**: application/json - **Accept**: application/json + ### HTTP response details | Status code | Description | Response headers | |-------------|-------------|------------------| diff --git a/docs/v2/UsersResponse.md b/docs/v2/UsersResponse.md index f32a829525..28dbd53fd9 100644 --- a/docs/v2/UsersResponse.md +++ b/docs/v2/UsersResponse.md @@ -1,6 +1,7 @@ # UsersResponse Response containing information about multiple users. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- diff --git a/docs/v2/UsersType.md b/docs/v2/UsersType.md index c220525966..c0e40e1cf9 100644 --- a/docs/v2/UsersType.md +++ b/docs/v2/UsersType.md @@ -1,6 +1,7 @@ # UsersType Users resource type. + ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | -------------