From e9ac07c85acccd1685a49ea79bd93f3756f1b72c Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Mon, 11 Jan 2021 16:37:38 -0500 Subject: [PATCH 01/19] Change signature of query parameters to allow None --- .../api/tests/defaults_tests_defaults_post.py | 52 +++---- ...tional_value_tests_optional_query_param.py | 6 +- ...el_with_primitive_additional_properties.py | 4 +- .../api/tests/defaults_tests_defaults_post.py | 132 +++++++++--------- ...tional_value_tests_optional_query_param.py | 14 +- ...el_with_primitive_additional_properties.py | 4 +- .../parser/properties/__init__.py | 33 ++--- .../parser/properties/enum_property.py | 13 +- .../parser/properties/model_property.py | 12 +- .../parser/properties/property.py | 34 +++-- .../templates/endpoint_macros.pyi | 6 +- .../property_templates/date_property.pyi | 4 +- .../property_templates/datetime_property.pyi | 4 +- .../property_templates/enum_property.pyi | 4 +- .../property_templates/file_property.pyi | 4 +- .../property_templates/list_property.pyi | 4 +- .../property_templates/model_property.pyi | 4 +- .../property_templates/union_property.pyi | 4 +- 18 files changed, 169 insertions(+), 169 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 574d5018b..fde6cb49b 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -40,28 +40,28 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal def httpx_request( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Response[Union[None, HTTPValidationError]]: json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset): + if not isinstance(datetime_prop, Unset) and datetime_prop is not None: json_datetime_prop = datetime_prop.isoformat() json_date_prop: Union[Unset, str] = UNSET - if not isinstance(date_prop, Unset): + if not isinstance(date_prop, Unset) and date_prop is not None: json_date_prop = date_prop.isoformat() json_list_prop: Union[Unset, List[Any]] = UNSET - if not isinstance(list_prop, Unset): + if not isinstance(list_prop, Unset) and list_prop is not None: json_list_prop = [] for list_prop_item_data in list_prop: list_prop_item = list_prop_item_data.value @@ -69,13 +69,13 @@ def httpx_request( json_list_prop.append(list_prop_item) json_union_prop: Union[Unset, float, str] - if isinstance(union_prop, Unset): + if isinstance(union_prop, Unset) or union_prop is None: json_union_prop = UNSET else: json_union_prop = union_prop json_union_prop_with_ref: Union[Unset, float, AnEnum] - if isinstance(union_prop_with_ref, Unset): + if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: json_union_prop_with_ref = UNSET elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET @@ -86,29 +86,29 @@ def httpx_request( json_union_prop_with_ref = union_prop_with_ref json_enum_prop: Union[Unset, AnEnum] = UNSET - if not isinstance(enum_prop, Unset): + if not isinstance(enum_prop, Unset) and enum_prop is not None: json_enum_prop = enum_prop params: Dict[str, Any] = {} - if string_prop is not UNSET: + if string_prop is not UNSET and string_prop is not None: params["string_prop"] = string_prop - if datetime_prop is not UNSET: + if datetime_prop is not UNSET and datetime_prop is not None: params["datetime_prop"] = json_datetime_prop - if date_prop is not UNSET: + if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop - if float_prop is not UNSET: + if float_prop is not UNSET and float_prop is not None: params["float_prop"] = float_prop - if int_prop is not UNSET: + if int_prop is not UNSET and int_prop is not None: params["int_prop"] = int_prop - if boolean_prop is not UNSET: + if boolean_prop is not UNSET and boolean_prop is not None: params["boolean_prop"] = boolean_prop - if list_prop is not UNSET: + if list_prop is not UNSET and list_prop is not None: params["list_prop"] = json_list_prop - if union_prop is not UNSET: + if union_prop is not UNSET and union_prop is not None: params["union_prop"] = json_union_prop - if union_prop_with_ref is not UNSET: + if union_prop_with_ref is not UNSET and union_prop_with_ref is not None: params["union_prop_with_ref"] = json_union_prop_with_ref - if enum_prop is not UNSET: + if enum_prop is not UNSET and enum_prop is not None: params["enum_prop"] = json_enum_prop response = client.request( diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py index bff43cc10..7b821fca6 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py @@ -36,15 +36,15 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal def httpx_request( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Response[Union[None, HTTPValidationError]]: json_query_param: Union[Unset, List[Any]] = UNSET - if not isinstance(query_param, Unset): + if not isinstance(query_param, Unset) and query_param is not None: json_query_param = query_param params: Dict[str, Any] = {} - if query_param is not UNSET: + if query_param is not UNSET and query_param is not None: params["query_param"] = json_query_param response = client.request( diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py index a45edaab8..0066962ed 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_primitive_additional_properties.py @@ -14,7 +14,7 @@ class ModelWithPrimitiveAdditionalProperties: """ """ - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -33,7 +33,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET _a_date_holder = d.pop("a_date_holder", UNSET) if _a_date_holder is not None and not isinstance(_a_date_holder, Unset): a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index 9242cddaa..77ee6cce1 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -13,31 +13,31 @@ def _get_kwargs( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Dict[str, Any]: url = "{}/tests/defaults".format(client.base_url) headers: Dict[str, Any] = client.get_headers() json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset): + if not isinstance(datetime_prop, Unset) and datetime_prop is not None: json_datetime_prop = datetime_prop.isoformat() json_date_prop: Union[Unset, str] = UNSET - if not isinstance(date_prop, Unset): + if not isinstance(date_prop, Unset) and date_prop is not None: json_date_prop = date_prop.isoformat() json_list_prop: Union[Unset, List[Any]] = UNSET - if not isinstance(list_prop, Unset): + if not isinstance(list_prop, Unset) and list_prop is not None: json_list_prop = [] for list_prop_item_data in list_prop: list_prop_item = list_prop_item_data.value @@ -45,13 +45,13 @@ def _get_kwargs( json_list_prop.append(list_prop_item) json_union_prop: Union[Unset, float, str] - if isinstance(union_prop, Unset): + if isinstance(union_prop, Unset) or union_prop is None: json_union_prop = UNSET else: json_union_prop = union_prop json_union_prop_with_ref: Union[Unset, float, AnEnum] - if isinstance(union_prop_with_ref, Unset): + if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: json_union_prop_with_ref = UNSET elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET @@ -62,29 +62,29 @@ def _get_kwargs( json_union_prop_with_ref = union_prop_with_ref json_enum_prop: Union[Unset, AnEnum] = UNSET - if not isinstance(enum_prop, Unset): + if not isinstance(enum_prop, Unset) and enum_prop is not None: json_enum_prop = enum_prop params: Dict[str, Any] = {} - if string_prop is not UNSET: + if string_prop is not UNSET and string_prop is not None: params["string_prop"] = string_prop - if datetime_prop is not UNSET: + if datetime_prop is not UNSET and datetime_prop is not None: params["datetime_prop"] = json_datetime_prop - if date_prop is not UNSET: + if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop - if float_prop is not UNSET: + if float_prop is not UNSET and float_prop is not None: params["float_prop"] = float_prop - if int_prop is not UNSET: + if int_prop is not UNSET and int_prop is not None: params["int_prop"] = int_prop - if boolean_prop is not UNSET: + if boolean_prop is not UNSET and boolean_prop is not None: params["boolean_prop"] = boolean_prop - if list_prop is not UNSET: + if list_prop is not UNSET and list_prop is not None: params["list_prop"] = json_list_prop - if union_prop is not UNSET: + if union_prop is not UNSET and union_prop is not None: params["union_prop"] = json_union_prop - if union_prop_with_ref is not UNSET: + if union_prop_with_ref is not UNSET and union_prop_with_ref is not None: params["union_prop_with_ref"] = json_union_prop_with_ref - if enum_prop is not UNSET: + if enum_prop is not UNSET and enum_prop is not None: params["enum_prop"] = json_enum_prop return { @@ -120,16 +120,16 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal def sync_detailed( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -155,16 +155,16 @@ def sync_detailed( def sync( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Optional[Union[None, HTTPValidationError]]: """ """ @@ -186,16 +186,16 @@ def sync( async def asyncio_detailed( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -220,16 +220,16 @@ async def asyncio_detailed( async def asyncio( *, client: Client, - string_prop: Union[Unset, str] = "the default string", - datetime_prop: Union[Unset, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, float] = 3.14, - int_prop: Union[Unset, int] = 7, - boolean_prop: Union[Unset, bool] = False, - list_prop: Union[Unset, List[AnEnum]] = UNSET, - union_prop: Union[Unset, float, str] = "not a float", - union_prop_with_ref: Union[Unset, float, AnEnum] = 0.6, - enum_prop: Union[Unset, AnEnum] = UNSET, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = None, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = None, ) -> Optional[Union[None, HTTPValidationError]]: """ """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py index 751f48e03..8058acb43 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py @@ -10,18 +10,18 @@ def _get_kwargs( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Dict[str, Any]: url = "{}/tests/optional_query_param/".format(client.base_url) headers: Dict[str, Any] = client.get_headers() json_query_param: Union[Unset, List[Any]] = UNSET - if not isinstance(query_param, Unset): + if not isinstance(query_param, Unset) and query_param is not None: json_query_param = query_param params: Dict[str, Any] = {} - if query_param is not UNSET: + if query_param is not UNSET and query_param is not None: params["query_param"] = json_query_param return { @@ -57,7 +57,7 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal def sync_detailed( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -74,7 +74,7 @@ def sync_detailed( def sync( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Optional[Union[None, HTTPValidationError]]: """ Test optional query parameters """ @@ -87,7 +87,7 @@ def sync( async def asyncio_detailed( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Response[Union[None, HTTPValidationError]]: kwargs = _get_kwargs( client=client, @@ -103,7 +103,7 @@ async def asyncio_detailed( async def asyncio( *, client: Client, - query_param: Union[Unset, List[str]] = UNSET, + query_param: Union[Unset, None, List[str]] = None, ) -> Optional[Union[None, HTTPValidationError]]: """ Test optional query parameters """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py index a45edaab8..0066962ed 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py @@ -14,7 +14,7 @@ class ModelWithPrimitiveAdditionalProperties: """ """ - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) def to_dict(self) -> Dict[str, Any]: @@ -33,7 +33,7 @@ def to_dict(self) -> Dict[str, Any]: @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: d = src_dict.copy() - a_date_holder: Union[ModelWithPrimitiveAdditionalPropertiesADateHolder, Unset] = UNSET + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET _a_date_holder = d.pop("a_date_holder", UNSET) if _a_date_holder is not None and not isinstance(_a_date_holder, Unset): a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 427276692..30b74104f 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -124,16 +124,8 @@ class ListProperty(Property, Generic[InnerProp]): inner_property: InnerProp template: ClassVar[str] = "list_property.pyi" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - type_string = f"List[{self.inner_property.get_type_string()}]" - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[Unset, {type_string}]" - return type_string + def get_base_type_string(self) -> str: + return f"List[{self.inner_property.get_type_string()}]" def get_instance_type_string(self) -> str: """Get a string representation of runtime type that should be used for `isinstance` checks""" @@ -167,17 +159,26 @@ def __attrs_post_init__(self) -> None: self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) ) - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ + def _get_inner_prop_string(self) -> List[str]: inner_types = [p.get_type_string(no_optional=True) for p in self.inner_properties] - inner_prop_string = ", ".join(inner_types) - type_string = f"Union[{inner_prop_string}]" + return ", ".join(inner_types) + + def get_base_type_string(self) -> str: + return f"Union[{self._get_inner_prop_string()}]" + + def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: + """ Get a string representation of type that should be used when declaring this property """ + type_string = self.get_base_type_string() if no_optional: return type_string - if not self.required: - type_string = f"Union[Unset, {inner_prop_string}]" if self.nullable: type_string = f"Optional[{type_string}]" + if not self.required: + if query_parameter: + # For query parameters, None has the same meaning as Unset + type_string = f"Union[Unset, None, {self._get_inner_prop_string()}]" + else: + type_string = f"Union[Unset, {self._get_inner_prop_string()}]" return type_string def get_imports(self, *, prefix: str) -> Set[str]: diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py index 1217f23ee..08fce294d 100644 --- a/openapi_python_client/parser/properties/enum_property.py +++ b/openapi_python_client/parser/properties/enum_property.py @@ -22,17 +22,8 @@ class EnumProperty(Property): template: ClassVar[str] = "enum_property.pyi" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - - type_string = self.reference.class_name - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[Unset, {type_string}]" - return type_string + def get_base_type_string(self) -> str: + return self.reference.class_name def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index 084017a41..03f217d52 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -20,16 +20,8 @@ class ModelProperty(Property): template: ClassVar[str] = "model_property.pyi" - def get_type_string(self, no_optional: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ - type_string = self.reference.class_name - if no_optional: - return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - type_string = f"Union[{type_string}, Unset]" - return type_string + def get_base_type_string(self) -> str: + return self.reference.class_name def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 0b7047551..a75fc481f 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -31,21 +31,29 @@ class Property: def __attrs_post_init__(self) -> None: object.__setattr__(self, "python_name", utils.to_valid_python_identifier(utils.snake_case(self.name))) + + def get_base_type_string(self) -> str: + return self._type_string - def get_type_string(self, no_optional: bool = False) -> str: + def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property Args: no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks) + query_parameter: True if the property's type is being used for a query parameter """ - type_string = self._type_string + type_string = self.get_base_type_string() if no_optional: - return self._type_string + return type_string if self.nullable: type_string = f"Optional[{type_string}]" if not self.required: - type_string = f"Union[Unset, {type_string}]" + if query_parameter: + # For query parameters, None has the same meaning as Unset + type_string = f"Union[Unset, None, {type_string}]" + else: + type_string = f"Union[Unset, {type_string}]" return type_string def get_instance_type_string(self) -> str: @@ -69,17 +77,25 @@ def get_imports(self, *, prefix: str) -> Set[str]: imports.add(f"from {prefix}types import UNSET, Unset") return imports - def to_string(self) -> str: - """ How this should be declared in a dataclass """ + def to_string(self, query_parameter: bool = False) -> str: + """ + How this should be declared in a dataclass + + Args: + query_parameter: True if the property's type is being used for a query parameter + """ default: Optional[str] if self.default is not None: default = self.default elif not self.required: - default = "UNSET" + if query_parameter: + default = "None" + else: + default = "UNSET" else: default = None if default is not None: - return f"{self.python_name}: {self.get_type_string()} = {default}" + return f"{self.python_name}: {self.get_type_string(query_parameter=query_parameter)} = {default}" else: - return f"{self.python_name}: {self.get_type_string()}" + return f"{self.python_name}: {self.get_type_string(query_parameter=query_parameter)}" diff --git a/openapi_python_client/templates/endpoint_macros.pyi b/openapi_python_client/templates/endpoint_macros.pyi index 5819714d8..3e527b017 100644 --- a/openapi_python_client/templates/endpoint_macros.pyi +++ b/openapi_python_client/templates/endpoint_macros.pyi @@ -17,7 +17,7 @@ if {{ parameter.python_name }} is not UNSET: {% set destination = "json_" + property.python_name %} {% if property.template %} {% from "property_templates/" + property.template import transform %} -{{ transform(property, property.python_name, destination) }} +{{ transform(property, property.python_name, destination, query_parameter=True) }} {% endif %} {% endfor %} params: Dict[str, Any] = { @@ -33,7 +33,7 @@ params: Dict[str, Any] = { } {% for property in endpoint.query_parameters %} {% if not property.required %} -if {{ property.python_name }} is not UNSET: +if {{ property.python_name }} is not UNSET and {{ property.python_name }} is not None: {% if property.template %} params["{{ property.name }}"] = {{ "json_" + property.python_name }} {% else %} @@ -96,7 +96,7 @@ json_body: {{ endpoint.json_body.get_type_string() }}, {% endif %} {# query parameters #} {% for parameter in endpoint.query_parameters %} -{{ parameter.to_string() }}, +{{ parameter.to_string(query_parameter=True) }}, {% endfor %} {% for parameter in endpoint.header_parameters %} {{ parameter.to_string() }}, diff --git a/openapi_python_client/templates/property_templates/date_property.pyi b/openapi_python_client/templates/property_templates/date_property.pyi index a3a980c8f..18fbf7735 100644 --- a/openapi_python_client/templates/property_templates/date_property.pyi +++ b/openapi_python_client/templates/property_templates/date_property.pyi @@ -9,12 +9,12 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if property.required %} {{ destination }} = {{ source }}.isoformat() {% if property.nullable %}if {{ source }} else None {%endif%} {% else %} {{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None {% else %} diff --git a/openapi_python_client/templates/property_templates/datetime_property.pyi b/openapi_python_client/templates/property_templates/datetime_property.pyi index b8e1b8ff0..073db6822 100644 --- a/openapi_python_client/templates/property_templates/datetime_property.pyi +++ b/openapi_python_client/templates/property_templates/datetime_property.pyi @@ -14,7 +14,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if property.required %} {% if property.nullable %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None @@ -23,7 +23,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% else %} {{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None {% else %} diff --git a/openapi_python_client/templates/property_templates/enum_property.pyi b/openapi_python_client/templates/property_templates/enum_property.pyi index 4765a6fd5..a5f07a8e4 100644 --- a/openapi_python_client/templates/property_templates/enum_property.pyi +++ b/openapi_python_client/templates/property_templates/enum_property.pyi @@ -9,7 +9,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if property.required %} {% if property.nullable %} {{ destination }} = {{ source }}.value if {{ source }} else None @@ -18,7 +18,7 @@ if _{{ property.python_name }} is not None: {% endif %} {% else %} {{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} {{ destination }} = {{ source }} if {{ source }} else None {% else %} diff --git a/openapi_python_client/templates/property_templates/file_property.pyi b/openapi_python_client/templates/property_templates/file_property.pyi index ffa3c20d9..3833a93ea 100644 --- a/openapi_python_client/templates/property_templates/file_property.pyi +++ b/openapi_python_client/templates/property_templates/file_property.pyi @@ -4,7 +4,7 @@ ) {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if property.required %} {% if property.nullable %} {{ destination }} = {{ source }}.to_tuple() if {{ source }} else None @@ -13,7 +13,7 @@ {% endif %} {% else %} {{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} {{ destination }} = {{ source }}.to_tuple() if {{ source }} else None {% else %} diff --git a/openapi_python_client/templates/property_templates/list_property.pyi b/openapi_python_client/templates/property_templates/list_property.pyi index d05a13960..317bb19e8 100644 --- a/openapi_python_client/templates/property_templates/list_property.pyi +++ b/openapi_python_client/templates/property_templates/list_property.pyi @@ -32,7 +32,7 @@ for {{ inner_source }} in {{ source }}: {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% set inner_property = property.inner_property %} {% if property.required %} {% if property.nullable %} @@ -45,7 +45,7 @@ else: {% endif %} {% else %} {{ destination }}{% if declare_type %}: Union[Unset, List[Any]]{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} if {{ source }} is None: {{ destination }} = None diff --git a/openapi_python_client/templates/property_templates/model_property.pyi b/openapi_python_client/templates/property_templates/model_property.pyi index e6746cb24..0ad78c991 100644 --- a/openapi_python_client/templates/property_templates/model_property.pyi +++ b/openapi_python_client/templates/property_templates/model_property.pyi @@ -15,7 +15,7 @@ if _{{ property.python_name }} is not None and not isinstance(_{{ property.pytho {% endif %} {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if property.required %} {% if property.nullable %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None @@ -24,7 +24,7 @@ if _{{ property.python_name }} is not None and not isinstance(_{{ property.pytho {% endif %} {% else %} {{ destination }}{% if declare_type %}: Union[{% if property.nullable %}None, {% endif %}Unset, Dict[str, Any]]{% endif %} = UNSET -if not isinstance({{ source }}, Unset): +if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: {% if property.nullable %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None {% else %} diff --git a/openapi_python_client/templates/property_templates/union_property.pyi b/openapi_python_client/templates/property_templates/union_property.pyi index 4c632c60a..fadef57e5 100644 --- a/openapi_python_client/templates/property_templates/union_property.pyi +++ b/openapi_python_client/templates/property_templates/union_property.pyi @@ -24,11 +24,11 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string( {{ property.python_name }} = _parse_{{ property.python_name }}({{ source }}) {% endmacro %} -{% macro transform(property, source, destination, declare_type=True) %} +{% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if not property.required %} {{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} -if isinstance({{ source }}, Unset): +if isinstance({{ source }}, Unset){%if query_parameter %} or {{ source }} is None{% endif %}: {{ destination }} = UNSET {% endif %} {% if property.nullable %} From 3265a759cd62abab831048d2c6be4346a4ed8d07 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 08:39:04 -0500 Subject: [PATCH 02/19] Run lint --- openapi_python_client/parser/properties/__init__.py | 2 +- openapi_python_client/parser/properties/property.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 30b74104f..828c3e4ea 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -162,7 +162,7 @@ def __attrs_post_init__(self) -> None: def _get_inner_prop_string(self) -> List[str]: inner_types = [p.get_type_string(no_optional=True) for p in self.inner_properties] return ", ".join(inner_types) - + def get_base_type_string(self) -> str: return f"Union[{self._get_inner_prop_string()}]" diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index a75fc481f..a7667f7aa 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -31,7 +31,7 @@ class Property: def __attrs_post_init__(self) -> None: object.__setattr__(self, "python_name", utils.to_valid_python_identifier(utils.snake_case(self.name))) - + def get_base_type_string(self) -> str: return self._type_string @@ -80,7 +80,7 @@ def get_imports(self, *, prefix: str) -> Set[str]: def to_string(self, query_parameter: bool = False) -> str: """ How this should be declared in a dataclass - + Args: query_parameter: True if the property's type is being used for a query parameter """ From 43d8bc4e418238d70d7c1e13f4acb2bd8104d382 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 08:42:51 -0500 Subject: [PATCH 03/19] Fix type error --- openapi_python_client/parser/properties/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 828c3e4ea..6138af6af 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -159,7 +159,7 @@ def __attrs_post_init__(self) -> None: self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) ) - def _get_inner_prop_string(self) -> List[str]: + def _get_inner_prop_string(self) -> str: inner_types = [p.get_type_string(no_optional=True) for p in self.inner_properties] return ", ".join(inner_types) From 6d01c2b7b7a0549effc9d893f1ec0e26dd49b5e9 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 09:00:00 -0500 Subject: [PATCH 04/19] Upgrade dependencies to fix py vulnerability --- poetry.lock | 695 ++++++++++++++++++++++++++++------------------------ 1 file changed, 369 insertions(+), 326 deletions(-) diff --git a/poetry.lock b/poetry.lock index c1d2481cd..2a1a7ca02 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,26 +1,26 @@ [[package]] -name = "appdirs" -version = "1.4.4" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "main" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +name = "appdirs" optional = false python-versions = "*" +version = "1.4.4" [[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." category = "dev" +description = "Atomic file writes." +name = "atomicwrites" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.4.0" [[package]] -name = "attrs" -version = "20.3.0" -description = "Classes Without Boilerplate" category = "main" +description = "Classes Without Boilerplate" +name = "attrs" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.3.0" [package.extras] dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface", "furo", "sphinx", "pre-commit"] @@ -29,23 +29,23 @@ tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)" tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] [[package]] -name = "autoflake" -version = "1.4" -description = "Removes unused imports and unused variables" category = "main" +description = "Removes unused imports and unused variables" +name = "autoflake" optional = false python-versions = "*" +version = "1.4" [package.dependencies] pyflakes = ">=1.1.0" [[package]] -name = "black" -version = "20.8b1" -description = "The uncompromising code formatter." category = "main" +description = "The uncompromising code formatter." +name = "black" optional = false python-versions = ">=3.6" +version = "20.8b1" [package.dependencies] appdirs = "*" @@ -63,74 +63,74 @@ colorama = ["colorama (>=0.4.3)"] d = ["aiohttp (>=3.3.2)", "aiohttp-cors"] [[package]] -name = "certifi" -version = "2020.6.20" -description = "Python package for providing Mozilla's CA Bundle." category = "main" +description = "Python package for providing Mozilla's CA Bundle." +name = "certifi" optional = false python-versions = "*" +version = "2020.12.5" [[package]] -name = "chardet" -version = "3.0.4" -description = "Universal encoding detector for Python 2 and 3" category = "dev" +description = "Universal encoding detector for Python 2 and 3" +name = "chardet" optional = false -python-versions = "*" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "4.0.0" [[package]] -name = "click" -version = "7.1.2" -description = "Composable command line interface toolkit" category = "main" +description = "Composable command line interface toolkit" +name = "click" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "7.1.2" [[package]] -name = "colorama" -version = "0.4.4" -description = "Cross-platform colored terminal text." category = "main" +description = "Cross-platform colored terminal text." +name = "colorama" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.4.4" [[package]] -name = "contextvars" -version = "2.4" -description = "PEP 567 Backport" category = "main" +description = "PEP 567 Backport" +name = "contextvars" optional = false python-versions = "*" +version = "2.4" [package.dependencies] immutables = ">=0.9" [[package]] -name = "coverage" -version = "5.3" -description = "Code coverage measurement for Python" category = "dev" +description = "Code coverage measurement for Python" +name = "coverage" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "5.3.1" [package.extras] toml = ["toml"] [[package]] -name = "dataclasses" -version = "0.6" -description = "A backport of the dataclasses module for Python 3.6" category = "main" +description = "A backport of the dataclasses module for Python 3.6" +name = "dataclasses" optional = false -python-versions = "*" +python-versions = ">=3.6, <3.7" +version = "0.8" [[package]] -name = "dparse" -version = "0.5.1" -description = "A parser for Python dependency files" category = "dev" +description = "A parser for Python dependency files" +name = "dparse" optional = false python-versions = ">=3.5" +version = "0.5.1" [package.dependencies] packaging = "*" @@ -141,12 +141,12 @@ toml = "*" pipenv = ["pipenv"] [[package]] -name = "flake8" -version = "3.8.4" -description = "the modular source code checker: pep8 pyflakes and co" category = "dev" +description = "the modular source code checker: pep8 pyflakes and co" +name = "flake8" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +version = "3.8.4" [package.dependencies] importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} @@ -155,20 +155,20 @@ pycodestyle = ">=2.6.0a1,<2.7.0" pyflakes = ">=2.2.0,<2.3.0" [[package]] -name = "h11" -version = "0.9.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +name = "h11" optional = false -python-versions = "*" +python-versions = ">=3.6" +version = "0.12.0" [[package]] -name = "httpcore" -version = "0.12.0" -description = "A minimal low-level HTTP client." category = "main" +description = "A minimal low-level HTTP client." +name = "httpcore" optional = false python-versions = ">=3.6" +version = "0.12.2" [package.dependencies] h11 = "<1.0.0" @@ -178,12 +178,12 @@ sniffio = ">=1.0.0,<2.0.0" http2 = ["h2 (>=3,<5)"] [[package]] -name = "httpx" -version = "0.16.1" -description = "The next generation HTTP client." category = "main" +description = "The next generation HTTP client." +name = "httpx" optional = false python-versions = ">=3.6" +version = "0.16.1" [package.dependencies] certifi = "*" @@ -196,64 +196,64 @@ brotli = ["brotlipy (>=0.7.0,<0.8.0)"] http2 = ["h2 (>=3.0.0,<4.0.0)"] [[package]] -name = "idna" -version = "2.10" -description = "Internationalized Domain Names in Applications (IDNA)" category = "main" +description = "Internationalized Domain Names in Applications (IDNA)" +name = "idna" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.10" [[package]] -name = "immutables" -version = "0.14" -description = "Immutable Collections" category = "main" +description = "Immutable Collections" +name = "immutables" optional = false python-versions = ">=3.5" +version = "0.14" [[package]] -name = "importlib-metadata" -version = "2.0.0" -description = "Read metadata from Python packages" category = "main" +description = "Read metadata from Python packages" +name = "importlib-metadata" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +version = "2.1.1" [package.dependencies] zipp = ">=0.5" [package.extras] docs = ["sphinx", "rst.linker"] -testing = ["packaging", "pep517", "importlib-resources (>=1.3)"] +testing = ["packaging", "pep517", "unittest2", "importlib-resources (>=1.3)"] [[package]] -name = "iniconfig" -version = "1.0.1" -description = "iniconfig: brain-dead simple config-ini parsing" category = "dev" +description = "iniconfig: brain-dead simple config-ini parsing" +name = "iniconfig" optional = false python-versions = "*" +version = "1.1.1" [[package]] -name = "isort" -version = "5.7.0" -description = "A Python utility / library to sort Python imports." category = "main" +description = "A Python utility / library to sort Python imports." +name = "isort" optional = false python-versions = ">=3.6,<4.0" +version = "5.7.0" [package.extras] +colors = ["colorama (>=0.4.3,<0.5.0)"] pipfile_deprecated_finder = ["pipreqs", "requirementslib"] requirements_deprecated_finder = ["pipreqs", "pip-api"] -colors = ["colorama (>=0.4.3,<0.5.0)"] [[package]] -name = "jinja2" -version = "2.11.2" -description = "A very fast and expressive template engine." category = "main" +description = "A very fast and expressive template engine." +name = "jinja2" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.11.2" [package.dependencies] MarkupSafe = ">=0.23" @@ -262,36 +262,36 @@ MarkupSafe = ">=0.23" i18n = ["Babel (>=0.8)"] [[package]] -name = "markupsafe" -version = "1.1.1" -description = "Safely add untrusted strings to HTML/XML markup." category = "main" +description = "Safely add untrusted strings to HTML/XML markup." +name = "markupsafe" optional = false python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" +version = "1.1.1" [[package]] -name = "mccabe" -version = "0.6.1" -description = "McCabe checker, plugin for flake8" category = "dev" +description = "McCabe checker, plugin for flake8" +name = "mccabe" optional = false python-versions = "*" +version = "0.6.1" [[package]] -name = "mslex" -version = "0.3.0" -description = "shlex for windows" category = "dev" +description = "shlex for windows" +name = "mslex" optional = false python-versions = ">=3.5" +version = "0.3.0" [[package]] -name = "mypy" -version = "0.790" -description = "Optional static typing for Python" category = "dev" +description = "Optional static typing for Python" +name = "mypy" optional = false python-versions = ">=3.5" +version = "0.790" [package.dependencies] mypy-extensions = ">=0.4.3,<0.5.0" @@ -302,40 +302,39 @@ typing-extensions = ">=3.7.4" dmypy = ["psutil (>=4.0)"] [[package]] -name = "mypy-extensions" -version = "0.4.3" -description = "Experimental type system extensions for programs checked with the mypy typechecker." category = "main" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +name = "mypy-extensions" optional = false python-versions = "*" +version = "0.4.3" [[package]] -name = "packaging" -version = "20.4" -description = "Core utilities for Python packages" category = "dev" +description = "Core utilities for Python packages" +name = "packaging" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "20.8" [package.dependencies] pyparsing = ">=2.0.2" -six = "*" [[package]] -name = "pathspec" -version = "0.8.0" -description = "Utility library for gitignore style pattern matching of file paths." category = "main" +description = "Utility library for gitignore style pattern matching of file paths." +name = "pathspec" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "0.8.1" [[package]] -name = "pluggy" -version = "0.13.1" -description = "plugin and hook calling mechanisms for python" category = "dev" +description = "plugin and hook calling mechanisms for python" +name = "pluggy" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "0.13.1" [package.dependencies] importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} @@ -344,39 +343,39 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""} dev = ["pre-commit", "tox"] [[package]] -name = "psutil" -version = "5.7.2" -description = "Cross-platform lib for process and system monitoring in Python." category = "dev" +description = "Cross-platform lib for process and system monitoring in Python." +name = "psutil" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "5.8.0" [package.extras] test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"] [[package]] -name = "py" -version = "1.9.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" category = "dev" +description = "library with cross-python path, ini-parsing, io, code, log facilities" +name = "py" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "1.10.0" [[package]] -name = "pycodestyle" -version = "2.6.0" -description = "Python style guide checker" category = "dev" +description = "Python style guide checker" +name = "pycodestyle" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.6.0" [[package]] -name = "pydantic" -version = "1.7.3" -description = "Data validation and settings management using python 3.6 type hinting" category = "main" +description = "Data validation and settings management using python 3.6 type hinting" +name = "pydantic" optional = false python-versions = ">=3.6" +version = "1.7.3" [package.dependencies] dataclasses = {version = ">=0.6", markers = "python_version < \"3.7\""} @@ -387,28 +386,28 @@ email = ["email-validator (>=1.0.3)"] typing_extensions = ["typing-extensions (>=3.7.2)"] [[package]] -name = "pyflakes" -version = "2.2.0" -description = "passive checker of Python programs" category = "main" +description = "passive checker of Python programs" +name = "pyflakes" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +version = "2.2.0" [[package]] -name = "pyparsing" -version = "2.4.7" -description = "Python parsing module" category = "dev" +description = "Python parsing module" +name = "pyparsing" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "2.4.7" [[package]] -name = "pytest" -version = "6.2.1" -description = "pytest: simple powerful testing with Python" category = "dev" +description = "pytest: simple powerful testing with Python" +name = "pytest" optional = false python-versions = ">=3.6" +version = "6.2.1" [package.dependencies] atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} @@ -425,12 +424,12 @@ toml = "*" testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] [[package]] -name = "pytest-cov" -version = "2.10.1" -description = "Pytest plugin for measuring coverage." category = "dev" +description = "Pytest plugin for measuring coverage." +name = "pytest-cov" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.10.1" [package.dependencies] coverage = ">=4.4" @@ -440,12 +439,12 @@ pytest = ">=4.6" testing = ["fields", "hunter", "process-tests (==2.0.2)", "six", "pytest-xdist", "virtualenv"] [[package]] -name = "pytest-mock" -version = "3.5.1" -description = "Thin-wrapper around the mock package for easier use with pytest" category = "dev" +description = "Thin-wrapper around the mock package for easier use with pytest" +name = "pytest-mock" optional = false python-versions = ">=3.5" +version = "3.5.1" [package.dependencies] pytest = ">=5.0" @@ -454,68 +453,68 @@ pytest = ">=5.0" dev = ["pre-commit", "tox", "pytest-asyncio"] [[package]] -name = "python-dateutil" -version = "2.8.1" -description = "Extensions to the standard Python datetime module" category = "main" +description = "Extensions to the standard Python datetime module" +name = "python-dateutil" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +version = "2.8.1" [package.dependencies] six = ">=1.5" [[package]] -name = "python-multipart" -version = "0.0.5" -description = "A streaming multipart parser for Python" category = "dev" +description = "A streaming multipart parser for Python" +name = "python-multipart" optional = false python-versions = "*" +version = "0.0.5" [package.dependencies] six = ">=1.4.0" [[package]] -name = "pyyaml" -version = "5.3.1" -description = "YAML parser and emitter for Python" category = "main" +description = "YAML parser and emitter for Python" +name = "pyyaml" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "5.3.1" [[package]] -name = "regex" -version = "2020.9.27" -description = "Alternative regular expression module, to replace re." category = "main" +description = "Alternative regular expression module, to replace re." +name = "regex" optional = false python-versions = "*" +version = "2020.11.13" [[package]] -name = "requests" -version = "2.24.0" -description = "Python HTTP for Humans." category = "dev" +description = "Python HTTP for Humans." +name = "requests" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +version = "2.25.1" [package.dependencies] certifi = ">=2017.4.17" -chardet = ">=3.0.2,<4" +chardet = ">=3.0.2,<5" idna = ">=2.5,<3" -urllib3 = ">=1.21.1,<1.25.0 || >1.25.0,<1.25.1 || >1.25.1,<1.26" +urllib3 = ">=1.21.1,<1.27" [package.extras] security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] [[package]] -name = "rfc3986" -version = "1.4.0" -description = "Validating URI References per RFC 3986" category = "main" +description = "Validating URI References per RFC 3986" +name = "rfc3986" optional = false python-versions = "*" +version = "1.4.0" [package.dependencies] idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} @@ -524,12 +523,12 @@ idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} idna2008 = ["idna"] [[package]] -name = "safety" -version = "1.10.1" -description = "Checks installed dependencies for known vulnerabilities." category = "dev" +description = "Checks installed dependencies for known vulnerabilities." +name = "safety" optional = false python-versions = ">=3.5" +version = "1.10.2.post1" [package.dependencies] Click = ">=6.0" @@ -538,47 +537,47 @@ packaging = "*" requests = "*" [[package]] -name = "shellingham" -version = "1.3.2" -description = "Tool to Detect Surrounding Shell" category = "main" +description = "Tool to Detect Surrounding Shell" +name = "shellingham" optional = false python-versions = "!=3.0,!=3.1,!=3.2,!=3.3,>=2.6" +version = "1.3.2" [[package]] -name = "six" -version = "1.15.0" -description = "Python 2 and 3 compatibility utilities" category = "main" +description = "Python 2 and 3 compatibility utilities" +name = "six" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +version = "1.15.0" [[package]] -name = "sniffio" -version = "1.1.0" -description = "Sniff out which async library your code is running under" category = "main" +description = "Sniff out which async library your code is running under" +name = "sniffio" optional = false python-versions = ">=3.5" +version = "1.2.0" [package.dependencies] contextvars = {version = ">=2.1", markers = "python_version < \"3.7\""} [[package]] -name = "stringcase" -version = "1.2.0" -description = "String case converter." category = "main" +description = "String case converter." +name = "stringcase" optional = false python-versions = "*" +version = "1.2.0" [[package]] -name = "taskipy" -version = "1.6.0" -description = "tasks runner for python projects" category = "dev" +description = "tasks runner for python projects" +name = "taskipy" optional = false python-versions = ">=3.6,<4.0" +version = "1.6.0" [package.dependencies] mslex = ">=0.3.0,<0.4.0" @@ -586,45 +585,45 @@ psutil = ">=5.7.2,<6.0.0" toml = ">=0.10.0,<0.11.0" [[package]] -name = "toml" -version = "0.10.1" -description = "Python Library for Tom's Obvious, Minimal Language" category = "main" +description = "Python Library for Tom's Obvious, Minimal Language" +name = "toml" optional = false -python-versions = "*" +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +version = "0.10.2" [[package]] -name = "typed-ast" -version = "1.4.1" -description = "a fork of Python 2 and 3 ast modules with type comment support" category = "main" +description = "a fork of Python 2 and 3 ast modules with type comment support" +name = "typed-ast" optional = false python-versions = "*" +version = "1.4.2" [[package]] -name = "typer" -version = "0.3.2" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." category = "main" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +name = "typer" optional = false python-versions = ">=3.6" +version = "0.3.2" [package.dependencies] click = ">=7.1.1,<7.2.0" [package.extras] -test = ["pytest-xdist (>=1.32.0,<2.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "mypy (==0.782)", "black (>=19.10b0,<20.0b0)", "isort (>=5.0.6,<6.0.0)", "shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "coverage (>=5.2,<6.0)"] all = ["colorama (>=0.4.3,<0.5.0)", "shellingham (>=1.3.0,<2.0.0)"] dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)"] doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=5.4.0,<6.0.0)", "markdown-include (>=0.5.1,<0.6.0)"] +test = ["pytest-xdist (>=1.32.0,<2.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "mypy (==0.782)", "black (>=19.10b0,<20.0b0)", "isort (>=5.0.6,<6.0.0)", "shellingham (>=1.3.0,<2.0.0)", "pytest (>=4.4.0,<5.4.0)", "pytest-cov (>=2.10.0,<3.0.0)", "coverage (>=5.2,<6.0)"] [[package]] -name = "typer-cli" -version = "0.0.11" -description = "Run Typer scripts with completion, without having to create a package, using Typer CLI." category = "dev" +description = "Run Typer scripts with completion, without having to create a package, using Typer CLI." +name = "typer-cli" optional = false python-versions = ">=3.6,<4.0" +version = "0.0.11" [package.dependencies] colorama = ">=0.4.3,<0.5.0" @@ -633,42 +632,42 @@ shellingham = ">=1.3.2,<2.0.0" typer = ">=0.3.0,<0.4.0" [[package]] -name = "typing-extensions" -version = "3.7.4.3" -description = "Backported and Experimental Type Hints for Python 3.5+" category = "main" +description = "Backported and Experimental Type Hints for Python 3.5+" +name = "typing-extensions" optional = false python-versions = "*" +version = "3.7.4.3" [[package]] -name = "urllib3" -version = "1.25.10" -description = "HTTP library with thread-safe connection pooling, file post, and more." category = "dev" +description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "urllib3" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +version = "1.26.2" [package.extras] brotli = ["brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "pyOpenSSL (>=0.14)", "ipaddress"] +secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] -name = "zipp" -version = "3.3.0" -description = "Backport of pathlib-compatible object wrapper for zip files" category = "main" +description = "Backport of pathlib-compatible object wrapper for zip files" +name = "zipp" optional = false python-versions = ">=3.6" +version = "3.4.0" [package.extras] docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"] testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy"] [metadata] +content-hash = "b6a52b70db4ea03eda283efd4e65611530ab59b2091c675881e6cab696276f54" lock-version = "1.1" python-versions = "^3.6" -content-hash = "b6a52b70db4ea03eda283efd4e65611530ab59b2091c675881e6cab696276f54" [metadata.files] appdirs = [ @@ -687,15 +686,16 @@ autoflake = [ {file = "autoflake-1.4.tar.gz", hash = "sha256:61a353012cff6ab94ca062823d1fb2f692c4acda51c76ff83a8d77915fba51ea"}, ] black = [ + {file = "black-20.8b1-py3-none-any.whl", hash = "sha256:70b62ef1527c950db59062cda342ea224d772abdf6adc58b86a45421bab20a6b"}, {file = "black-20.8b1.tar.gz", hash = "sha256:1c02557aa099101b9d21496f8a914e9ed2222ef70336404eeeac8edba836fbea"}, ] certifi = [ - {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, - {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, + {file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, + {file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, ] chardet = [ - {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, - {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, + {file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, + {file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, ] click = [ {file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"}, @@ -703,50 +703,64 @@ click = [ ] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, - {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, ] contextvars = [ {file = "contextvars-2.4.tar.gz", hash = "sha256:f38c908aaa59c14335eeea12abea5f443646216c4e29380d7bf34d2018e2c39e"}, ] coverage = [ - {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"}, - {file = "coverage-5.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4"}, - {file = "coverage-5.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9"}, - {file = "coverage-5.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729"}, - {file = "coverage-5.3-cp27-cp27m-win32.whl", hash = "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d"}, - {file = "coverage-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418"}, - {file = "coverage-5.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9"}, - {file = "coverage-5.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5"}, - {file = "coverage-5.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822"}, - {file = "coverage-5.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097"}, - {file = "coverage-5.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9"}, - {file = "coverage-5.3-cp35-cp35m-win32.whl", hash = "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636"}, - {file = "coverage-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f"}, - {file = "coverage-5.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237"}, - {file = "coverage-5.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54"}, - {file = "coverage-5.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7"}, - {file = "coverage-5.3-cp36-cp36m-win32.whl", hash = "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a"}, - {file = "coverage-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d"}, - {file = "coverage-5.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"}, - {file = "coverage-5.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f"}, - {file = "coverage-5.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c"}, - {file = "coverage-5.3-cp37-cp37m-win32.whl", hash = "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751"}, - {file = "coverage-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709"}, - {file = "coverage-5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516"}, - {file = "coverage-5.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f"}, - {file = "coverage-5.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259"}, - {file = "coverage-5.3-cp38-cp38-win32.whl", hash = "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82"}, - {file = "coverage-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221"}, - {file = "coverage-5.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978"}, - {file = "coverage-5.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21"}, - {file = "coverage-5.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24"}, - {file = "coverage-5.3-cp39-cp39-win32.whl", hash = "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7"}, - {file = "coverage-5.3-cp39-cp39-win_amd64.whl", hash = "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7"}, - {file = "coverage-5.3.tar.gz", hash = "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0"}, + {file = "coverage-5.3.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fabeeb121735d47d8eab8671b6b031ce08514c86b7ad8f7d5490a7b6dcd6267d"}, + {file = "coverage-5.3.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:7e4d159021c2029b958b2363abec4a11db0ce8cd43abb0d9ce44284cb97217e7"}, + {file = "coverage-5.3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:378ac77af41350a8c6b8801a66021b52da8a05fd77e578b7380e876c0ce4f528"}, + {file = "coverage-5.3.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e448f56cfeae7b1b3b5bcd99bb377cde7c4eb1970a525c770720a352bc4c8044"}, + {file = "coverage-5.3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:cc44e3545d908ecf3e5773266c487ad1877be718d9dc65fc7eb6e7d14960985b"}, + {file = "coverage-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:08b3ba72bd981531fd557f67beee376d6700fba183b167857038997ba30dd297"}, + {file = "coverage-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:8dacc4073c359f40fcf73aede8428c35f84639baad7e1b46fce5ab7a8a7be4bb"}, + {file = "coverage-5.3.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ee2f1d1c223c3d2c24e3afbb2dd38be3f03b1a8d6a83ee3d9eb8c36a52bee899"}, + {file = "coverage-5.3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9a9d4ff06804920388aab69c5ea8a77525cf165356db70131616acd269e19b36"}, + {file = "coverage-5.3.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:782a5c7df9f91979a7a21792e09b34a658058896628217ae6362088b123c8500"}, + {file = "coverage-5.3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:fda29412a66099af6d6de0baa6bd7c52674de177ec2ad2630ca264142d69c6c7"}, + {file = "coverage-5.3.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:f2c6888eada180814b8583c3e793f3f343a692fc802546eed45f40a001b1169f"}, + {file = "coverage-5.3.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8f33d1156241c43755137288dea619105477961cfa7e47f48dbf96bc2c30720b"}, + {file = "coverage-5.3.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b239711e774c8eb910e9b1ac719f02f5ae4bf35fa0420f438cdc3a7e4e7dd6ec"}, + {file = "coverage-5.3.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:f54de00baf200b4539a5a092a759f000b5f45fd226d6d25a76b0dff71177a714"}, + {file = "coverage-5.3.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:be0416074d7f253865bb67630cf7210cbc14eb05f4099cc0f82430135aaa7a3b"}, + {file = "coverage-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:c46643970dff9f5c976c6512fd35768c4a3819f01f61169d8cdac3f9290903b7"}, + {file = "coverage-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9a4f66259bdd6964d8cf26142733c81fb562252db74ea367d9beb4f815478e72"}, + {file = "coverage-5.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c6e5174f8ca585755988bc278c8bb5d02d9dc2e971591ef4a1baabdf2d99589b"}, + {file = "coverage-5.3.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3911c2ef96e5ddc748a3c8b4702c61986628bb719b8378bf1e4a6184bbd48fe4"}, + {file = "coverage-5.3.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c5ec71fd4a43b6d84ddb88c1df94572479d9a26ef3f150cef3dacefecf888105"}, + {file = "coverage-5.3.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f51dbba78d68a44e99d484ca8c8f604f17e957c1ca09c3ebc2c7e3bbd9ba0448"}, + {file = "coverage-5.3.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a2070c5affdb3a5e751f24208c5c4f3d5f008fa04d28731416e023c93b275277"}, + {file = "coverage-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:535dc1e6e68fad5355f9984d5637c33badbdc987b0c0d303ee95a6c979c9516f"}, + {file = "coverage-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:a4857f7e2bc6921dbd487c5c88b84f5633de3e7d416c4dc0bb70256775551a6c"}, + {file = "coverage-5.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fac3c432851038b3e6afe086f777732bcf7f6ebbfd90951fa04ee53db6d0bcdd"}, + {file = "coverage-5.3.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cd556c79ad665faeae28020a0ab3bda6cd47d94bec48e36970719b0b86e4dcf4"}, + {file = "coverage-5.3.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a66ca3bdf21c653e47f726ca57f46ba7fc1f260ad99ba783acc3e58e3ebdb9ff"}, + {file = "coverage-5.3.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ab110c48bc3d97b4d19af41865e14531f300b482da21783fdaacd159251890e8"}, + {file = "coverage-5.3.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e52d3d95df81c8f6b2a1685aabffadf2d2d9ad97203a40f8d61e51b70f191e4e"}, + {file = "coverage-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:fa10fee7e32213f5c7b0d6428ea92e3a3fdd6d725590238a3f92c0de1c78b9d2"}, + {file = "coverage-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ce6f3a147b4b1a8b09aae48517ae91139b1b010c5f36423fa2b866a8b23df879"}, + {file = "coverage-5.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:93a280c9eb736a0dcca19296f3c30c720cb41a71b1f9e617f341f0a8e791a69b"}, + {file = "coverage-5.3.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3102bb2c206700a7d28181dbe04d66b30780cde1d1c02c5f3c165cf3d2489497"}, + {file = "coverage-5.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8ffd4b204d7de77b5dd558cdff986a8274796a1e57813ed005b33fd97e29f059"}, + {file = "coverage-5.3.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a607ae05b6c96057ba86c811d9c43423f35e03874ffb03fbdcd45e0637e8b631"}, + {file = "coverage-5.3.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3a3c3f8863255f3c31db3889f8055989527173ef6192a283eb6f4db3c579d830"}, + {file = "coverage-5.3.1-cp38-cp38-win32.whl", hash = "sha256:ff1330e8bc996570221b450e2d539134baa9465f5cb98aff0e0f73f34172e0ae"}, + {file = "coverage-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:3498b27d8236057def41de3585f317abae235dd3a11d33e01736ffedb2ef8606"}, + {file = "coverage-5.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ceb499d2b3d1d7b7ba23abe8bf26df5f06ba8c71127f188333dddcf356b4b63f"}, + {file = "coverage-5.3.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:3b14b1da110ea50c8bcbadc3b82c3933974dbeea1832e814aab93ca1163cd4c1"}, + {file = "coverage-5.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:76b2775dda7e78680d688daabcb485dc87cf5e3184a0b3e012e1d40e38527cc8"}, + {file = "coverage-5.3.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:cef06fb382557f66d81d804230c11ab292d94b840b3cb7bf4450778377b592f4"}, + {file = "coverage-5.3.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f61319e33222591f885c598e3e24f6a4be3533c1d70c19e0dc59e83a71ce27d"}, + {file = "coverage-5.3.1-cp39-cp39-win32.whl", hash = "sha256:cc6f8246e74dd210d7e2b56c76ceaba1cc52b025cd75dbe96eb48791e0250e98"}, + {file = "coverage-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:2757fa64e11ec12220968f65d086b7a29b6583d16e9a544c889b22ba98555ef1"}, + {file = "coverage-5.3.1-pp36-none-any.whl", hash = "sha256:723d22d324e7997a651478e9c5a3120a0ecbc9a7e94071f7e1954562a8806cf3"}, + {file = "coverage-5.3.1-pp37-none-any.whl", hash = "sha256:c89b558f8a9a5a6f2cfc923c304d49f0ce629c3bd85cb442ca258ec20366394c"}, + {file = "coverage-5.3.1.tar.gz", hash = "sha256:38f16b1317b8dd82df67ed5daa5f5e7c959e46579840d77a67a4ceb9cef0a50b"}, ] dataclasses = [ - {file = "dataclasses-0.6-py3-none-any.whl", hash = "sha256:454a69d788c7fda44efd71e259be79577822f5e3f53f029a22d08004e951dc9f"}, - {file = "dataclasses-0.6.tar.gz", hash = "sha256:6988bd2b895eef432d562370bb707d540f32f7360ab13da45340101bc2307d84"}, + {file = "dataclasses-0.8-py3-none-any.whl", hash = "sha256:0201d89fa866f68c8ebd9d08ee6ff50c0b255f8ec63a71c16fda7af82bb887bf"}, + {file = "dataclasses-0.8.tar.gz", hash = "sha256:8479067f342acf957dc82ec415d355ab5edb7e7646b90dc6e2fd1d96ad084c97"}, ] dparse = [ {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, @@ -757,12 +771,12 @@ flake8 = [ {file = "flake8-3.8.4.tar.gz", hash = "sha256:aadae8761ec651813c24be05c6f7b4680857ef6afaae4651a4eccaef97ce6c3b"}, ] h11 = [ - {file = "h11-0.9.0-py2.py3-none-any.whl", hash = "sha256:4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1"}, - {file = "h11-0.9.0.tar.gz", hash = "sha256:33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1"}, + {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, + {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, ] httpcore = [ - {file = "httpcore-0.12.0-py3-none-any.whl", hash = "sha256:18c4afcbfe884b635e59739105aed1692e132bc5d31597109f3c1c97e4ec1cac"}, - {file = "httpcore-0.12.0.tar.gz", hash = "sha256:2526a38f31ac5967d38b7f593b5d8c4bd3fa82c21400402f866ba3312946acbf"}, + {file = "httpcore-0.12.2-py3-none-any.whl", hash = "sha256:420700af11db658c782f7e8fda34f9dcd95e3ee93944dd97d78cb70247e0cd06"}, + {file = "httpcore-0.12.2.tar.gz", hash = "sha256:dd1d762d4f7c2702149d06be2597c35fb154c5eff9789a8c5823fbcf4d2978d6"}, ] httpx = [ {file = "httpx-0.16.1-py3-none-any.whl", hash = "sha256:9cffb8ba31fac6536f2c8cde30df859013f59e4bcc5b8d43901cb3654a8e0a5b"}, @@ -787,12 +801,12 @@ immutables = [ {file = "immutables-0.14.tar.gz", hash = "sha256:a0a1cc238b678455145bae291d8426f732f5255537ed6a5b7645949704c70a78"}, ] importlib-metadata = [ - {file = "importlib_metadata-2.0.0-py2.py3-none-any.whl", hash = "sha256:cefa1a2f919b866c5beb7c9f7b0ebb4061f30a8a9bf16d609b000e2dfaceb9c3"}, - {file = "importlib_metadata-2.0.0.tar.gz", hash = "sha256:77a540690e24b0305878c37ffd421785a6f7e53c8b5720d211b211de8d0e95da"}, + {file = "importlib_metadata-2.1.1-py2.py3-none-any.whl", hash = "sha256:c2d6341ff566f609e89a2acb2db190e5e1d23d5409d6cc8d2fe34d72443876d4"}, + {file = "importlib_metadata-2.1.1.tar.gz", hash = "sha256:b8de9eff2b35fb037368f28a7df1df4e6436f578fa74423505b6c6a778d5b5dd"}, ] iniconfig = [ - {file = "iniconfig-1.0.1-py3-none-any.whl", hash = "sha256:80cf40c597eb564e86346103f609d74efce0f6b4d4f30ec8ce9e2c26411ba437"}, - {file = "iniconfig-1.0.1.tar.gz", hash = "sha256:e5f92f89355a67de0595932a6c6c02ab4afddc6fcdc0bfc5becd0d60884d3f69"}, + {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, + {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, ] isort = [ {file = "isort-5.7.0-py3-none-any.whl", hash = "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"}, @@ -866,33 +880,50 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] packaging = [ - {file = "packaging-20.4-py2.py3-none-any.whl", hash = "sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181"}, - {file = "packaging-20.4.tar.gz", hash = "sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8"}, + {file = "packaging-20.8-py2.py3-none-any.whl", hash = "sha256:24e0da08660a87484d1602c30bb4902d74816b6985b93de36926f5bc95741858"}, + {file = "packaging-20.8.tar.gz", hash = "sha256:78598185a7008a470d64526a8059de9aaa449238f280fc9eb6b13ba6c4109093"}, ] pathspec = [ - {file = "pathspec-0.8.0-py2.py3-none-any.whl", hash = "sha256:7d91249d21749788d07a2d0f94147accd8f845507400749ea19c1ec9054a12b0"}, - {file = "pathspec-0.8.0.tar.gz", hash = "sha256:da45173eb3a6f2a5a487efba21f050af2b41948be6ab52b6a1e3ff22bb8b7061"}, + {file = "pathspec-0.8.1-py2.py3-none-any.whl", hash = "sha256:aa0cb481c4041bf52ffa7b0d8fa6cd3e88a2ca4879c533c9153882ee2556790d"}, + {file = "pathspec-0.8.1.tar.gz", hash = "sha256:86379d6b86d75816baba717e64b1a3a3469deb93bb76d613c9ce79edc5cb68fd"}, ] pluggy = [ {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"}, {file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"}, ] psutil = [ - {file = "psutil-5.7.2-cp27-none-win32.whl", hash = "sha256:f2018461733b23f308c298653c8903d32aaad7873d25e1d228765e91ae42c3f2"}, - {file = "psutil-5.7.2-cp27-none-win_amd64.whl", hash = "sha256:66c18ca7680a31bf16ee22b1d21b6397869dda8059dbdb57d9f27efa6615f195"}, - {file = "psutil-5.7.2-cp35-cp35m-win32.whl", hash = "sha256:5e9d0f26d4194479a13d5f4b3798260c20cecf9ac9a461e718eb59ea520a360c"}, - {file = "psutil-5.7.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4080869ed93cce662905b029a1770fe89c98787e543fa7347f075ade761b19d6"}, - {file = "psutil-5.7.2-cp36-cp36m-win32.whl", hash = "sha256:d8a82162f23c53b8525cf5f14a355f5d1eea86fa8edde27287dd3a98399e4fdf"}, - {file = "psutil-5.7.2-cp36-cp36m-win_amd64.whl", hash = "sha256:0ee3c36428f160d2d8fce3c583a0353e848abb7de9732c50cf3356dd49ad63f8"}, - {file = "psutil-5.7.2-cp37-cp37m-win32.whl", hash = "sha256:ff1977ba1a5f71f89166d5145c3da1cea89a0fdb044075a12c720ee9123ec818"}, - {file = "psutil-5.7.2-cp37-cp37m-win_amd64.whl", hash = "sha256:a5b120bb3c0c71dfe27551f9da2f3209a8257a178ed6c628a819037a8df487f1"}, - {file = "psutil-5.7.2-cp38-cp38-win32.whl", hash = "sha256:10512b46c95b02842c225f58fa00385c08fa00c68bac7da2d9a58ebe2c517498"}, - {file = "psutil-5.7.2-cp38-cp38-win_amd64.whl", hash = "sha256:68d36986ded5dac7c2dcd42f2682af1db80d4bce3faa126a6145c1637e1b559f"}, - {file = "psutil-5.7.2.tar.gz", hash = "sha256:90990af1c3c67195c44c9a889184f84f5b2320dce3ee3acbd054e3ba0b4a7beb"}, + {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"}, + {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:0ae6f386d8d297177fd288be6e8d1afc05966878704dad9847719650e44fc49c"}, + {file = "psutil-5.8.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:12d844996d6c2b1d3881cfa6fa201fd635971869a9da945cf6756105af73d2df"}, + {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:02b8292609b1f7fcb34173b25e48d0da8667bc85f81d7476584d889c6e0f2131"}, + {file = "psutil-5.8.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6ffe81843131ee0ffa02c317186ed1e759a145267d54fdef1bc4ea5f5931ab60"}, + {file = "psutil-5.8.0-cp27-none-win32.whl", hash = "sha256:ea313bb02e5e25224e518e4352af4bf5e062755160f77e4b1767dd5ccb65f876"}, + {file = "psutil-5.8.0-cp27-none-win_amd64.whl", hash = "sha256:5da29e394bdedd9144c7331192e20c1f79283fb03b06e6abd3a8ae45ffecee65"}, + {file = "psutil-5.8.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:74fb2557d1430fff18ff0d72613c5ca30c45cdbfcddd6a5773e9fc1fe9364be8"}, + {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:74f2d0be88db96ada78756cb3a3e1b107ce8ab79f65aa885f76d7664e56928f6"}, + {file = "psutil-5.8.0-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:99de3e8739258b3c3e8669cb9757c9a861b2a25ad0955f8e53ac662d66de61ac"}, + {file = "psutil-5.8.0-cp36-cp36m-win32.whl", hash = "sha256:36b3b6c9e2a34b7d7fbae330a85bf72c30b1c827a4366a07443fc4b6270449e2"}, + {file = "psutil-5.8.0-cp36-cp36m-win_amd64.whl", hash = "sha256:52de075468cd394ac98c66f9ca33b2f54ae1d9bff1ef6b67a212ee8f639ec06d"}, + {file = "psutil-5.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c6a5fd10ce6b6344e616cf01cc5b849fa8103fbb5ba507b6b2dee4c11e84c935"}, + {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:61f05864b42fedc0771d6d8e49c35f07efd209ade09a5afe6a5059e7bb7bf83d"}, + {file = "psutil-5.8.0-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:0dd4465a039d343925cdc29023bb6960ccf4e74a65ad53e768403746a9207023"}, + {file = "psutil-5.8.0-cp37-cp37m-win32.whl", hash = "sha256:1bff0d07e76114ec24ee32e7f7f8d0c4b0514b3fae93e3d2aaafd65d22502394"}, + {file = "psutil-5.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563"}, + {file = "psutil-5.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6223d07a1ae93f86451d0198a0c361032c4c93ebd4bf6d25e2fb3edfad9571ef"}, + {file = "psutil-5.8.0-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d225cd8319aa1d3c85bf195c4e07d17d3cd68636b8fc97e6cf198f782f99af28"}, + {file = "psutil-5.8.0-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:28ff7c95293ae74bf1ca1a79e8805fcde005c18a122ca983abf676ea3466362b"}, + {file = "psutil-5.8.0-cp38-cp38-win32.whl", hash = "sha256:ce8b867423291cb65cfc6d9c4955ee9bfc1e21fe03bb50e177f2b957f1c2469d"}, + {file = "psutil-5.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:90f31c34d25b1b3ed6c40cdd34ff122b1887a825297c017e4cbd6796dd8b672d"}, + {file = "psutil-5.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6323d5d845c2785efb20aded4726636546b26d3b577aded22492908f7c1bdda7"}, + {file = "psutil-5.8.0-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:245b5509968ac0bd179287d91210cd3f37add77dad385ef238b275bad35fa1c4"}, + {file = "psutil-5.8.0-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:90d4091c2d30ddd0a03e0b97e6a33a48628469b99585e2ad6bf21f17423b112b"}, + {file = "psutil-5.8.0-cp39-cp39-win32.whl", hash = "sha256:ea372bcc129394485824ae3e3ddabe67dc0b118d262c568b4d2602a7070afdb0"}, + {file = "psutil-5.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3"}, + {file = "psutil-5.8.0.tar.gz", hash = "sha256:0c9ccb99ab76025f2f0bbecf341d4656e9c1351db8cc8a03ccd62e318ab4b5c6"}, ] py = [ - {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, - {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, + {file = "py-1.10.0-py2.py3-none-any.whl", hash = "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a"}, + {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"}, ] pycodestyle = [ {file = "pycodestyle-2.6.0-py2.py3-none-any.whl", hash = "sha256:2295e7b2f6b5bd100585ebcb1f616591b652db8a741695b3d8f5d28bdc934367"}, @@ -960,50 +991,62 @@ pyyaml = [ {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"}, {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"}, {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"}, - {file = "PyYAML-5.3.1-cp39-cp39-win32.whl", hash = "sha256:ad9c67312c84def58f3c04504727ca879cb0013b2517c85a9a253f0cb6380c0a"}, - {file = "PyYAML-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:6034f55dab5fea9e53f436aa68fa3ace2634918e8b5994d82f3621c04ff5ed2e"}, {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"}, ] regex = [ - {file = "regex-2020.9.27-cp27-cp27m-win32.whl", hash = "sha256:d23a18037313714fb3bb5a94434d3151ee4300bae631894b1ac08111abeaa4a3"}, - {file = "regex-2020.9.27-cp27-cp27m-win_amd64.whl", hash = "sha256:84e9407db1b2eb368b7ecc283121b5e592c9aaedbe8c78b1a2f1102eb2e21d19"}, - {file = "regex-2020.9.27-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5f18875ac23d9aa2f060838e8b79093e8bb2313dbaaa9f54c6d8e52a5df097be"}, - {file = "regex-2020.9.27-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ae91972f8ac958039920ef6e8769277c084971a142ce2b660691793ae44aae6b"}, - {file = "regex-2020.9.27-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:9a02d0ae31d35e1ec12a4ea4d4cca990800f66a917d0fb997b20fbc13f5321fc"}, - {file = "regex-2020.9.27-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:ebbe29186a3d9b0c591e71b7393f1ae08c83cb2d8e517d2a822b8f7ec99dfd8b"}, - {file = "regex-2020.9.27-cp36-cp36m-win32.whl", hash = "sha256:4707f3695b34335afdfb09be3802c87fa0bc27030471dbc082f815f23688bc63"}, - {file = "regex-2020.9.27-cp36-cp36m-win_amd64.whl", hash = "sha256:9bc13e0d20b97ffb07821aa3e113f9998e84994fe4d159ffa3d3a9d1b805043b"}, - {file = "regex-2020.9.27-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f1b3afc574a3db3b25c89161059d857bd4909a1269b0b3cb3c904677c8c4a3f7"}, - {file = "regex-2020.9.27-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5533a959a1748a5c042a6da71fe9267a908e21eded7a4f373efd23a2cbdb0ecc"}, - {file = "regex-2020.9.27-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:1fe0a41437bbd06063aa184c34804efa886bcc128222e9916310c92cd54c3b4c"}, - {file = "regex-2020.9.27-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:c570f6fa14b9c4c8a4924aaad354652366577b4f98213cf76305067144f7b100"}, - {file = "regex-2020.9.27-cp37-cp37m-win32.whl", hash = "sha256:eda4771e0ace7f67f58bc5b560e27fb20f32a148cbc993b0c3835970935c2707"}, - {file = "regex-2020.9.27-cp37-cp37m-win_amd64.whl", hash = "sha256:60b0e9e6dc45683e569ec37c55ac20c582973841927a85f2d8a7d20ee80216ab"}, - {file = "regex-2020.9.27-cp38-cp38-manylinux1_i686.whl", hash = "sha256:088afc8c63e7bd187a3c70a94b9e50ab3f17e1d3f52a32750b5b77dbe99ef5ef"}, - {file = "regex-2020.9.27-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:eaf548d117b6737df379fdd53bdde4f08870e66d7ea653e230477f071f861121"}, - {file = "regex-2020.9.27-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:41bb65f54bba392643557e617316d0d899ed5b4946dccee1cb6696152b29844b"}, - {file = "regex-2020.9.27-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:8d69cef61fa50c8133382e61fd97439de1ae623fe943578e477e76a9d9471637"}, - {file = "regex-2020.9.27-cp38-cp38-win32.whl", hash = "sha256:f2388013e68e750eaa16ccbea62d4130180c26abb1d8e5d584b9baf69672b30f"}, - {file = "regex-2020.9.27-cp38-cp38-win_amd64.whl", hash = "sha256:4318d56bccfe7d43e5addb272406ade7a2274da4b70eb15922a071c58ab0108c"}, - {file = "regex-2020.9.27-cp39-cp39-manylinux1_i686.whl", hash = "sha256:84cada8effefe9a9f53f9b0d2ba9b7b6f5edf8d2155f9fdbe34616e06ececf81"}, - {file = "regex-2020.9.27-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:816064fc915796ea1f26966163f6845de5af78923dfcecf6551e095f00983650"}, - {file = "regex-2020.9.27-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:5d892a4f1c999834eaa3c32bc9e8b976c5825116cde553928c4c8e7e48ebda67"}, - {file = "regex-2020.9.27-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:c9443124c67b1515e4fe0bb0aa18df640965e1030f468a2a5dc2589b26d130ad"}, - {file = "regex-2020.9.27-cp39-cp39-win32.whl", hash = "sha256:49f23ebd5ac073765ecbcf046edc10d63dcab2f4ae2bce160982cb30df0c0302"}, - {file = "regex-2020.9.27-cp39-cp39-win_amd64.whl", hash = "sha256:3d20024a70b97b4f9546696cbf2fd30bae5f42229fbddf8661261b1eaff0deb7"}, - {file = "regex-2020.9.27.tar.gz", hash = "sha256:a6f32aea4260dfe0e55dc9733ea162ea38f0ea86aa7d0f77b15beac5bf7b369d"}, + {file = "regex-2020.11.13-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8b882a78c320478b12ff024e81dc7d43c1462aa4a3341c754ee65d857a521f85"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a63f1a07932c9686d2d416fb295ec2c01ab246e89b4d58e5fa468089cab44b70"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6e4b08c6f8daca7d8f07c8d24e4331ae7953333dbd09c648ed6ebd24db5a10ee"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:bba349276b126947b014e50ab3316c027cac1495992f10e5682dc677b3dfa0c5"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:56e01daca75eae420bce184edd8bb341c8eebb19dd3bce7266332258f9fb9dd7"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:6a8ce43923c518c24a2579fda49f093f1397dad5d18346211e46f134fc624e31"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:1ab79fcb02b930de09c76d024d279686ec5d532eb814fd0ed1e0051eb8bd2daa"}, + {file = "regex-2020.11.13-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:9801c4c1d9ae6a70aeb2128e5b4b68c45d4f0af0d1535500884d644fa9b768c6"}, + {file = "regex-2020.11.13-cp36-cp36m-win32.whl", hash = "sha256:49cae022fa13f09be91b2c880e58e14b6da5d10639ed45ca69b85faf039f7a4e"}, + {file = "regex-2020.11.13-cp36-cp36m-win_amd64.whl", hash = "sha256:749078d1eb89484db5f34b4012092ad14b327944ee7f1c4f74d6279a6e4d1884"}, + {file = "regex-2020.11.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b2f4007bff007c96a173e24dcda236e5e83bde4358a557f9ccf5e014439eae4b"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:38c8fd190db64f513fe4e1baa59fed086ae71fa45083b6936b52d34df8f86a88"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5862975b45d451b6db51c2e654990c1820523a5b07100fc6903e9c86575202a0"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:262c6825b309e6485ec2493ffc7e62a13cf13fb2a8b6d212f72bd53ad34118f1"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:bafb01b4688833e099d79e7efd23f99172f501a15c44f21ea2118681473fdba0"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:e32f5f3d1b1c663af7f9c4c1e72e6ffe9a78c03a31e149259f531e0fed826512"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:3bddc701bdd1efa0d5264d2649588cbfda549b2899dc8d50417e47a82e1387ba"}, + {file = "regex-2020.11.13-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:02951b7dacb123d8ea6da44fe45ddd084aa6777d4b2454fa0da61d569c6fa538"}, + {file = "regex-2020.11.13-cp37-cp37m-win32.whl", hash = "sha256:0d08e71e70c0237883d0bef12cad5145b84c3705e9c6a588b2a9c7080e5af2a4"}, + {file = "regex-2020.11.13-cp37-cp37m-win_amd64.whl", hash = "sha256:1fa7ee9c2a0e30405e21031d07d7ba8617bc590d391adfc2b7f1e8b99f46f444"}, + {file = "regex-2020.11.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:baf378ba6151f6e272824b86a774326f692bc2ef4cc5ce8d5bc76e38c813a55f"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e3faaf10a0d1e8e23a9b51d1900b72e1635c2d5b0e1bea1c18022486a8e2e52d"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:2a11a3e90bd9901d70a5b31d7dd85114755a581a5da3fc996abfefa48aee78af"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:d1ebb090a426db66dd80df8ca85adc4abfcbad8a7c2e9a5ec7513ede522e0a8f"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:b2b1a5ddae3677d89b686e5c625fc5547c6e492bd755b520de5332773a8af06b"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:2c99e97d388cd0a8d30f7c514d67887d8021541b875baf09791a3baad48bb4f8"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:c084582d4215593f2f1d28b65d2a2f3aceff8342aa85afd7be23a9cad74a0de5"}, + {file = "regex-2020.11.13-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:a3d748383762e56337c39ab35c6ed4deb88df5326f97a38946ddd19028ecce6b"}, + {file = "regex-2020.11.13-cp38-cp38-win32.whl", hash = "sha256:7913bd25f4ab274ba37bc97ad0e21c31004224ccb02765ad984eef43e04acc6c"}, + {file = "regex-2020.11.13-cp38-cp38-win_amd64.whl", hash = "sha256:6c54ce4b5d61a7129bad5c5dc279e222afd00e721bf92f9ef09e4fae28755683"}, + {file = "regex-2020.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1862a9d9194fae76a7aaf0150d5f2a8ec1da89e8b55890b1786b8f88a0f619dc"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux1_i686.whl", hash = "sha256:4902e6aa086cbb224241adbc2f06235927d5cdacffb2425c73e6570e8d862364"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7a25fcbeae08f96a754b45bdc050e1fb94b95cab046bf56b016c25e9ab127b3e"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:d2d8ce12b7c12c87e41123997ebaf1a5767a5be3ec545f64675388970f415e2e"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:f7d29a6fc4760300f86ae329e3b6ca28ea9c20823df123a2ea8693e967b29917"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:717881211f46de3ab130b58ec0908267961fadc06e44f974466d1887f865bd5b"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:3128e30d83f2e70b0bed9b2a34e92707d0877e460b402faca908c6667092ada9"}, + {file = "regex-2020.11.13-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:8f6a2229e8ad946e36815f2a03386bb8353d4bde368fdf8ca5f0cb97264d3b5c"}, + {file = "regex-2020.11.13-cp39-cp39-win32.whl", hash = "sha256:f8f295db00ef5f8bae530fc39af0b40486ca6068733fb860b42115052206466f"}, + {file = "regex-2020.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:a15f64ae3a027b64496a71ab1f722355e570c3fac5ba2801cafce846bf5af01d"}, + {file = "regex-2020.11.13.tar.gz", hash = "sha256:83d6b356e116ca119db8e7c6fc2983289d87b27b3fac238cfe5dca529d884562"}, ] requests = [ - {file = "requests-2.24.0-py2.py3-none-any.whl", hash = "sha256:fe75cc94a9443b9246fc7049224f75604b113c36acb93f87b80ed42c44cbb898"}, - {file = "requests-2.24.0.tar.gz", hash = "sha256:b3559a131db72c33ee969480840fff4bb6dd111de7dd27c8ee1f820f4f00231b"}, + {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, + {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, ] rfc3986 = [ {file = "rfc3986-1.4.0-py2.py3-none-any.whl", hash = "sha256:af9147e9aceda37c91a05f4deb128d4b4b49d6b199775fd2d2927768abdc8f50"}, {file = "rfc3986-1.4.0.tar.gz", hash = "sha256:112398da31a3344dc25dbf477d8df6cb34f9278a94fee2625d89e4514be8bb9d"}, ] safety = [ - {file = "safety-1.10.1-py2.py3-none-any.whl", hash = "sha256:6e86b4bd47ea6e8f623045bd3687342fb5ac402fb37147fca82fd5a752ec3afc"}, - {file = "safety-1.10.1.tar.gz", hash = "sha256:f2ab09596ebcbb4012fb7345d2dbda28319c8f3c2731ef6e27ba206b279c13b2"}, + {file = "safety-1.10.2.post1-py2.py3-none-any.whl", hash = "sha256:6f50edff1c5162d096cacd9557406b32c021c77fe8d2229750eeff22a3e10dfe"}, + {file = "safety-1.10.2.post1.tar.gz", hash = "sha256:1d8f904c7df7c99f094154a6d2c3ae9703fd2fa58914bd80e005e860a9f4045c"}, ] shellingham = [ {file = "shellingham-1.3.2-py2.py3-none-any.whl", hash = "sha256:7f6206ae169dc1a03af8a138681b3f962ae61cc93ade84d0585cca3aaf770044"}, @@ -1014,8 +1057,8 @@ six = [ {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, ] sniffio = [ - {file = "sniffio-1.1.0-py3-none-any.whl", hash = "sha256:20ed6d5b46f8ae136d00b9dcb807615d83ed82ceea6b2058cecb696765246da5"}, - {file = "sniffio-1.1.0.tar.gz", hash = "sha256:8e3810100f69fe0edd463d02ad407112542a11ffdc29f67db2bf3771afb87a21"}, + {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, + {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, ] stringcase = [ {file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"}, @@ -1025,40 +1068,40 @@ taskipy = [ {file = "taskipy-1.6.0.tar.gz", hash = "sha256:ec4d1f2208ae24218950e3a2812e4e8b4397b1f65a6ad7e2b1240b702042fa3e"}, ] toml = [ - {file = "toml-0.10.1-py2.py3-none-any.whl", hash = "sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"}, - {file = "toml-0.10.1.tar.gz", hash = "sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f"}, + {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, + {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, ] typed-ast = [ - {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"}, - {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"}, - {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"}, - {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"}, - {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"}, - {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"}, - {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"}, - {file = "typed_ast-1.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:fcf135e17cc74dbfbc05894ebca928ffeb23d9790b3167a674921db19082401f"}, - {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"}, - {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"}, - {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"}, - {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"}, - {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"}, - {file = "typed_ast-1.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f208eb7aff048f6bea9586e61af041ddf7f9ade7caed625742af423f6bae3298"}, - {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"}, - {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"}, - {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"}, - {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"}, - {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"}, - {file = "typed_ast-1.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7e4c9d7658aaa1fc80018593abdf8598bf91325af6af5cce4ce7c73bc45ea53d"}, - {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"}, - {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"}, - {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"}, - {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:92c325624e304ebf0e025d1224b77dd4e6393f18aab8d829b5b7e04afe9b7a2c"}, - {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:d648b8e3bf2fe648745c8ffcee3db3ff903d0817a01a12dd6a6ea7a8f4889072"}, - {file = "typed_ast-1.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:fac11badff8313e23717f3dada86a15389d0708275bddf766cca67a84ead3e91"}, - {file = "typed_ast-1.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:0d8110d78a5736e16e26213114a38ca35cb15b6515d535413b090bd50951556d"}, - {file = "typed_ast-1.4.1-cp39-cp39-win32.whl", hash = "sha256:b52ccf7cfe4ce2a1064b18594381bccf4179c2ecf7f513134ec2f993dd4ab395"}, - {file = "typed_ast-1.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:3742b32cf1c6ef124d57f95be609c473d7ec4c14d0090e5a5e05a15269fb4d0c"}, - {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"}, + {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"}, + {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"}, + {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"}, + {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"}, + {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"}, + {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"}, + {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"}, + {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"}, + {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"}, + {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"}, + {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"}, + {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"}, + {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"}, + {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"}, + {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"}, + {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"}, + {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"}, + {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"}, + {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"}, + {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"}, + {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"}, + {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"}, + {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"}, + {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"}, + {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"}, + {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"}, + {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"}, + {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"}, + {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"}, + {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"}, ] typer = [ {file = "typer-0.3.2-py3-none-any.whl", hash = "sha256:ba58b920ce851b12a2d790143009fa00ac1d05b3ff3257061ff69dbdfc3d161b"}, @@ -1074,10 +1117,10 @@ typing-extensions = [ {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, ] urllib3 = [ - {file = "urllib3-1.25.10-py2.py3-none-any.whl", hash = "sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"}, - {file = "urllib3-1.25.10.tar.gz", hash = "sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a"}, + {file = "urllib3-1.26.2-py2.py3-none-any.whl", hash = "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"}, + {file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"}, ] zipp = [ - {file = "zipp-3.3.0-py3-none-any.whl", hash = "sha256:eed8ec0b8d1416b2ca33516a37a08892442f3954dee131e92cfd92d8fe3e7066"}, - {file = "zipp-3.3.0.tar.gz", hash = "sha256:64ad89efee774d1897a58607895d80789c59778ea02185dd846ac38394a8642b"}, + {file = "zipp-3.4.0-py3-none-any.whl", hash = "sha256:102c24ef8f171fd729d46599845e95c7ab894a4cf45f5de11a44cc7444fb1108"}, + {file = "zipp-3.4.0.tar.gz", hash = "sha256:ed5eee1974372595f9e416cc7bbeeb12335201d8081ca8a0743c954d4446e5cb"}, ] From cbd81369979435784d019bf61fe2d391da8389d9 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 09:07:45 -0500 Subject: [PATCH 05/19] Add task for unit tests --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 2cecc045d..ef21b8d32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,6 +58,7 @@ isort .\ && mypy openapi_python_client\ && pytest --cov openapi_python_client tests --cov-report=term-missing\ """ +unit = "pytest --cov openapi_python_client tests --cov-report=term-missing" regen = "python -m end_to_end_tests.regen_golden_record" regen_custom = "python -m end_to_end_tests.regen_golden_record custom" e2e = "pytest openapi_python_client end_to_end_tests/test_end_to_end.py" From aac9b3a724dd595e803f83138cb8b93774625bd5 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 09:07:49 -0500 Subject: [PATCH 06/19] Fix remaining unit tests --- openapi_python_client/parser/properties/__init__.py | 4 ++-- tests/test_parser/test_properties/test_model_property.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 6138af6af..f5900c35f 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -171,14 +171,14 @@ def get_type_string(self, no_optional: bool = False, query_parameter: bool = Fal type_string = self.get_base_type_string() if no_optional: return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" if not self.required: if query_parameter: # For query parameters, None has the same meaning as Unset type_string = f"Union[Unset, None, {self._get_inner_prop_string()}]" else: type_string = f"Union[Unset, {self._get_inner_prop_string()}]" + if self.nullable: + type_string = f"Optional[{type_string}]" return type_string def get_imports(self, *, prefix: str) -> Set[str]: diff --git a/tests/test_parser/test_properties/test_model_property.py b/tests/test_parser/test_properties/test_model_property.py index 1024ef179..6e319b7cc 100644 --- a/tests/test_parser/test_properties/test_model_property.py +++ b/tests/test_parser/test_properties/test_model_property.py @@ -4,9 +4,9 @@ @pytest.mark.parametrize( "no_optional,nullable,required,expected", [ - (False, False, False, "Union[MyClass, Unset]"), + (False, False, False, "Union[Unset, MyClass]"), (False, False, True, "MyClass"), - (False, True, False, "Union[Optional[MyClass], Unset]"), + (False, True, False, "Union[Unset, Optional[MyClass]]"), (False, True, True, "Optional[MyClass]"), (True, False, False, "MyClass"), (True, False, True, "MyClass"), From 233f73e2ef79d5994f06fd8b93b1ba3685dd5c2d Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 09:33:29 -0500 Subject: [PATCH 07/19] Collapse Optional and Union types --- .../custom_e2e/models/a_model.py | 2 +- .../my_test_api_client/models/a_model.py | 2 +- .../parser/properties/__init__.py | 28 +++-- .../parser/properties/property.py | 21 ++-- .../test_parser/test_properties/test_init.py | 102 ++++++++++++++++-- .../test_properties/test_model_property.py | 2 +- 6 files changed, 131 insertions(+), 26 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index 25bceb17c..452eb08fa 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -23,7 +23,7 @@ class AModel: required_nullable: Optional[str] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET - not_required_nullable: Union[Unset, Optional[str]] = UNSET + not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET def to_dict(self) -> Dict[str, Any]: diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index 25bceb17c..452eb08fa 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -23,7 +23,7 @@ class AModel: required_nullable: Optional[str] nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET attr_1_leading_digit: Union[Unset, str] = UNSET - not_required_nullable: Union[Unset, Optional[str]] = UNSET + not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET def to_dict(self) -> Dict[str, Any]: diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index f5900c35f..2399d8b75 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -167,19 +167,29 @@ def get_base_type_string(self) -> str: return f"Union[{self._get_inner_prop_string()}]" def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: - """ Get a string representation of type that should be used when declaring this property """ + """ + Get a string representation of type that should be used when declaring this property. + + This implementation differs slightly from `Property.get_type_string` in order to collapse + nested union types. + """ type_string = self.get_base_type_string() if no_optional: return type_string - if not self.required: - if query_parameter: - # For query parameters, None has the same meaning as Unset - type_string = f"Union[Unset, None, {self._get_inner_prop_string()}]" + if self.required: + if self.nullable: + return f"Union[None, {self._get_inner_prop_string()}]" + else: + return type_string + else: + if self.nullable: + return f"Union[Unset, None, {self._get_inner_prop_string()}]" else: - type_string = f"Union[Unset, {self._get_inner_prop_string()}]" - if self.nullable: - type_string = f"Optional[{type_string}]" - return type_string + if query_parameter: + # For query parameters, None has the same meaning as Unset + return f"Union[Unset, None, {self._get_inner_prop_string()}]" + else: + return f"Union[Unset, {self._get_inner_prop_string()}]" def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index a7667f7aa..03d55ccf3 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -46,15 +46,20 @@ def get_type_string(self, no_optional: bool = False, query_parameter: bool = Fal type_string = self.get_base_type_string() if no_optional: return type_string - if self.nullable: - type_string = f"Optional[{type_string}]" - if not self.required: - if query_parameter: - # For query parameters, None has the same meaning as Unset - type_string = f"Union[Unset, None, {type_string}]" + if self.required: + if self.nullable: + return f"Optional[{type_string}]" + else: + return type_string + else: + if self.nullable: + return f"Union[Unset, None, {type_string}]" else: - type_string = f"Union[Unset, {type_string}]" - return type_string + if query_parameter: + # For query parameters, None has the same meaning as Unset + return f"Union[Unset, None, {type_string}]" + else: + return f"Union[Unset, {type_string}]" def get_instance_type_string(self) -> str: """Get a string representation of runtime type that should be used for `isinstance` checks""" diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index a7ea05881..3a66f6e6d 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -31,13 +31,35 @@ def test_get_type_string(self, mocker): assert p.get_type_string(no_optional=True) == base_type_string p = Property(name="test", required=False, default=None, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string p = Property(name="test", required=False, default=None, nullable=False) assert p.get_type_string() == f"Union[Unset, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string + def test_get_type_string_query_parameter(self, mocker): + from openapi_python_client.parser.properties import Property + + mocker.patch.object(Property, "_type_string", "TestType") + p = Property(name="test", required=True, default=None, nullable=False) + + base_type_string = f"TestType" + + assert p.get_type_string(query_parameter=True) == base_type_string + + p = Property(name="test", required=True, default=None, nullable=True) + assert p.get_type_string(query_parameter=True) == f"Optional[{base_type_string}]" + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + + p = Property(name="test", required=False, default=None, nullable=True) + assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, {base_type_string}]" + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + + p = Property(name="test", required=False, default=None, nullable=False) + assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, {base_type_string}]" + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + def test_to_string(self, mocker): from openapi_python_client.parser.properties import Property @@ -56,6 +78,24 @@ def test_to_string(self, mocker): p = Property(name=name, required=True, default="TEST", nullable=False) assert p.to_string() == f"{name}: {get_type_string()} = TEST" + def test_to_string_query_parameter(self, mocker): + from openapi_python_client.parser.properties import Property + + name = "test" + get_type_string = mocker.patch.object(Property, "get_type_string") + p = Property(name=name, required=True, default=None, nullable=False) + + assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" + + p = Property(name=name, required=False, default=None, nullable=False) + assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = None" + + p = Property(name=name, required=True, default=None, nullable=False) + assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" + + p = Property(name=name, required=True, default="TEST", nullable=False) + assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = TEST" + def test_get_imports(self): from openapi_python_client.parser.properties import Property @@ -87,7 +127,7 @@ def test_get_type_string(self): assert p.get_type_string() == f"Optional[{base_type_string}]" p = StringProperty(name="test", required=False, default=None, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" p = StringProperty(name="test", required=False, default=None, nullable=False) assert p.get_type_string() == f"Union[Unset, {base_type_string}]" @@ -202,7 +242,7 @@ def test_get_type_string(self, mocker): assert p.get_type_string(no_optional=True) == base_type_string p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=True) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string p = ListProperty(name="test", required=False, default=None, inner_property=inner_property, nullable=False) @@ -268,7 +308,7 @@ def test_get_type_string(self, mocker): inner_properties=[inner_property_1, inner_property_2], nullable=True, ) - assert p.get_type_string() == f"Optional[{base_type_string}]" + assert p.get_type_string() == f"Union[None, inner_type_string_1, inner_type_string_2]" assert p.get_type_string(no_optional=True) == base_type_string base_type_string_with_unset = f"Union[Unset, inner_type_string_1, inner_type_string_2]" @@ -279,7 +319,7 @@ def test_get_type_string(self, mocker): inner_properties=[inner_property_1, inner_property_2], nullable=True, ) - assert p.get_type_string() == f"Optional[{base_type_string_with_unset}]" + assert p.get_type_string() == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" assert p.get_type_string(no_optional=True) == base_type_string p = UnionProperty( @@ -292,6 +332,56 @@ def test_get_type_string(self, mocker): assert p.get_type_string() == base_type_string_with_unset assert p.get_type_string(no_optional=True) == base_type_string + def test_get_type_string_query_parameter(self, mocker): + from openapi_python_client.parser.properties import UnionProperty + + inner_property_1 = mocker.MagicMock() + inner_property_1.get_type_string.return_value = "inner_type_string_1" + inner_property_2 = mocker.MagicMock() + inner_property_2.get_type_string.return_value = "inner_type_string_2" + p = UnionProperty( + name="test", + required=True, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=False, + ) + + base_type_string = f"Union[inner_type_string_1, inner_type_string_2]" + + assert p.get_type_string(query_parameter=True) == base_type_string + + p = UnionProperty( + name="test", + required=True, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=True, + ) + assert p.get_type_string(query_parameter=True) == f"Union[None, inner_type_string_1, inner_type_string_2]" + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + + base_type_string_with_unset = f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" + p = UnionProperty( + name="test", + required=False, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=True, + ) + assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + + p = UnionProperty( + name="test", + required=False, + default=None, + inner_properties=[inner_property_1, inner_property_2], + nullable=False, + ) + assert p.get_type_string(query_parameter=True) == base_type_string_with_unset + assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty @@ -389,7 +479,7 @@ def test_get_type_string(self, mocker): reference=fake_reference, value_type=str, ) - assert p.get_type_string() == f"Union[Unset, Optional[{base_type_string}]]" + assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" assert p.get_type_string(no_optional=True) == base_type_string p = properties.EnumProperty( diff --git a/tests/test_parser/test_properties/test_model_property.py b/tests/test_parser/test_properties/test_model_property.py index 6e319b7cc..410112666 100644 --- a/tests/test_parser/test_properties/test_model_property.py +++ b/tests/test_parser/test_properties/test_model_property.py @@ -6,7 +6,7 @@ [ (False, False, False, "Union[Unset, MyClass]"), (False, False, True, "MyClass"), - (False, True, False, "Union[Unset, Optional[MyClass]]"), + (False, True, False, "Union[Unset, None, MyClass]"), (False, True, True, "Optional[MyClass]"), (True, False, False, "MyClass"), (True, False, True, "MyClass"), From 0f2706dd992f1b9f39fed448e5eed38047d20571 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 13 Jan 2021 09:35:32 -0500 Subject: [PATCH 08/19] Run black --- openapi_python_client/parser/properties/__init__.py | 2 +- tests/test_parser/test_properties/test_init.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 2399d8b75..8da587b1e 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -169,7 +169,7 @@ def get_base_type_string(self) -> str: def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property. - + This implementation differs slightly from `Property.get_type_string` in order to collapse nested union types. """ diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 3a66f6e6d..67d6c80ba 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -369,7 +369,9 @@ def test_get_type_string_query_parameter(self, mocker): inner_properties=[inner_property_1, inner_property_2], nullable=True, ) - assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" + assert ( + p.get_type_string(query_parameter=True) == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" + ) assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string p = UnionProperty( From 6a403e80162f7faedce03467f7ad5dce70a2ad15 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 19 Jan 2021 17:15:39 -0500 Subject: [PATCH 09/19] Apply suggestions from code review Co-authored-by: Dylan Anthony <43723790+dbanty@users.noreply.github.com> --- openapi_python_client/parser/properties/property.py | 5 +---- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 03d55ccf3..80390a5ec 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -93,10 +93,7 @@ def to_string(self, query_parameter: bool = False) -> str: if self.default is not None: default = self.default elif not self.required: - if query_parameter: - default = "None" - else: - default = "UNSET" + default = "UNSET" else: default = None diff --git a/pyproject.toml b/pyproject.toml index ef21b8d32..4be8d93db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ isort .\ && flake8 openapi_python_client\ && safety check --bare\ && mypy openapi_python_client\ - && pytest --cov openapi_python_client tests --cov-report=term-missing\ + && task unit\ """ unit = "pytest --cov openapi_python_client tests --cov-report=term-missing" regen = "python -m end_to_end_tests.regen_golden_record" From d1b33b2b2a64795467bd8fc27ae60aa1022dda80 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 19 Jan 2021 17:17:35 -0500 Subject: [PATCH 10/19] Fix tests --- end_to_end_tests/golden-record/.gitignore | 23 -- end_to_end_tests/golden-record/README.md | 67 ----- .../my_test_api_client/__init__.py | 2 - .../my_test_api_client/api/__init__.py | 1 - .../my_test_api_client/api/tests/__init__.py | 0 .../api/tests/defaults_tests_defaults_post.py | 250 ------------------ .../api/tests/get_basic_list_of_booleans.py | 92 ------- .../api/tests/get_basic_list_of_floats.py | 92 ------- .../api/tests/get_basic_list_of_integers.py | 92 ------- .../api/tests/get_basic_list_of_strings.py | 92 ------- .../api/tests/get_user_list.py | 140 ---------- .../api/tests/int_enum_tests_int_enum_post.py | 114 -------- .../tests/json_body_tests_json_body_post.py | 110 -------- .../no_response_tests_no_response_get.py | 60 ----- .../octet_stream_tests_octet_stream_get.py | 93 ------- ...tional_value_tests_optional_query_param.py | 115 -------- .../api/tests/test_inline_objects.py | 106 -------- ...d_content_tests_unsupported_content_get.py | 60 ----- .../tests/upload_file_tests_upload_post.py | 120 --------- .../my_test_api_client/client.py | 46 ---- .../my_test_api_client/models/__init__.py | 22 -- .../my_test_api_client/models/a_model.py | 142 ---------- .../my_test_api_client/models/an_enum.py | 9 - .../my_test_api_client/models/an_int_enum.py | 10 - .../body_upload_file_tests_upload_post.py | 38 --- .../models/different_enum.py | 9 - .../models/free_form_model.py | 44 --- .../models/http_validation_error.py | 47 ---- ...odel_with_additional_properties_inlined.py | 67 ----- ..._properties_inlined_additional_property.py | 54 ---- .../model_with_additional_properties_refed.py | 54 ---- .../models/model_with_any_json_properties.py | 90 ------- ...any_json_properties_additional_property.py | 44 --- ...el_with_primitive_additional_properties.py | 64 ----- ...ive_additional_properties_a_date_holder.py | 54 ---- .../models/model_with_union_property.py | 68 ----- .../models/test_inline_objects_json_body.py | 35 --- .../test_inline_objects_response_200.py | 35 --- .../models/validation_error.py | 48 ---- .../golden-record/my_test_api_client/py.typed | 1 - .../golden-record/my_test_api_client/types.py | 41 --- end_to_end_tests/golden-record/pyproject.toml | 41 --- .../test_parser/test_properties/test_init.py | 2 +- 43 files changed, 1 insertion(+), 2693 deletions(-) delete mode 100644 end_to_end_tests/golden-record/.gitignore delete mode 100644 end_to_end_tests/golden-record/README.md delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/__init__.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/__init__.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/client.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/__init__.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/a_model.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/py.typed delete mode 100644 end_to_end_tests/golden-record/my_test_api_client/types.py delete mode 100644 end_to_end_tests/golden-record/pyproject.toml diff --git a/end_to_end_tests/golden-record/.gitignore b/end_to_end_tests/golden-record/.gitignore deleted file mode 100644 index ed29cb977..000000000 --- a/end_to_end_tests/golden-record/.gitignore +++ /dev/null @@ -1,23 +0,0 @@ -__pycache__/ -build/ -dist/ -*.egg-info/ -.pytest_cache/ - -# pyenv -.python-version - -# Environments -.env -.venv - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# JetBrains -.idea/ - -/coverage.xml -/.coverage \ No newline at end of file diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md deleted file mode 100644 index 1f9c3a6ee..000000000 --- a/end_to_end_tests/golden-record/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# my-test-api-client -A client library for accessing My Test API - -## Usage -First, create a client: - -```python -from my_test_api_client import Client - -client = Client(base_url="https://api.example.com") -``` - -If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead: - -```python -from my_test_api_client import AuthenticatedClient - -client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken") -``` - -Now call your endpoint and use your models: - -```python -from my_test_api_client.models import MyDataModel -from my_test_api_client.api.my_tag import get_my_data_model -from my_test_api_client.types import Response - -my_data: MyDataModel = get_my_data_model.sync(client=client) -# or if you need more info (e.g. status_code) -response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) -``` - -Or do the same thing with an async version: - -```python -from my_test_api_client.models import MyDataModel -from my_test_api_client.async_api.my_tag import get_my_data_model -from my_test_api_client.types import Response - -my_data: MyDataModel = await get_my_data_model.asyncio(client=client) -response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) -``` - -Things to know: -1. Every path/method combo becomes a Python module with four functions: - 1. `sync`: Blocking request that returns parsed data (if successful) or `None` - 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. - 1. `asyncio`: Like `sync` but the async instead of blocking - 1. `asyncio_detailed`: Like `sync_detailed` by async instead of blocking - -1. All path/query params, and bodies become method arguments. -1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) -1. Any endpoint which did not have a tag will be in `my_test_api_client.api.default` - -## Building / publishing this Client -This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics: -1. Update the metadata in pyproject.toml (e.g. authors, version) -1. If you're using a private repository, configure it with Poetry - 1. `poetry config repositories. ` - 1. `poetry config http-basic. ` -1. Publish the client with `poetry publish --build -r ` or, if for public PyPI, just `poetry publish --build` - -If you want to install this client into another project without publishing it (e.g. for development) then: -1. If that project **is using Poetry**, you can simply do `poetry add ` from that project -1. If that project is not using Poetry: - 1. Build a wheel with `poetry build -f wheel` - 1. Install that wheel from the other project `pip install ` \ No newline at end of file diff --git a/end_to_end_tests/golden-record/my_test_api_client/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/__init__.py deleted file mode 100644 index 0f240c245..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -""" A client library for accessing My Test API """ -from .client import AuthenticatedClient, Client diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py deleted file mode 100644 index dc035f4ce..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py +++ /dev/null @@ -1 +0,0 @@ -""" Contains methods for accessing the API """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py deleted file mode 100644 index 77ee6cce1..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ /dev/null @@ -1,250 +0,0 @@ -import datetime -from typing import Any, Dict, List, Optional, Union - -import httpx -from dateutil.parser import isoparse - -from ...client import Client -from ...models.an_enum import AnEnum -from ...models.http_validation_error import HTTPValidationError -from ...types import UNSET, Response, Unset - - -def _get_kwargs( - *, - client: Client, - string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, None, float] = 3.14, - int_prop: Union[Unset, None, int] = 7, - boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, - union_prop: Union[Unset, None, float, str] = "not a float", - union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, -) -> Dict[str, Any]: - url = "{}/tests/defaults".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset) and datetime_prop is not None: - json_datetime_prop = datetime_prop.isoformat() - - json_date_prop: Union[Unset, str] = UNSET - if not isinstance(date_prop, Unset) and date_prop is not None: - json_date_prop = date_prop.isoformat() - - json_list_prop: Union[Unset, List[Any]] = UNSET - if not isinstance(list_prop, Unset) and list_prop is not None: - json_list_prop = [] - for list_prop_item_data in list_prop: - list_prop_item = list_prop_item_data.value - - json_list_prop.append(list_prop_item) - - json_union_prop: Union[Unset, float, str] - if isinstance(union_prop, Unset) or union_prop is None: - json_union_prop = UNSET - else: - json_union_prop = union_prop - - json_union_prop_with_ref: Union[Unset, float, AnEnum] - if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: - json_union_prop_with_ref = UNSET - elif isinstance(union_prop_with_ref, AnEnum): - json_union_prop_with_ref = UNSET - if not isinstance(union_prop_with_ref, Unset): - json_union_prop_with_ref = union_prop_with_ref - - else: - json_union_prop_with_ref = union_prop_with_ref - - json_enum_prop: Union[Unset, AnEnum] = UNSET - if not isinstance(enum_prop, Unset) and enum_prop is not None: - json_enum_prop = enum_prop - - params: Dict[str, Any] = {} - if string_prop is not UNSET and string_prop is not None: - params["string_prop"] = string_prop - if datetime_prop is not UNSET and datetime_prop is not None: - params["datetime_prop"] = json_datetime_prop - if date_prop is not UNSET and date_prop is not None: - params["date_prop"] = json_date_prop - if float_prop is not UNSET and float_prop is not None: - params["float_prop"] = float_prop - if int_prop is not UNSET and int_prop is not None: - params["int_prop"] = int_prop - if boolean_prop is not UNSET and boolean_prop is not None: - params["boolean_prop"] = boolean_prop - if list_prop is not UNSET and list_prop is not None: - params["list_prop"] = json_list_prop - if union_prop is not UNSET and union_prop is not None: - params["union_prop"] = json_union_prop - if union_prop_with_ref is not UNSET and union_prop_with_ref is not None: - params["union_prop_with_ref"] = json_union_prop_with_ref - if enum_prop is not UNSET and enum_prop is not None: - params["enum_prop"] = json_enum_prop - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "params": params, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: - if response.status_code == 200: - response_200 = None - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, None, float] = 3.14, - int_prop: Union[Unset, None, int] = 7, - boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, - union_prop: Union[Unset, None, float, str] = "not a float", - union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - string_prop=string_prop, - datetime_prop=datetime_prop, - date_prop=date_prop, - float_prop=float_prop, - int_prop=int_prop, - boolean_prop=boolean_prop, - list_prop=list_prop, - union_prop=union_prop, - union_prop_with_ref=union_prop_with_ref, - enum_prop=enum_prop, - ) - - response = httpx.post( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, None, float] = 3.14, - int_prop: Union[Unset, None, int] = 7, - boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, - union_prop: Union[Unset, None, float, str] = "not a float", - union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, -) -> Optional[Union[None, HTTPValidationError]]: - """ """ - - return sync_detailed( - client=client, - string_prop=string_prop, - datetime_prop=datetime_prop, - date_prop=date_prop, - float_prop=float_prop, - int_prop=int_prop, - boolean_prop=boolean_prop, - list_prop=list_prop, - union_prop=union_prop, - union_prop_with_ref=union_prop_with_ref, - enum_prop=enum_prop, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, None, float] = 3.14, - int_prop: Union[Unset, None, int] = 7, - boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, - union_prop: Union[Unset, None, float, str] = "not a float", - union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - string_prop=string_prop, - datetime_prop=datetime_prop, - date_prop=date_prop, - float_prop=float_prop, - int_prop=int_prop, - boolean_prop=boolean_prop, - list_prop=list_prop, - union_prop=union_prop, - union_prop_with_ref=union_prop_with_ref, - enum_prop=enum_prop, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.post(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), - date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), - float_prop: Union[Unset, None, float] = 3.14, - int_prop: Union[Unset, None, int] = 7, - boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, - union_prop: Union[Unset, None, float, str] = "not a float", - union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, -) -> Optional[Union[None, HTTPValidationError]]: - """ """ - - return ( - await asyncio_detailed( - client=client, - string_prop=string_prop, - datetime_prop=datetime_prop, - date_prop=date_prop, - float_prop=float_prop, - int_prop=int_prop, - boolean_prop=boolean_prop, - list_prop=list_prop, - union_prop=union_prop, - union_prop_with_ref=union_prop_with_ref, - enum_prop=enum_prop, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py deleted file mode 100644 index eeedd5337..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Any, Dict, List, Optional, cast - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/booleans".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[List[bool]]: - if response.status_code == 200: - response_200 = cast(List[bool], response.json()) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[List[bool]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[List[bool]]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, -) -> Optional[List[bool]]: - """ Get a list of booleans """ - - return sync_detailed( - client=client, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[List[bool]]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, -) -> Optional[List[bool]]: - """ Get a list of booleans """ - - return ( - await asyncio_detailed( - client=client, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py deleted file mode 100644 index 84735b823..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Any, Dict, List, Optional, cast - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/floats".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[List[float]]: - if response.status_code == 200: - response_200 = cast(List[float], response.json()) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[List[float]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[List[float]]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, -) -> Optional[List[float]]: - """ Get a list of floats """ - - return sync_detailed( - client=client, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[List[float]]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, -) -> Optional[List[float]]: - """ Get a list of floats """ - - return ( - await asyncio_detailed( - client=client, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py deleted file mode 100644 index 56197de7c..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Any, Dict, List, Optional, cast - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/integers".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[List[int]]: - if response.status_code == 200: - response_200 = cast(List[int], response.json()) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[List[int]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[List[int]]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, -) -> Optional[List[int]]: - """ Get a list of integers """ - - return sync_detailed( - client=client, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[List[int]]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, -) -> Optional[List[int]]: - """ Get a list of integers """ - - return ( - await asyncio_detailed( - client=client, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py deleted file mode 100644 index d75f452fb..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py +++ /dev/null @@ -1,92 +0,0 @@ -from typing import Any, Dict, List, Optional, cast - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/basic_lists/strings".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[List[str]]: - if response.status_code == 200: - response_200 = cast(List[str], response.json()) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[List[str]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[List[str]]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, -) -> Optional[List[str]]: - """ Get a list of strings """ - - return sync_detailed( - client=client, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[List[str]]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, -) -> Optional[List[str]]: - """ Get a list of strings """ - - return ( - await asyncio_detailed( - client=client, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py deleted file mode 100644 index e43c92d9b..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ /dev/null @@ -1,140 +0,0 @@ -import datetime -from typing import Any, Dict, List, Optional, Union - -import httpx - -from ...client import Client -from ...models.a_model import AModel -from ...models.an_enum import AnEnum -from ...models.http_validation_error import HTTPValidationError -from ...types import Response - - -def _get_kwargs( - *, - client: Client, - an_enum_value: List[AnEnum], - some_date: Union[datetime.date, datetime.datetime], -) -> Dict[str, Any]: - url = "{}/tests/".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_an_enum_value = [] - for an_enum_value_item_data in an_enum_value: - an_enum_value_item = an_enum_value_item_data.value - - json_an_enum_value.append(an_enum_value_item) - - if isinstance(some_date, datetime.date): - json_some_date = some_date.isoformat() - else: - json_some_date = some_date.isoformat() - - params: Dict[str, Any] = { - "an_enum_value": json_an_enum_value, - "some_date": json_some_date, - } - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "params": params, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[List[AModel], HTTPValidationError]]: - if response.status_code == 200: - response_200 = [] - _response_200 = response.json() - for response_200_item_data in _response_200: - response_200_item = AModel.from_dict(response_200_item_data) - - response_200.append(response_200_item) - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[List[AModel], HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - an_enum_value: List[AnEnum], - some_date: Union[datetime.date, datetime.datetime], -) -> Response[Union[List[AModel], HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - an_enum_value=an_enum_value, - some_date=some_date, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - an_enum_value: List[AnEnum], - some_date: Union[datetime.date, datetime.datetime], -) -> Optional[Union[List[AModel], HTTPValidationError]]: - """ Get a list of things """ - - return sync_detailed( - client=client, - an_enum_value=an_enum_value, - some_date=some_date, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - an_enum_value: List[AnEnum], - some_date: Union[datetime.date, datetime.datetime], -) -> Response[Union[List[AModel], HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - an_enum_value=an_enum_value, - some_date=some_date, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - an_enum_value: List[AnEnum], - some_date: Union[datetime.date, datetime.datetime], -) -> Optional[Union[List[AModel], HTTPValidationError]]: - """ Get a list of things """ - - return ( - await asyncio_detailed( - client=client, - an_enum_value=an_enum_value, - some_date=some_date, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py deleted file mode 100644 index cace678f1..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py +++ /dev/null @@ -1,114 +0,0 @@ -from typing import Any, Dict, Optional, Union - -import httpx - -from ...client import Client -from ...models.an_int_enum import AnIntEnum -from ...models.http_validation_error import HTTPValidationError -from ...types import Response - - -def _get_kwargs( - *, - client: Client, - int_enum: AnIntEnum, -) -> Dict[str, Any]: - url = "{}/tests/int_enum".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_int_enum = int_enum.value - - params: Dict[str, Any] = { - "int_enum": json_int_enum, - } - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "params": params, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: - if response.status_code == 200: - response_200 = None - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - int_enum: AnIntEnum, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - int_enum=int_enum, - ) - - response = httpx.post( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - int_enum: AnIntEnum, -) -> Optional[Union[None, HTTPValidationError]]: - """ """ - - return sync_detailed( - client=client, - int_enum=int_enum, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - int_enum: AnIntEnum, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - int_enum=int_enum, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.post(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - int_enum: AnIntEnum, -) -> Optional[Union[None, HTTPValidationError]]: - """ """ - - return ( - await asyncio_detailed( - client=client, - int_enum=int_enum, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py deleted file mode 100644 index 408f2dab1..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py +++ /dev/null @@ -1,110 +0,0 @@ -from typing import Any, Dict, Optional, Union - -import httpx - -from ...client import Client -from ...models.a_model import AModel -from ...models.http_validation_error import HTTPValidationError -from ...types import Response - - -def _get_kwargs( - *, - client: Client, - json_body: AModel, -) -> Dict[str, Any]: - url = "{}/tests/json_body".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_json_body = json_body.to_dict() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "json": json_json_body, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: - if response.status_code == 200: - response_200 = None - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - json_body: AModel, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - json_body=json_body, - ) - - response = httpx.post( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - json_body: AModel, -) -> Optional[Union[None, HTTPValidationError]]: - """ Try sending a JSON body """ - - return sync_detailed( - client=client, - json_body=json_body, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - json_body: AModel, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - json_body=json_body, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.post(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - json_body: AModel, -) -> Optional[Union[None, HTTPValidationError]]: - """ Try sending a JSON body """ - - return ( - await asyncio_detailed( - client=client, - json_body=json_body, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py deleted file mode 100644 index 0f27db9f3..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py +++ /dev/null @@ -1,60 +0,0 @@ -from typing import Any, Dict - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/no_response".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _build_response(*, response: httpx.Response) -> Response[None]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=None, - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[None]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[None]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py deleted file mode 100644 index 753b64a13..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py +++ /dev/null @@ -1,93 +0,0 @@ -from io import BytesIO -from typing import Any, Dict, Optional - -import httpx - -from ...client import Client -from ...types import File, Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/octet_stream".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[File]: - if response.status_code == 200: - response_200 = File(payload=BytesIO(response.content)) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[File]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[File]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, -) -> Optional[File]: - """ """ - - return sync_detailed( - client=client, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[File]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, -) -> Optional[File]: - """ """ - - return ( - await asyncio_detailed( - client=client, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py deleted file mode 100644 index 8058acb43..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py +++ /dev/null @@ -1,115 +0,0 @@ -from typing import Any, Dict, List, Optional, Union - -import httpx - -from ...client import Client -from ...models.http_validation_error import HTTPValidationError -from ...types import UNSET, Response, Unset - - -def _get_kwargs( - *, - client: Client, - query_param: Union[Unset, None, List[str]] = None, -) -> Dict[str, Any]: - url = "{}/tests/optional_query_param/".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_query_param: Union[Unset, List[Any]] = UNSET - if not isinstance(query_param, Unset) and query_param is not None: - json_query_param = query_param - - params: Dict[str, Any] = {} - if query_param is not UNSET and query_param is not None: - params["query_param"] = json_query_param - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "params": params, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: - if response.status_code == 200: - response_200 = None - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - query_param: Union[Unset, None, List[str]] = None, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - query_param=query_param, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - query_param: Union[Unset, None, List[str]] = None, -) -> Optional[Union[None, HTTPValidationError]]: - """ Test optional query parameters """ - - return sync_detailed( - client=client, - query_param=query_param, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - query_param: Union[Unset, None, List[str]] = None, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - query_param=query_param, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - query_param: Union[Unset, None, List[str]] = None, -) -> Optional[Union[None, HTTPValidationError]]: - """ Test optional query parameters """ - - return ( - await asyncio_detailed( - client=client, - query_param=query_param, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py deleted file mode 100644 index 0f134aa87..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py +++ /dev/null @@ -1,106 +0,0 @@ -from typing import Any, Dict, Optional - -import httpx - -from ...client import Client -from ...models.test_inline_objects_json_body import TestInlineObjectsJsonBody -from ...models.test_inline_objects_response_200 import TestInlineObjectsResponse_200 -from ...types import Response - - -def _get_kwargs( - *, - client: Client, - json_body: TestInlineObjectsJsonBody, -) -> Dict[str, Any]: - url = "{}/tests/inline_objects".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - json_json_body = json_body.to_dict() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "json": json_json_body, - } - - -def _parse_response(*, response: httpx.Response) -> Optional[TestInlineObjectsResponse_200]: - if response.status_code == 200: - response_200 = TestInlineObjectsResponse_200.from_dict(response.json()) - - return response_200 - return None - - -def _build_response(*, response: httpx.Response) -> Response[TestInlineObjectsResponse_200]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - json_body: TestInlineObjectsJsonBody, -) -> Response[TestInlineObjectsResponse_200]: - kwargs = _get_kwargs( - client=client, - json_body=json_body, - ) - - response = httpx.post( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - json_body: TestInlineObjectsJsonBody, -) -> Optional[TestInlineObjectsResponse_200]: - """ """ - - return sync_detailed( - client=client, - json_body=json_body, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - json_body: TestInlineObjectsJsonBody, -) -> Response[TestInlineObjectsResponse_200]: - kwargs = _get_kwargs( - client=client, - json_body=json_body, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.post(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - json_body: TestInlineObjectsJsonBody, -) -> Optional[TestInlineObjectsResponse_200]: - """ """ - - return ( - await asyncio_detailed( - client=client, - json_body=json_body, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py deleted file mode 100644 index 45dc0e5dc..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py +++ /dev/null @@ -1,60 +0,0 @@ -from typing import Any, Dict - -import httpx - -from ...client import Client -from ...types import Response - - -def _get_kwargs( - *, - client: Client, -) -> Dict[str, Any]: - url = "{}/tests/unsupported_content".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - } - - -def _build_response(*, response: httpx.Response) -> Response[None]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=None, - ) - - -def sync_detailed( - *, - client: Client, -) -> Response[None]: - kwargs = _get_kwargs( - client=client, - ) - - response = httpx.get( - **kwargs, - ) - - return _build_response(response=response) - - -async def asyncio_detailed( - *, - client: Client, -) -> Response[None]: - kwargs = _get_kwargs( - client=client, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.get(**kwargs) - - return _build_response(response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py deleted file mode 100644 index f8a54ec77..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py +++ /dev/null @@ -1,120 +0,0 @@ -from typing import Any, Dict, Optional, Union - -import httpx - -from ...client import Client -from ...models.body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost -from ...models.http_validation_error import HTTPValidationError -from ...types import UNSET, Response, Unset - - -def _get_kwargs( - *, - client: Client, - multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, -) -> Dict[str, Any]: - url = "{}/tests/upload".format(client.base_url) - - headers: Dict[str, Any] = client.get_headers() - - if keep_alive is not UNSET: - headers["keep-alive"] = keep_alive - - return { - "url": url, - "headers": headers, - "cookies": client.get_cookies(), - "timeout": client.get_timeout(), - "files": multipart_data.to_dict(), - } - - -def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: - if response.status_code == 200: - response_200 = None - - return response_200 - if response.status_code == 422: - response_422 = HTTPValidationError.from_dict(response.json()) - - return response_422 - return None - - -def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: - return Response( - status_code=response.status_code, - content=response.content, - headers=response.headers, - parsed=_parse_response(response=response), - ) - - -def sync_detailed( - *, - client: Client, - multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - multipart_data=multipart_data, - keep_alive=keep_alive, - ) - - response = httpx.post( - **kwargs, - ) - - return _build_response(response=response) - - -def sync( - *, - client: Client, - multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, -) -> Optional[Union[None, HTTPValidationError]]: - """ Upload a file """ - - return sync_detailed( - client=client, - multipart_data=multipart_data, - keep_alive=keep_alive, - ).parsed - - -async def asyncio_detailed( - *, - client: Client, - multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, -) -> Response[Union[None, HTTPValidationError]]: - kwargs = _get_kwargs( - client=client, - multipart_data=multipart_data, - keep_alive=keep_alive, - ) - - async with httpx.AsyncClient() as _client: - response = await _client.post(**kwargs) - - return _build_response(response=response) - - -async def asyncio( - *, - client: Client, - multipart_data: BodyUploadFileTestsUploadPost, - keep_alive: Union[Unset, bool] = UNSET, -) -> Optional[Union[None, HTTPValidationError]]: - """ Upload a file """ - - return ( - await asyncio_detailed( - client=client, - multipart_data=multipart_data, - keep_alive=keep_alive, - ) - ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py deleted file mode 100644 index c3074040c..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/client.py +++ /dev/null @@ -1,46 +0,0 @@ -from typing import Dict - -import attr - - -@attr.s(auto_attribs=True) -class Client: - """ A class for keeping track of data related to the API """ - - base_url: str - cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True) - timeout: float = attr.ib(5.0, kw_only=True) - - def get_headers(self) -> Dict[str, str]: - """ Get headers to be used in all endpoints """ - return {**self.headers} - - def with_headers(self, headers: Dict[str, str]) -> "Client": - """ Get a new client matching this one with additional headers """ - return attr.evolve(self, headers={**self.headers, **headers}) - - def get_cookies(self) -> Dict[str, str]: - return {**self.cookies} - - def with_cookies(self, cookies: Dict[str, str]) -> "Client": - """ Get a new client matching this one with additional cookies """ - return attr.evolve(self, cookies={**self.cookies, **cookies}) - - def get_timeout(self) -> float: - return self.timeout - - def with_timeout(self, timeout: float) -> "Client": - """ Get a new client matching this one with a new timeout (in seconds) """ - return attr.evolve(self, timeout=timeout) - - -@attr.s(auto_attribs=True) -class AuthenticatedClient(Client): - """ A Client which has been authenticated for use on secured endpoints """ - - token: str - - def get_headers(self) -> Dict[str, str]: - """ Get headers to be used in authenticated endpoints """ - return {"Authorization": f"Bearer {self.token}", **self.headers} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py deleted file mode 100644 index d3ca924b3..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py +++ /dev/null @@ -1,22 +0,0 @@ -""" Contains all the data models used in inputs/outputs """ - -from .a_model import AModel -from .an_enum import AnEnum -from .an_int_enum import AnIntEnum -from .body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost -from .different_enum import DifferentEnum -from .free_form_model import FreeFormModel -from .http_validation_error import HTTPValidationError -from .model_with_additional_properties_inlined import ModelWithAdditionalPropertiesInlined -from .model_with_additional_properties_inlined_additional_property import ( - ModelWithAdditionalPropertiesInlinedAdditionalProperty, -) -from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed -from .model_with_any_json_properties import ModelWithAnyJsonProperties -from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty -from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties -from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder -from .model_with_union_property import ModelWithUnionProperty -from .test_inline_objects_json_body import TestInlineObjectsJsonBody -from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 -from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py deleted file mode 100644 index 452eb08fa..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ /dev/null @@ -1,142 +0,0 @@ -import datetime -from typing import Any, Dict, List, Optional, Type, TypeVar, Union, cast - -import attr -from dateutil.parser import isoparse - -from ..models.an_enum import AnEnum -from ..models.different_enum import DifferentEnum -from ..types import UNSET, Unset - -T = TypeVar("T", bound="AModel") - - -@attr.s(auto_attribs=True) -class AModel: - """ A Model for testing all the ways custom objects can be used """ - - an_enum_value: AnEnum - a_camel_date_time: Union[datetime.datetime, datetime.date] - a_date: datetime.date - required_not_nullable: str - a_nullable_date: Optional[datetime.date] - required_nullable: Optional[str] - nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET - attr_1_leading_digit: Union[Unset, str] = UNSET - not_required_nullable: Union[Unset, None, str] = UNSET - not_required_not_nullable: Union[Unset, str] = UNSET - - def to_dict(self) -> Dict[str, Any]: - an_enum_value = self.an_enum_value.value - - if isinstance(self.a_camel_date_time, datetime.datetime): - a_camel_date_time = self.a_camel_date_time.isoformat() - - else: - a_camel_date_time = self.a_camel_date_time.isoformat() - - a_date = self.a_date.isoformat() - required_not_nullable = self.required_not_nullable - nested_list_of_enums: Union[Unset, List[Any]] = UNSET - if not isinstance(self.nested_list_of_enums, Unset): - nested_list_of_enums = [] - for nested_list_of_enums_item_data in self.nested_list_of_enums: - nested_list_of_enums_item = [] - for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: - nested_list_of_enums_item_item = nested_list_of_enums_item_item_data.value - - nested_list_of_enums_item.append(nested_list_of_enums_item_item) - - nested_list_of_enums.append(nested_list_of_enums_item) - - a_nullable_date = self.a_nullable_date.isoformat() if self.a_nullable_date else None - attr_1_leading_digit = self.attr_1_leading_digit - required_nullable = self.required_nullable - not_required_nullable = self.not_required_nullable - not_required_not_nullable = self.not_required_not_nullable - - field_dict: Dict[str, Any] = {} - field_dict.update( - { - "an_enum_value": an_enum_value, - "aCamelDateTime": a_camel_date_time, - "a_date": a_date, - "required_not_nullable": required_not_nullable, - "a_nullable_date": a_nullable_date, - "required_nullable": required_nullable, - } - ) - if nested_list_of_enums is not UNSET: - field_dict["nested_list_of_enums"] = nested_list_of_enums - if attr_1_leading_digit is not UNSET: - field_dict["1_leading_digit"] = attr_1_leading_digit - if not_required_nullable is not UNSET: - field_dict["not_required_nullable"] = not_required_nullable - if not_required_not_nullable is not UNSET: - field_dict["not_required_not_nullable"] = not_required_not_nullable - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - an_enum_value = AnEnum(d.pop("an_enum_value")) - - def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: - data = None if isinstance(data, Unset) else data - a_camel_date_time: Union[datetime.datetime, datetime.date] - try: - a_camel_date_time = isoparse(data) - - return a_camel_date_time - except: # noqa: E722 - pass - a_camel_date_time = isoparse(data).date() - - return a_camel_date_time - - a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) - - a_date = isoparse(d.pop("a_date")).date() - - required_not_nullable = d.pop("required_not_nullable") - - nested_list_of_enums = [] - _nested_list_of_enums = d.pop("nested_list_of_enums", UNSET) - for nested_list_of_enums_item_data in _nested_list_of_enums or []: - nested_list_of_enums_item = [] - _nested_list_of_enums_item = nested_list_of_enums_item_data - for nested_list_of_enums_item_item_data in _nested_list_of_enums_item: - nested_list_of_enums_item_item = DifferentEnum(nested_list_of_enums_item_item_data) - - nested_list_of_enums_item.append(nested_list_of_enums_item_item) - - nested_list_of_enums.append(nested_list_of_enums_item) - - a_nullable_date = None - _a_nullable_date = d.pop("a_nullable_date") - if _a_nullable_date is not None: - a_nullable_date = isoparse(cast(str, _a_nullable_date)).date() - - attr_1_leading_digit = d.pop("1_leading_digit", UNSET) - - required_nullable = d.pop("required_nullable") - - not_required_nullable = d.pop("not_required_nullable", UNSET) - - not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) - - a_model = cls( - an_enum_value=an_enum_value, - a_camel_date_time=a_camel_date_time, - a_date=a_date, - required_not_nullable=required_not_nullable, - nested_list_of_enums=nested_list_of_enums, - a_nullable_date=a_nullable_date, - attr_1_leading_digit=attr_1_leading_digit, - required_nullable=required_nullable, - not_required_nullable=not_required_nullable, - not_required_not_nullable=not_required_not_nullable, - ) - - return a_model diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py deleted file mode 100644 index c266d0763..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import Enum - - -class AnEnum(str, Enum): - FIRST_VALUE = "FIRST_VALUE" - SECOND_VALUE = "SECOND_VALUE" - - def __str__(self) -> str: - return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py deleted file mode 100644 index d7d7a713d..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py +++ /dev/null @@ -1,10 +0,0 @@ -from enum import IntEnum - - -class AnIntEnum(IntEnum): - VALUE_NEGATIVE_1 = -1 - VALUE_1 = 1 - VALUE_2 = 2 - - def __str__(self) -> str: - return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py deleted file mode 100644 index 97db03356..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py +++ /dev/null @@ -1,38 +0,0 @@ -from io import BytesIO -from typing import Any, Dict, Type, TypeVar - -import attr - -from ..types import File - -T = TypeVar("T", bound="BodyUploadFileTestsUploadPost") - - -@attr.s(auto_attribs=True) -class BodyUploadFileTestsUploadPost: - """ """ - - some_file: File - - def to_dict(self) -> Dict[str, Any]: - some_file = self.some_file.to_tuple() - - field_dict: Dict[str, Any] = {} - field_dict.update( - { - "some_file": some_file, - } - ) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - some_file = File(payload=BytesIO(d.pop("some_file"))) - - body_upload_file_tests_upload_post = cls( - some_file=some_file, - ) - - return body_upload_file_tests_upload_post diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py deleted file mode 100644 index 6c167f25c..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import Enum - - -class DifferentEnum(str, Enum): - DIFFERENT = "DIFFERENT" - OTHER = "OTHER" - - def __str__(self) -> str: - return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py deleted file mode 100644 index 1a86b6bac..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar - -import attr - -T = TypeVar("T", bound="FreeFormModel") - - -@attr.s(auto_attribs=True) -class FreeFormModel: - """ """ - - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - - field_dict: Dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({}) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - free_form_model = cls() - - free_form_model.additional_properties = d - return free_form_model - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py deleted file mode 100644 index 3025b07af..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py +++ /dev/null @@ -1,47 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, Union - -import attr - -from ..models.validation_error import ValidationError -from ..types import UNSET, Unset - -T = TypeVar("T", bound="HTTPValidationError") - - -@attr.s(auto_attribs=True) -class HTTPValidationError: - """ """ - - detail: Union[Unset, List[ValidationError]] = UNSET - - def to_dict(self) -> Dict[str, Any]: - detail: Union[Unset, List[Any]] = UNSET - if not isinstance(self.detail, Unset): - detail = [] - for detail_item_data in self.detail: - detail_item = detail_item_data.to_dict() - - detail.append(detail_item) - - field_dict: Dict[str, Any] = {} - field_dict.update({}) - if detail is not UNSET: - field_dict["detail"] = detail - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - detail = [] - _detail = d.pop("detail", UNSET) - for detail_item_data in _detail or []: - detail_item = ValidationError.from_dict(detail_item_data) - - detail.append(detail_item) - - http_validation_error = cls( - detail=detail, - ) - - return http_validation_error diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py deleted file mode 100644 index a81e57a8e..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py +++ /dev/null @@ -1,67 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, Union - -import attr - -from ..models.model_with_additional_properties_inlined_additional_property import ( - ModelWithAdditionalPropertiesInlinedAdditionalProperty, -) -from ..types import UNSET, Unset - -T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlined") - - -@attr.s(auto_attribs=True) -class ModelWithAdditionalPropertiesInlined: - """ """ - - a_number: Union[Unset, float] = UNSET - additional_properties: Dict[str, ModelWithAdditionalPropertiesInlinedAdditionalProperty] = attr.ib( - init=False, factory=dict - ) - - def to_dict(self) -> Dict[str, Any]: - a_number = self.a_number - - field_dict: Dict[str, Any] = {} - for prop_name, prop in self.additional_properties.items(): - field_dict[prop_name] = prop.to_dict() - - field_dict.update({}) - if a_number is not UNSET: - field_dict["a_number"] = a_number - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - a_number = d.pop("a_number", UNSET) - - model_with_additional_properties_inlined = cls( - a_number=a_number, - ) - - additional_properties = {} - for prop_name, prop_dict in d.items(): - additional_property = ModelWithAdditionalPropertiesInlinedAdditionalProperty.from_dict(prop_dict) - - additional_properties[prop_name] = additional_property - - model_with_additional_properties_inlined.additional_properties = additional_properties - return model_with_additional_properties_inlined - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> ModelWithAdditionalPropertiesInlinedAdditionalProperty: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: ModelWithAdditionalPropertiesInlinedAdditionalProperty) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py deleted file mode 100644 index baedb6193..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, Union - -import attr - -from ..types import UNSET, Unset - -T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlinedAdditionalProperty") - - -@attr.s(auto_attribs=True) -class ModelWithAdditionalPropertiesInlinedAdditionalProperty: - """ """ - - extra_props_prop: Union[Unset, str] = UNSET - additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - extra_props_prop = self.extra_props_prop - - field_dict: Dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({}) - if extra_props_prop is not UNSET: - field_dict["extra_props_prop"] = extra_props_prop - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - extra_props_prop = d.pop("extra_props_prop", UNSET) - - model_with_additional_properties_inlined_additional_property = cls( - extra_props_prop=extra_props_prop, - ) - - model_with_additional_properties_inlined_additional_property.additional_properties = d - return model_with_additional_properties_inlined_additional_property - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py deleted file mode 100644 index b265db582..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar - -import attr - -from ..models.an_enum import AnEnum - -T = TypeVar("T", bound="ModelWithAdditionalPropertiesRefed") - - -@attr.s(auto_attribs=True) -class ModelWithAdditionalPropertiesRefed: - """ """ - - additional_properties: Dict[str, AnEnum] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - - field_dict: Dict[str, Any] = {} - for prop_name, prop in self.additional_properties.items(): - field_dict[prop_name] = prop.value - - field_dict.update({}) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - model_with_additional_properties_refed = cls() - - additional_properties = {} - for prop_name, prop_dict in d.items(): - additional_property = AnEnum(prop_dict) - - additional_properties[prop_name] = additional_property - - model_with_additional_properties_refed.additional_properties = additional_properties - return model_with_additional_properties_refed - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> AnEnum: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: AnEnum) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py deleted file mode 100644 index 7696b9753..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py +++ /dev/null @@ -1,90 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, Union, cast - -import attr - -from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty -from ..types import Unset - -T = TypeVar("T", bound="ModelWithAnyJsonProperties") - - -@attr.s(auto_attribs=True) -class ModelWithAnyJsonProperties: - """ """ - - additional_properties: Dict[ - str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] - ] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - - field_dict: Dict[str, Any] = {} - for prop_name, prop in self.additional_properties.items(): - if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty): - field_dict[prop_name] = prop.to_dict() - - elif isinstance(prop, list): - field_dict[prop_name] = prop - - else: - field_dict[prop_name] = prop - - field_dict.update({}) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - model_with_any_json_properties = cls() - - additional_properties = {} - for prop_name, prop_dict in d.items(): - - def _parse_additional_property( - data: Any, - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: - data = None if isinstance(data, Unset) else data - additional_property: Union[ - ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool - ] - try: - additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) - - return additional_property - except: # noqa: E722 - pass - try: - additional_property = cast(List[str], data) - - return additional_property - except: # noqa: E722 - pass - return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) - - additional_property = _parse_additional_property(prop_dict) - - additional_properties[prop_name] = additional_property - - model_with_any_json_properties.additional_properties = additional_properties - return model_with_any_json_properties - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__( - self, key: str - ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: - return self.additional_properties[key] - - def __setitem__( - self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] - ) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py deleted file mode 100644 index 69aa84641..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar - -import attr - -T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalProperty") - - -@attr.s(auto_attribs=True) -class ModelWithAnyJsonPropertiesAdditionalProperty: - """ """ - - additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - - field_dict: Dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({}) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - model_with_any_json_properties_additional_property = cls() - - model_with_any_json_properties_additional_property.additional_properties = d - return model_with_any_json_properties_additional_property - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> str: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: str) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py deleted file mode 100644 index 0066962ed..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py +++ /dev/null @@ -1,64 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, Union, cast - -import attr - -from ..models.model_with_primitive_additional_properties_a_date_holder import ( - ModelWithPrimitiveAdditionalPropertiesADateHolder, -) -from ..types import UNSET, Unset - -T = TypeVar("T", bound="ModelWithPrimitiveAdditionalProperties") - - -@attr.s(auto_attribs=True) -class ModelWithPrimitiveAdditionalProperties: - """ """ - - a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET - additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - a_date_holder: Union[Unset, Dict[str, Any]] = UNSET - if not isinstance(self.a_date_holder, Unset): - a_date_holder = self.a_date_holder.to_dict() - - field_dict: Dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({}) - if a_date_holder is not UNSET: - field_dict["a_date_holder"] = a_date_holder - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET - _a_date_holder = d.pop("a_date_holder", UNSET) - if _a_date_holder is not None and not isinstance(_a_date_holder, Unset): - a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( - cast(Dict[str, Any], _a_date_holder) - ) - - model_with_primitive_additional_properties = cls( - a_date_holder=a_date_holder, - ) - - model_with_primitive_additional_properties.additional_properties = d - return model_with_primitive_additional_properties - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> str: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: str) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py deleted file mode 100644 index 3df34635f..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py +++ /dev/null @@ -1,54 +0,0 @@ -import datetime -from typing import Any, Dict, List, Type, TypeVar - -import attr -from dateutil.parser import isoparse - -T = TypeVar("T", bound="ModelWithPrimitiveAdditionalPropertiesADateHolder") - - -@attr.s(auto_attribs=True) -class ModelWithPrimitiveAdditionalPropertiesADateHolder: - """ """ - - additional_properties: Dict[str, datetime.datetime] = attr.ib(init=False, factory=dict) - - def to_dict(self) -> Dict[str, Any]: - - field_dict: Dict[str, Any] = {} - for prop_name, prop in self.additional_properties.items(): - field_dict[prop_name] = prop.isoformat() - - field_dict.update({}) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - model_with_primitive_additional_properties_a_date_holder = cls() - - additional_properties = {} - for prop_name, prop_dict in d.items(): - additional_property = isoparse(prop_dict) - - additional_properties[prop_name] = additional_property - - model_with_primitive_additional_properties_a_date_holder.additional_properties = additional_properties - return model_with_primitive_additional_properties_a_date_holder - - @property - def additional_keys(self) -> List[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> datetime.datetime: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: datetime.datetime) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py deleted file mode 100644 index 960360cdb..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ /dev/null @@ -1,68 +0,0 @@ -from typing import Any, Dict, Type, TypeVar, Union - -import attr - -from ..models.an_enum import AnEnum -from ..models.an_int_enum import AnIntEnum -from ..types import UNSET, Unset - -T = TypeVar("T", bound="ModelWithUnionProperty") - - -@attr.s(auto_attribs=True) -class ModelWithUnionProperty: - """ """ - - a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET - - def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, AnEnum, AnIntEnum] - if isinstance(self.a_property, Unset): - a_property = UNSET - elif isinstance(self.a_property, AnEnum): - a_property = UNSET - if not isinstance(self.a_property, Unset): - a_property = self.a_property - - else: - a_property = UNSET - if not isinstance(self.a_property, Unset): - a_property = self.a_property - - field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - - def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: - data = None if isinstance(data, Unset) else data - a_property: Union[Unset, AnEnum, AnIntEnum] - try: - a_property = UNSET - _a_property = data - if _a_property is not None: - a_property = AnEnum(_a_property) - - return a_property - except: # noqa: E722 - pass - a_property = UNSET - _a_property = data - if _a_property is not None: - a_property = AnIntEnum(_a_property) - - return a_property - - a_property = _parse_a_property(d.pop("a_property", UNSET)) - - model_with_union_property = cls( - a_property=a_property, - ) - - return model_with_union_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py deleted file mode 100644 index 1ee542873..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Any, Dict, Type, TypeVar, Union - -import attr - -from ..types import UNSET, Unset - -T = TypeVar("T", bound="TestInlineObjectsJsonBody") - - -@attr.s(auto_attribs=True) -class TestInlineObjectsJsonBody: - """ """ - - a_property: Union[Unset, str] = UNSET - - def to_dict(self) -> Dict[str, Any]: - a_property = self.a_property - - field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - a_property = d.pop("a_property", UNSET) - - test_inline_objects_json_body = cls( - a_property=a_property, - ) - - return test_inline_objects_json_body diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py deleted file mode 100644 index 6e44a5b14..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Any, Dict, Type, TypeVar, Union - -import attr - -from ..types import UNSET, Unset - -T = TypeVar("T", bound="TestInlineObjectsResponse_200") - - -@attr.s(auto_attribs=True) -class TestInlineObjectsResponse_200: - """ """ - - a_property: Union[Unset, str] = UNSET - - def to_dict(self) -> Dict[str, Any]: - a_property = self.a_property - - field_dict: Dict[str, Any] = {} - field_dict.update({}) - if a_property is not UNSET: - field_dict["a_property"] = a_property - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - a_property = d.pop("a_property", UNSET) - - test_inline_objects_response_200 = cls( - a_property=a_property, - ) - - return test_inline_objects_response_200 diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py deleted file mode 100644 index a0cd07b51..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Any, Dict, List, Type, TypeVar, cast - -import attr - -T = TypeVar("T", bound="ValidationError") - - -@attr.s(auto_attribs=True) -class ValidationError: - """ """ - - loc: List[str] - msg: str - type: str - - def to_dict(self) -> Dict[str, Any]: - loc = self.loc - - msg = self.msg - type = self.type - - field_dict: Dict[str, Any] = {} - field_dict.update( - { - "loc": loc, - "msg": msg, - "type": type, - } - ) - - return field_dict - - @classmethod - def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: - d = src_dict.copy() - loc = cast(List[str], d.pop("loc")) - - msg = d.pop("msg") - - type = d.pop("type") - - validation_error = cls( - loc=loc, - msg=msg, - type=type, - ) - - return validation_error diff --git a/end_to_end_tests/golden-record/my_test_api_client/py.typed b/end_to_end_tests/golden-record/my_test_api_client/py.typed deleted file mode 100644 index 1aad32711..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/py.typed +++ /dev/null @@ -1 +0,0 @@ -# Marker file for PEP 561 \ No newline at end of file diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py deleted file mode 100644 index 2061b9f08..000000000 --- a/end_to_end_tests/golden-record/my_test_api_client/types.py +++ /dev/null @@ -1,41 +0,0 @@ -""" Contains some shared types for properties """ -from typing import BinaryIO, Generic, MutableMapping, Optional, TextIO, Tuple, TypeVar, Union - -import attr - - -class Unset: - def __bool__(self) -> bool: - return False - - -UNSET: Unset = Unset() - - -@attr.s(auto_attribs=True) -class File: - """ Contains information for file uploads """ - - payload: Union[BinaryIO, TextIO] - file_name: Optional[str] = None - mime_type: Optional[str] = None - - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: - """ Return a tuple representation that httpx will accept for multipart/form-data """ - return self.file_name, self.payload, self.mime_type - - -T = TypeVar("T") - - -@attr.s(auto_attribs=True) -class Response(Generic[T]): - """ A response from an endpoint """ - - status_code: int - content: bytes - headers: MutableMapping[str, str] - parsed: Optional[T] - - -__all__ = ["File", "Response"] diff --git a/end_to_end_tests/golden-record/pyproject.toml b/end_to_end_tests/golden-record/pyproject.toml deleted file mode 100644 index d05055ecd..000000000 --- a/end_to_end_tests/golden-record/pyproject.toml +++ /dev/null @@ -1,41 +0,0 @@ -[tool.poetry] -name = "my-test-api-client" -version = "0.1.0" -description = "A client library for accessing My Test API" - -authors = [] - -readme = "README.md" -packages = [ - {include = "my_test_api_client"}, -] -include = ["CHANGELOG.md", "my_test_api_client/py.typed"] - - -[tool.poetry.dependencies] -python = "^3.6" -httpx = ">=0.15.4,<0.17.0" -attrs = "^20.1.0" -python-dateutil = "^2.8.0" - -[tool.black] -line-length = 120 -target_version = ['py36', 'py37', 'py38'] -exclude = ''' -( - /( - | \.git - | \.venv - | \.mypy_cache - )/ -) -''' - -[tool.isort] -line_length = 120 -multi_line_output = 3 -include_trailing_comma = true - -[build-system] -requires = ["poetry>=1.0"] -build-backend = "poetry.masonry.api" \ No newline at end of file diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 67d6c80ba..edf2e640b 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -88,7 +88,7 @@ def test_to_string_query_parameter(self, mocker): assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" p = Property(name=name, required=False, default=None, nullable=False) - assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = None" + assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = UNSET" p = Property(name=name, required=True, default=None, nullable=False) assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" From 75d250dd70f3e981c88aad1b3098ca16779b39a4 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Tue, 19 Jan 2021 17:28:01 -0500 Subject: [PATCH 11/19] Add another check for nullable --- .../api/tests/defaults_tests_defaults_post.py | 4 +- ...tional_value_tests_optional_query_param.py | 2 +- end_to_end_tests/golden-record/.gitignore | 23 ++ end_to_end_tests/golden-record/README.md | 67 +++++ .../my_test_api_client/__init__.py | 2 + .../my_test_api_client/api/__init__.py | 1 + .../my_test_api_client/api/tests/__init__.py | 0 .../api/tests/defaults_tests_defaults_post.py | 250 ++++++++++++++++++ .../api/tests/get_basic_list_of_booleans.py | 92 +++++++ .../api/tests/get_basic_list_of_floats.py | 92 +++++++ .../api/tests/get_basic_list_of_integers.py | 92 +++++++ .../api/tests/get_basic_list_of_strings.py | 92 +++++++ .../api/tests/get_user_list.py | 140 ++++++++++ .../api/tests/int_enum_tests_int_enum_post.py | 114 ++++++++ .../tests/json_body_tests_json_body_post.py | 110 ++++++++ .../no_response_tests_no_response_get.py | 60 +++++ .../octet_stream_tests_octet_stream_get.py | 93 +++++++ ...tional_value_tests_optional_query_param.py | 115 ++++++++ .../api/tests/test_inline_objects.py | 106 ++++++++ ...d_content_tests_unsupported_content_get.py | 60 +++++ .../tests/upload_file_tests_upload_post.py | 120 +++++++++ .../my_test_api_client/client.py | 46 ++++ .../my_test_api_client/models/__init__.py | 22 ++ .../my_test_api_client/models/a_model.py | 142 ++++++++++ .../my_test_api_client/models/an_enum.py | 9 + .../my_test_api_client/models/an_int_enum.py | 10 + .../body_upload_file_tests_upload_post.py | 38 +++ .../models/different_enum.py | 9 + .../models/free_form_model.py | 44 +++ .../models/http_validation_error.py | 47 ++++ ...odel_with_additional_properties_inlined.py | 67 +++++ ..._properties_inlined_additional_property.py | 54 ++++ .../model_with_additional_properties_refed.py | 54 ++++ .../models/model_with_any_json_properties.py | 90 +++++++ ...any_json_properties_additional_property.py | 44 +++ ...el_with_primitive_additional_properties.py | 64 +++++ ...ive_additional_properties_a_date_holder.py | 54 ++++ .../models/model_with_union_property.py | 68 +++++ .../models/test_inline_objects_json_body.py | 35 +++ .../test_inline_objects_response_200.py | 35 +++ .../models/validation_error.py | 48 ++++ .../golden-record/my_test_api_client/py.typed | 1 + .../golden-record/my_test_api_client/types.py | 41 +++ end_to_end_tests/golden-record/pyproject.toml | 41 +++ .../templates/endpoint_macros.pyi | 4 +- 45 files changed, 2697 insertions(+), 5 deletions(-) create mode 100644 end_to_end_tests/golden-record/.gitignore create mode 100644 end_to_end_tests/golden-record/README.md create mode 100644 end_to_end_tests/golden-record/my_test_api_client/__init__.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/__init__.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/client.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/__init__.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/a_model.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py create mode 100644 end_to_end_tests/golden-record/my_test_api_client/py.typed create mode 100644 end_to_end_tests/golden-record/my_test_api_client/types.py create mode 100644 end_to_end_tests/golden-record/pyproject.toml diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index fde6cb49b..d1a9ef0bf 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -46,10 +46,10 @@ def httpx_request( float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, boolean_prop: Union[Unset, None, bool] = False, - list_prop: Union[Unset, None, List[AnEnum]] = None, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, union_prop: Union[Unset, None, float, str] = "not a float", union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, - enum_prop: Union[Unset, None, AnEnum] = None, + enum_prop: Union[Unset, None, AnEnum] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: json_datetime_prop: Union[Unset, str] = UNSET diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py index 7b821fca6..6dc28630b 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py @@ -36,7 +36,7 @@ def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPVal def httpx_request( *, client: Client, - query_param: Union[Unset, None, List[str]] = None, + query_param: Union[Unset, None, List[str]] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: json_query_param: Union[Unset, List[Any]] = UNSET diff --git a/end_to_end_tests/golden-record/.gitignore b/end_to_end_tests/golden-record/.gitignore new file mode 100644 index 000000000..ed29cb977 --- /dev/null +++ b/end_to_end_tests/golden-record/.gitignore @@ -0,0 +1,23 @@ +__pycache__/ +build/ +dist/ +*.egg-info/ +.pytest_cache/ + +# pyenv +.python-version + +# Environments +.env +.venv + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# JetBrains +.idea/ + +/coverage.xml +/.coverage \ No newline at end of file diff --git a/end_to_end_tests/golden-record/README.md b/end_to_end_tests/golden-record/README.md new file mode 100644 index 000000000..1f9c3a6ee --- /dev/null +++ b/end_to_end_tests/golden-record/README.md @@ -0,0 +1,67 @@ +# my-test-api-client +A client library for accessing My Test API + +## Usage +First, create a client: + +```python +from my_test_api_client import Client + +client = Client(base_url="https://api.example.com") +``` + +If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead: + +```python +from my_test_api_client import AuthenticatedClient + +client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken") +``` + +Now call your endpoint and use your models: + +```python +from my_test_api_client.models import MyDataModel +from my_test_api_client.api.my_tag import get_my_data_model +from my_test_api_client.types import Response + +my_data: MyDataModel = get_my_data_model.sync(client=client) +# or if you need more info (e.g. status_code) +response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client) +``` + +Or do the same thing with an async version: + +```python +from my_test_api_client.models import MyDataModel +from my_test_api_client.async_api.my_tag import get_my_data_model +from my_test_api_client.types import Response + +my_data: MyDataModel = await get_my_data_model.asyncio(client=client) +response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client) +``` + +Things to know: +1. Every path/method combo becomes a Python module with four functions: + 1. `sync`: Blocking request that returns parsed data (if successful) or `None` + 1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful. + 1. `asyncio`: Like `sync` but the async instead of blocking + 1. `asyncio_detailed`: Like `sync_detailed` by async instead of blocking + +1. All path/query params, and bodies become method arguments. +1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above) +1. Any endpoint which did not have a tag will be in `my_test_api_client.api.default` + +## Building / publishing this Client +This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics: +1. Update the metadata in pyproject.toml (e.g. authors, version) +1. If you're using a private repository, configure it with Poetry + 1. `poetry config repositories. ` + 1. `poetry config http-basic. ` +1. Publish the client with `poetry publish --build -r ` or, if for public PyPI, just `poetry publish --build` + +If you want to install this client into another project without publishing it (e.g. for development) then: +1. If that project **is using Poetry**, you can simply do `poetry add ` from that project +1. If that project is not using Poetry: + 1. Build a wheel with `poetry build -f wheel` + 1. Install that wheel from the other project `pip install ` \ No newline at end of file diff --git a/end_to_end_tests/golden-record/my_test_api_client/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/__init__.py new file mode 100644 index 000000000..0f240c245 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/__init__.py @@ -0,0 +1,2 @@ +""" A client library for accessing My Test API """ +from .client import AuthenticatedClient, Client diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py new file mode 100644 index 000000000..dc035f4ce --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/__init__.py @@ -0,0 +1 @@ +""" Contains methods for accessing the API """ diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py new file mode 100644 index 000000000..c54cb393c --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -0,0 +1,250 @@ +import datetime +from typing import Any, Dict, List, Optional, Union + +import httpx +from dateutil.parser import isoparse + +from ...client import Client +from ...models.an_enum import AnEnum +from ...models.http_validation_error import HTTPValidationError +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + client: Client, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = UNSET, +) -> Dict[str, Any]: + url = "{}/tests/defaults".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_datetime_prop: Union[Unset, str] = UNSET + if not isinstance(datetime_prop, Unset) and datetime_prop is not None: + json_datetime_prop = datetime_prop.isoformat() + + json_date_prop: Union[Unset, str] = UNSET + if not isinstance(date_prop, Unset) and date_prop is not None: + json_date_prop = date_prop.isoformat() + + json_list_prop: Union[Unset, List[Any]] = UNSET + if not isinstance(list_prop, Unset) and list_prop is not None: + json_list_prop = [] + for list_prop_item_data in list_prop: + list_prop_item = list_prop_item_data.value + + json_list_prop.append(list_prop_item) + + json_union_prop: Union[Unset, float, str] + if isinstance(union_prop, Unset) or union_prop is None: + json_union_prop = UNSET + else: + json_union_prop = union_prop + + json_union_prop_with_ref: Union[Unset, float, AnEnum] + if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: + json_union_prop_with_ref = UNSET + elif isinstance(union_prop_with_ref, AnEnum): + json_union_prop_with_ref = UNSET + if not isinstance(union_prop_with_ref, Unset): + json_union_prop_with_ref = union_prop_with_ref + + else: + json_union_prop_with_ref = union_prop_with_ref + + json_enum_prop: Union[Unset, AnEnum] = UNSET + if not isinstance(enum_prop, Unset) and enum_prop is not None: + json_enum_prop = enum_prop + + params: Dict[str, Any] = {} + if string_prop is not UNSET and string_prop is not None: + params["string_prop"] = string_prop + if datetime_prop is not UNSET and datetime_prop is not None: + params["datetime_prop"] = json_datetime_prop + if date_prop is not UNSET and date_prop is not None: + params["date_prop"] = json_date_prop + if float_prop is not UNSET and float_prop is not None: + params["float_prop"] = float_prop + if int_prop is not UNSET and int_prop is not None: + params["int_prop"] = int_prop + if boolean_prop is not UNSET and boolean_prop is not None: + params["boolean_prop"] = boolean_prop + if list_prop is not UNSET and list_prop is not None: + params["list_prop"] = json_list_prop + if union_prop is not UNSET and union_prop is not None: + params["union_prop"] = json_union_prop + if union_prop_with_ref is not UNSET and union_prop_with_ref is not None: + params["union_prop_with_ref"] = json_union_prop_with_ref + if enum_prop is not UNSET and enum_prop is not None: + params["enum_prop"] = json_enum_prop + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "params": params, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: + if response.status_code == 200: + response_200 = None + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + string_prop=string_prop, + datetime_prop=datetime_prop, + date_prop=date_prop, + float_prop=float_prop, + int_prop=int_prop, + boolean_prop=boolean_prop, + list_prop=list_prop, + union_prop=union_prop, + union_prop_with_ref=union_prop_with_ref, + enum_prop=enum_prop, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ """ + + return sync_detailed( + client=client, + string_prop=string_prop, + datetime_prop=datetime_prop, + date_prop=date_prop, + float_prop=float_prop, + int_prop=int_prop, + boolean_prop=boolean_prop, + list_prop=list_prop, + union_prop=union_prop, + union_prop_with_ref=union_prop_with_ref, + enum_prop=enum_prop, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + string_prop=string_prop, + datetime_prop=datetime_prop, + date_prop=date_prop, + float_prop=float_prop, + int_prop=int_prop, + boolean_prop=boolean_prop, + list_prop=list_prop, + union_prop=union_prop, + union_prop_with_ref=union_prop_with_ref, + enum_prop=enum_prop, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + string_prop: Union[Unset, None, str] = "the default string", + datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), + float_prop: Union[Unset, None, float] = 3.14, + int_prop: Union[Unset, None, int] = 7, + boolean_prop: Union[Unset, None, bool] = False, + list_prop: Union[Unset, None, List[AnEnum]] = UNSET, + union_prop: Union[Unset, None, float, str] = "not a float", + union_prop_with_ref: Union[Unset, None, float, AnEnum] = 0.6, + enum_prop: Union[Unset, None, AnEnum] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ """ + + return ( + await asyncio_detailed( + client=client, + string_prop=string_prop, + datetime_prop=datetime_prop, + date_prop=date_prop, + float_prop=float_prop, + int_prop=int_prop, + boolean_prop=boolean_prop, + list_prop=list_prop, + union_prop=union_prop, + union_prop_with_ref=union_prop_with_ref, + enum_prop=enum_prop, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py new file mode 100644 index 000000000..eeedd5337 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_booleans.py @@ -0,0 +1,92 @@ +from typing import Any, Dict, List, Optional, cast + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/basic_lists/booleans".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[List[bool]]: + if response.status_code == 200: + response_200 = cast(List[bool], response.json()) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[List[bool]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[List[bool]]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, +) -> Optional[List[bool]]: + """ Get a list of booleans """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[List[bool]]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, +) -> Optional[List[bool]]: + """ Get a list of booleans """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py new file mode 100644 index 000000000..84735b823 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_floats.py @@ -0,0 +1,92 @@ +from typing import Any, Dict, List, Optional, cast + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/basic_lists/floats".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[List[float]]: + if response.status_code == 200: + response_200 = cast(List[float], response.json()) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[List[float]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[List[float]]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, +) -> Optional[List[float]]: + """ Get a list of floats """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[List[float]]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, +) -> Optional[List[float]]: + """ Get a list of floats """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py new file mode 100644 index 000000000..56197de7c --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_integers.py @@ -0,0 +1,92 @@ +from typing import Any, Dict, List, Optional, cast + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/basic_lists/integers".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[List[int]]: + if response.status_code == 200: + response_200 = cast(List[int], response.json()) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[List[int]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[List[int]]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, +) -> Optional[List[int]]: + """ Get a list of integers """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[List[int]]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, +) -> Optional[List[int]]: + """ Get a list of integers """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py new file mode 100644 index 000000000..d75f452fb --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_basic_list_of_strings.py @@ -0,0 +1,92 @@ +from typing import Any, Dict, List, Optional, cast + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/basic_lists/strings".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[List[str]]: + if response.status_code == 200: + response_200 = cast(List[str], response.json()) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[List[str]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[List[str]]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, +) -> Optional[List[str]]: + """ Get a list of strings """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[List[str]]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, +) -> Optional[List[str]]: + """ Get a list of strings """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py new file mode 100644 index 000000000..e43c92d9b --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -0,0 +1,140 @@ +import datetime +from typing import Any, Dict, List, Optional, Union + +import httpx + +from ...client import Client +from ...models.a_model import AModel +from ...models.an_enum import AnEnum +from ...models.http_validation_error import HTTPValidationError +from ...types import Response + + +def _get_kwargs( + *, + client: Client, + an_enum_value: List[AnEnum], + some_date: Union[datetime.date, datetime.datetime], +) -> Dict[str, Any]: + url = "{}/tests/".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_an_enum_value = [] + for an_enum_value_item_data in an_enum_value: + an_enum_value_item = an_enum_value_item_data.value + + json_an_enum_value.append(an_enum_value_item) + + if isinstance(some_date, datetime.date): + json_some_date = some_date.isoformat() + else: + json_some_date = some_date.isoformat() + + params: Dict[str, Any] = { + "an_enum_value": json_an_enum_value, + "some_date": json_some_date, + } + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "params": params, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[List[AModel], HTTPValidationError]]: + if response.status_code == 200: + response_200 = [] + _response_200 = response.json() + for response_200_item_data in _response_200: + response_200_item = AModel.from_dict(response_200_item_data) + + response_200.append(response_200_item) + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[List[AModel], HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + an_enum_value: List[AnEnum], + some_date: Union[datetime.date, datetime.datetime], +) -> Response[Union[List[AModel], HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + an_enum_value=an_enum_value, + some_date=some_date, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + an_enum_value: List[AnEnum], + some_date: Union[datetime.date, datetime.datetime], +) -> Optional[Union[List[AModel], HTTPValidationError]]: + """ Get a list of things """ + + return sync_detailed( + client=client, + an_enum_value=an_enum_value, + some_date=some_date, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + an_enum_value: List[AnEnum], + some_date: Union[datetime.date, datetime.datetime], +) -> Response[Union[List[AModel], HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + an_enum_value=an_enum_value, + some_date=some_date, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + an_enum_value: List[AnEnum], + some_date: Union[datetime.date, datetime.datetime], +) -> Optional[Union[List[AModel], HTTPValidationError]]: + """ Get a list of things """ + + return ( + await asyncio_detailed( + client=client, + an_enum_value=an_enum_value, + some_date=some_date, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py new file mode 100644 index 000000000..cace678f1 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/int_enum_tests_int_enum_post.py @@ -0,0 +1,114 @@ +from typing import Any, Dict, Optional, Union + +import httpx + +from ...client import Client +from ...models.an_int_enum import AnIntEnum +from ...models.http_validation_error import HTTPValidationError +from ...types import Response + + +def _get_kwargs( + *, + client: Client, + int_enum: AnIntEnum, +) -> Dict[str, Any]: + url = "{}/tests/int_enum".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_int_enum = int_enum.value + + params: Dict[str, Any] = { + "int_enum": json_int_enum, + } + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "params": params, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: + if response.status_code == 200: + response_200 = None + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + int_enum: AnIntEnum, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + int_enum=int_enum, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + int_enum: AnIntEnum, +) -> Optional[Union[None, HTTPValidationError]]: + """ """ + + return sync_detailed( + client=client, + int_enum=int_enum, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + int_enum: AnIntEnum, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + int_enum=int_enum, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + int_enum: AnIntEnum, +) -> Optional[Union[None, HTTPValidationError]]: + """ """ + + return ( + await asyncio_detailed( + client=client, + int_enum=int_enum, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py new file mode 100644 index 000000000..408f2dab1 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/json_body_tests_json_body_post.py @@ -0,0 +1,110 @@ +from typing import Any, Dict, Optional, Union + +import httpx + +from ...client import Client +from ...models.a_model import AModel +from ...models.http_validation_error import HTTPValidationError +from ...types import Response + + +def _get_kwargs( + *, + client: Client, + json_body: AModel, +) -> Dict[str, Any]: + url = "{}/tests/json_body".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_json_body = json_body.to_dict() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "json": json_json_body, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: + if response.status_code == 200: + response_200 = None + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + json_body: AModel, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + json_body=json_body, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + json_body: AModel, +) -> Optional[Union[None, HTTPValidationError]]: + """ Try sending a JSON body """ + + return sync_detailed( + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + json_body: AModel, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + json_body=json_body, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + json_body: AModel, +) -> Optional[Union[None, HTTPValidationError]]: + """ Try sending a JSON body """ + + return ( + await asyncio_detailed( + client=client, + json_body=json_body, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py new file mode 100644 index 000000000..0f27db9f3 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/no_response_tests_no_response_get.py @@ -0,0 +1,60 @@ +from typing import Any, Dict + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/no_response".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _build_response(*, response: httpx.Response) -> Response[None]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=None, + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[None]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[None]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py new file mode 100644 index 000000000..753b64a13 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/octet_stream_tests_octet_stream_get.py @@ -0,0 +1,93 @@ +from io import BytesIO +from typing import Any, Dict, Optional + +import httpx + +from ...client import Client +from ...types import File, Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/octet_stream".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[File]: + if response.status_code == 200: + response_200 = File(payload=BytesIO(response.content)) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[File]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[File]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, +) -> Optional[File]: + """ """ + + return sync_detailed( + client=client, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[File]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, +) -> Optional[File]: + """ """ + + return ( + await asyncio_detailed( + client=client, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py new file mode 100644 index 000000000..a593d7b55 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py @@ -0,0 +1,115 @@ +from typing import Any, Dict, List, Optional, Union + +import httpx + +from ...client import Client +from ...models.http_validation_error import HTTPValidationError +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + client: Client, + query_param: Union[Unset, None, List[str]] = UNSET, +) -> Dict[str, Any]: + url = "{}/tests/optional_query_param/".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_query_param: Union[Unset, List[Any]] = UNSET + if not isinstance(query_param, Unset) and query_param is not None: + json_query_param = query_param + + params: Dict[str, Any] = {} + if query_param is not UNSET and query_param is not None: + params["query_param"] = json_query_param + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "params": params, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: + if response.status_code == 200: + response_200 = None + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + query_param: Union[Unset, None, List[str]] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + query_param=query_param, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + query_param: Union[Unset, None, List[str]] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ Test optional query parameters """ + + return sync_detailed( + client=client, + query_param=query_param, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + query_param: Union[Unset, None, List[str]] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + query_param=query_param, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + query_param: Union[Unset, None, List[str]] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ Test optional query parameters """ + + return ( + await asyncio_detailed( + client=client, + query_param=query_param, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py new file mode 100644 index 000000000..0f134aa87 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/test_inline_objects.py @@ -0,0 +1,106 @@ +from typing import Any, Dict, Optional + +import httpx + +from ...client import Client +from ...models.test_inline_objects_json_body import TestInlineObjectsJsonBody +from ...models.test_inline_objects_response_200 import TestInlineObjectsResponse_200 +from ...types import Response + + +def _get_kwargs( + *, + client: Client, + json_body: TestInlineObjectsJsonBody, +) -> Dict[str, Any]: + url = "{}/tests/inline_objects".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + json_json_body = json_body.to_dict() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "json": json_json_body, + } + + +def _parse_response(*, response: httpx.Response) -> Optional[TestInlineObjectsResponse_200]: + if response.status_code == 200: + response_200 = TestInlineObjectsResponse_200.from_dict(response.json()) + + return response_200 + return None + + +def _build_response(*, response: httpx.Response) -> Response[TestInlineObjectsResponse_200]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + json_body: TestInlineObjectsJsonBody, +) -> Response[TestInlineObjectsResponse_200]: + kwargs = _get_kwargs( + client=client, + json_body=json_body, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + json_body: TestInlineObjectsJsonBody, +) -> Optional[TestInlineObjectsResponse_200]: + """ """ + + return sync_detailed( + client=client, + json_body=json_body, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + json_body: TestInlineObjectsJsonBody, +) -> Response[TestInlineObjectsResponse_200]: + kwargs = _get_kwargs( + client=client, + json_body=json_body, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + json_body: TestInlineObjectsJsonBody, +) -> Optional[TestInlineObjectsResponse_200]: + """ """ + + return ( + await asyncio_detailed( + client=client, + json_body=json_body, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py new file mode 100644 index 000000000..45dc0e5dc --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/unsupported_content_tests_unsupported_content_get.py @@ -0,0 +1,60 @@ +from typing import Any, Dict + +import httpx + +from ...client import Client +from ...types import Response + + +def _get_kwargs( + *, + client: Client, +) -> Dict[str, Any]: + url = "{}/tests/unsupported_content".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + } + + +def _build_response(*, response: httpx.Response) -> Response[None]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=None, + ) + + +def sync_detailed( + *, + client: Client, +) -> Response[None]: + kwargs = _get_kwargs( + client=client, + ) + + response = httpx.get( + **kwargs, + ) + + return _build_response(response=response) + + +async def asyncio_detailed( + *, + client: Client, +) -> Response[None]: + kwargs = _get_kwargs( + client=client, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.get(**kwargs) + + return _build_response(response=response) diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py new file mode 100644 index 000000000..f8a54ec77 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/upload_file_tests_upload_post.py @@ -0,0 +1,120 @@ +from typing import Any, Dict, Optional, Union + +import httpx + +from ...client import Client +from ...models.body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost +from ...models.http_validation_error import HTTPValidationError +from ...types import UNSET, Response, Unset + + +def _get_kwargs( + *, + client: Client, + multipart_data: BodyUploadFileTestsUploadPost, + keep_alive: Union[Unset, bool] = UNSET, +) -> Dict[str, Any]: + url = "{}/tests/upload".format(client.base_url) + + headers: Dict[str, Any] = client.get_headers() + + if keep_alive is not UNSET: + headers["keep-alive"] = keep_alive + + return { + "url": url, + "headers": headers, + "cookies": client.get_cookies(), + "timeout": client.get_timeout(), + "files": multipart_data.to_dict(), + } + + +def _parse_response(*, response: httpx.Response) -> Optional[Union[None, HTTPValidationError]]: + if response.status_code == 200: + response_200 = None + + return response_200 + if response.status_code == 422: + response_422 = HTTPValidationError.from_dict(response.json()) + + return response_422 + return None + + +def _build_response(*, response: httpx.Response) -> Response[Union[None, HTTPValidationError]]: + return Response( + status_code=response.status_code, + content=response.content, + headers=response.headers, + parsed=_parse_response(response=response), + ) + + +def sync_detailed( + *, + client: Client, + multipart_data: BodyUploadFileTestsUploadPost, + keep_alive: Union[Unset, bool] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + + response = httpx.post( + **kwargs, + ) + + return _build_response(response=response) + + +def sync( + *, + client: Client, + multipart_data: BodyUploadFileTestsUploadPost, + keep_alive: Union[Unset, bool] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ Upload a file """ + + return sync_detailed( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ).parsed + + +async def asyncio_detailed( + *, + client: Client, + multipart_data: BodyUploadFileTestsUploadPost, + keep_alive: Union[Unset, bool] = UNSET, +) -> Response[Union[None, HTTPValidationError]]: + kwargs = _get_kwargs( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + + async with httpx.AsyncClient() as _client: + response = await _client.post(**kwargs) + + return _build_response(response=response) + + +async def asyncio( + *, + client: Client, + multipart_data: BodyUploadFileTestsUploadPost, + keep_alive: Union[Unset, bool] = UNSET, +) -> Optional[Union[None, HTTPValidationError]]: + """ Upload a file """ + + return ( + await asyncio_detailed( + client=client, + multipart_data=multipart_data, + keep_alive=keep_alive, + ) + ).parsed diff --git a/end_to_end_tests/golden-record/my_test_api_client/client.py b/end_to_end_tests/golden-record/my_test_api_client/client.py new file mode 100644 index 000000000..c3074040c --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/client.py @@ -0,0 +1,46 @@ +from typing import Dict + +import attr + + +@attr.s(auto_attribs=True) +class Client: + """ A class for keeping track of data related to the API """ + + base_url: str + cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True) + headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True) + timeout: float = attr.ib(5.0, kw_only=True) + + def get_headers(self) -> Dict[str, str]: + """ Get headers to be used in all endpoints """ + return {**self.headers} + + def with_headers(self, headers: Dict[str, str]) -> "Client": + """ Get a new client matching this one with additional headers """ + return attr.evolve(self, headers={**self.headers, **headers}) + + def get_cookies(self) -> Dict[str, str]: + return {**self.cookies} + + def with_cookies(self, cookies: Dict[str, str]) -> "Client": + """ Get a new client matching this one with additional cookies """ + return attr.evolve(self, cookies={**self.cookies, **cookies}) + + def get_timeout(self) -> float: + return self.timeout + + def with_timeout(self, timeout: float) -> "Client": + """ Get a new client matching this one with a new timeout (in seconds) """ + return attr.evolve(self, timeout=timeout) + + +@attr.s(auto_attribs=True) +class AuthenticatedClient(Client): + """ A Client which has been authenticated for use on secured endpoints """ + + token: str + + def get_headers(self) -> Dict[str, str]: + """ Get headers to be used in authenticated endpoints """ + return {"Authorization": f"Bearer {self.token}", **self.headers} diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py new file mode 100644 index 000000000..d3ca924b3 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/__init__.py @@ -0,0 +1,22 @@ +""" Contains all the data models used in inputs/outputs """ + +from .a_model import AModel +from .an_enum import AnEnum +from .an_int_enum import AnIntEnum +from .body_upload_file_tests_upload_post import BodyUploadFileTestsUploadPost +from .different_enum import DifferentEnum +from .free_form_model import FreeFormModel +from .http_validation_error import HTTPValidationError +from .model_with_additional_properties_inlined import ModelWithAdditionalPropertiesInlined +from .model_with_additional_properties_inlined_additional_property import ( + ModelWithAdditionalPropertiesInlinedAdditionalProperty, +) +from .model_with_additional_properties_refed import ModelWithAdditionalPropertiesRefed +from .model_with_any_json_properties import ModelWithAnyJsonProperties +from .model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from .model_with_primitive_additional_properties import ModelWithPrimitiveAdditionalProperties +from .model_with_primitive_additional_properties_a_date_holder import ModelWithPrimitiveAdditionalPropertiesADateHolder +from .model_with_union_property import ModelWithUnionProperty +from .test_inline_objects_json_body import TestInlineObjectsJsonBody +from .test_inline_objects_response_200 import TestInlineObjectsResponse_200 +from .validation_error import ValidationError diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py new file mode 100644 index 000000000..452eb08fa --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -0,0 +1,142 @@ +import datetime +from typing import Any, Dict, List, Optional, Type, TypeVar, Union, cast + +import attr +from dateutil.parser import isoparse + +from ..models.an_enum import AnEnum +from ..models.different_enum import DifferentEnum +from ..types import UNSET, Unset + +T = TypeVar("T", bound="AModel") + + +@attr.s(auto_attribs=True) +class AModel: + """ A Model for testing all the ways custom objects can be used """ + + an_enum_value: AnEnum + a_camel_date_time: Union[datetime.datetime, datetime.date] + a_date: datetime.date + required_not_nullable: str + a_nullable_date: Optional[datetime.date] + required_nullable: Optional[str] + nested_list_of_enums: Union[Unset, List[List[DifferentEnum]]] = UNSET + attr_1_leading_digit: Union[Unset, str] = UNSET + not_required_nullable: Union[Unset, None, str] = UNSET + not_required_not_nullable: Union[Unset, str] = UNSET + + def to_dict(self) -> Dict[str, Any]: + an_enum_value = self.an_enum_value.value + + if isinstance(self.a_camel_date_time, datetime.datetime): + a_camel_date_time = self.a_camel_date_time.isoformat() + + else: + a_camel_date_time = self.a_camel_date_time.isoformat() + + a_date = self.a_date.isoformat() + required_not_nullable = self.required_not_nullable + nested_list_of_enums: Union[Unset, List[Any]] = UNSET + if not isinstance(self.nested_list_of_enums, Unset): + nested_list_of_enums = [] + for nested_list_of_enums_item_data in self.nested_list_of_enums: + nested_list_of_enums_item = [] + for nested_list_of_enums_item_item_data in nested_list_of_enums_item_data: + nested_list_of_enums_item_item = nested_list_of_enums_item_item_data.value + + nested_list_of_enums_item.append(nested_list_of_enums_item_item) + + nested_list_of_enums.append(nested_list_of_enums_item) + + a_nullable_date = self.a_nullable_date.isoformat() if self.a_nullable_date else None + attr_1_leading_digit = self.attr_1_leading_digit + required_nullable = self.required_nullable + not_required_nullable = self.not_required_nullable + not_required_not_nullable = self.not_required_not_nullable + + field_dict: Dict[str, Any] = {} + field_dict.update( + { + "an_enum_value": an_enum_value, + "aCamelDateTime": a_camel_date_time, + "a_date": a_date, + "required_not_nullable": required_not_nullable, + "a_nullable_date": a_nullable_date, + "required_nullable": required_nullable, + } + ) + if nested_list_of_enums is not UNSET: + field_dict["nested_list_of_enums"] = nested_list_of_enums + if attr_1_leading_digit is not UNSET: + field_dict["1_leading_digit"] = attr_1_leading_digit + if not_required_nullable is not UNSET: + field_dict["not_required_nullable"] = not_required_nullable + if not_required_not_nullable is not UNSET: + field_dict["not_required_not_nullable"] = not_required_not_nullable + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + an_enum_value = AnEnum(d.pop("an_enum_value")) + + def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.date]: + data = None if isinstance(data, Unset) else data + a_camel_date_time: Union[datetime.datetime, datetime.date] + try: + a_camel_date_time = isoparse(data) + + return a_camel_date_time + except: # noqa: E722 + pass + a_camel_date_time = isoparse(data).date() + + return a_camel_date_time + + a_camel_date_time = _parse_a_camel_date_time(d.pop("aCamelDateTime")) + + a_date = isoparse(d.pop("a_date")).date() + + required_not_nullable = d.pop("required_not_nullable") + + nested_list_of_enums = [] + _nested_list_of_enums = d.pop("nested_list_of_enums", UNSET) + for nested_list_of_enums_item_data in _nested_list_of_enums or []: + nested_list_of_enums_item = [] + _nested_list_of_enums_item = nested_list_of_enums_item_data + for nested_list_of_enums_item_item_data in _nested_list_of_enums_item: + nested_list_of_enums_item_item = DifferentEnum(nested_list_of_enums_item_item_data) + + nested_list_of_enums_item.append(nested_list_of_enums_item_item) + + nested_list_of_enums.append(nested_list_of_enums_item) + + a_nullable_date = None + _a_nullable_date = d.pop("a_nullable_date") + if _a_nullable_date is not None: + a_nullable_date = isoparse(cast(str, _a_nullable_date)).date() + + attr_1_leading_digit = d.pop("1_leading_digit", UNSET) + + required_nullable = d.pop("required_nullable") + + not_required_nullable = d.pop("not_required_nullable", UNSET) + + not_required_not_nullable = d.pop("not_required_not_nullable", UNSET) + + a_model = cls( + an_enum_value=an_enum_value, + a_camel_date_time=a_camel_date_time, + a_date=a_date, + required_not_nullable=required_not_nullable, + nested_list_of_enums=nested_list_of_enums, + a_nullable_date=a_nullable_date, + attr_1_leading_digit=attr_1_leading_digit, + required_nullable=required_nullable, + not_required_nullable=not_required_nullable, + not_required_not_nullable=not_required_not_nullable, + ) + + return a_model diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py new file mode 100644 index 000000000..c266d0763 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_enum.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class AnEnum(str, Enum): + FIRST_VALUE = "FIRST_VALUE" + SECOND_VALUE = "SECOND_VALUE" + + def __str__(self) -> str: + return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py new file mode 100644 index 000000000..d7d7a713d --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/an_int_enum.py @@ -0,0 +1,10 @@ +from enum import IntEnum + + +class AnIntEnum(IntEnum): + VALUE_NEGATIVE_1 = -1 + VALUE_1 = 1 + VALUE_2 = 2 + + def __str__(self) -> str: + return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py new file mode 100644 index 000000000..97db03356 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/body_upload_file_tests_upload_post.py @@ -0,0 +1,38 @@ +from io import BytesIO +from typing import Any, Dict, Type, TypeVar + +import attr + +from ..types import File + +T = TypeVar("T", bound="BodyUploadFileTestsUploadPost") + + +@attr.s(auto_attribs=True) +class BodyUploadFileTestsUploadPost: + """ """ + + some_file: File + + def to_dict(self) -> Dict[str, Any]: + some_file = self.some_file.to_tuple() + + field_dict: Dict[str, Any] = {} + field_dict.update( + { + "some_file": some_file, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + some_file = File(payload=BytesIO(d.pop("some_file"))) + + body_upload_file_tests_upload_post = cls( + some_file=some_file, + ) + + return body_upload_file_tests_upload_post diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py b/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py new file mode 100644 index 000000000..6c167f25c --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/different_enum.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class DifferentEnum(str, Enum): + DIFFERENT = "DIFFERENT" + OTHER = "OTHER" + + def __str__(self) -> str: + return str(self.value) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py new file mode 100644 index 000000000..1a86b6bac --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/free_form_model.py @@ -0,0 +1,44 @@ +from typing import Any, Dict, List, Type, TypeVar + +import attr + +T = TypeVar("T", bound="FreeFormModel") + + +@attr.s(auto_attribs=True) +class FreeFormModel: + """ """ + + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + free_form_model = cls() + + free_form_model.additional_properties = d + return free_form_model + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py new file mode 100644 index 000000000..3025b07af --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/http_validation_error.py @@ -0,0 +1,47 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..models.validation_error import ValidationError +from ..types import UNSET, Unset + +T = TypeVar("T", bound="HTTPValidationError") + + +@attr.s(auto_attribs=True) +class HTTPValidationError: + """ """ + + detail: Union[Unset, List[ValidationError]] = UNSET + + def to_dict(self) -> Dict[str, Any]: + detail: Union[Unset, List[Any]] = UNSET + if not isinstance(self.detail, Unset): + detail = [] + for detail_item_data in self.detail: + detail_item = detail_item_data.to_dict() + + detail.append(detail_item) + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if detail is not UNSET: + field_dict["detail"] = detail + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + detail = [] + _detail = d.pop("detail", UNSET) + for detail_item_data in _detail or []: + detail_item = ValidationError.from_dict(detail_item_data) + + detail.append(detail_item) + + http_validation_error = cls( + detail=detail, + ) + + return http_validation_error diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py new file mode 100644 index 000000000..a81e57a8e --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined.py @@ -0,0 +1,67 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..models.model_with_additional_properties_inlined_additional_property import ( + ModelWithAdditionalPropertiesInlinedAdditionalProperty, +) +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlined") + + +@attr.s(auto_attribs=True) +class ModelWithAdditionalPropertiesInlined: + """ """ + + a_number: Union[Unset, float] = UNSET + additional_properties: Dict[str, ModelWithAdditionalPropertiesInlinedAdditionalProperty] = attr.ib( + init=False, factory=dict + ) + + def to_dict(self) -> Dict[str, Any]: + a_number = self.a_number + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + field_dict.update({}) + if a_number is not UNSET: + field_dict["a_number"] = a_number + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + a_number = d.pop("a_number", UNSET) + + model_with_additional_properties_inlined = cls( + a_number=a_number, + ) + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ModelWithAdditionalPropertiesInlinedAdditionalProperty.from_dict(prop_dict) + + additional_properties[prop_name] = additional_property + + model_with_additional_properties_inlined.additional_properties = additional_properties + return model_with_additional_properties_inlined + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ModelWithAdditionalPropertiesInlinedAdditionalProperty: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ModelWithAdditionalPropertiesInlinedAdditionalProperty) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py new file mode 100644 index 000000000..baedb6193 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_inlined_additional_property.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithAdditionalPropertiesInlinedAdditionalProperty") + + +@attr.s(auto_attribs=True) +class ModelWithAdditionalPropertiesInlinedAdditionalProperty: + """ """ + + extra_props_prop: Union[Unset, str] = UNSET + additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + extra_props_prop = self.extra_props_prop + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if extra_props_prop is not UNSET: + field_dict["extra_props_prop"] = extra_props_prop + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + extra_props_prop = d.pop("extra_props_prop", UNSET) + + model_with_additional_properties_inlined_additional_property = cls( + extra_props_prop=extra_props_prop, + ) + + model_with_additional_properties_inlined_additional_property.additional_properties = d + return model_with_additional_properties_inlined_additional_property + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py new file mode 100644 index 000000000..b265db582 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_additional_properties_refed.py @@ -0,0 +1,54 @@ +from typing import Any, Dict, List, Type, TypeVar + +import attr + +from ..models.an_enum import AnEnum + +T = TypeVar("T", bound="ModelWithAdditionalPropertiesRefed") + + +@attr.s(auto_attribs=True) +class ModelWithAdditionalPropertiesRefed: + """ """ + + additional_properties: Dict[str, AnEnum] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.value + + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_with_additional_properties_refed = cls() + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = AnEnum(prop_dict) + + additional_properties[prop_name] = additional_property + + model_with_additional_properties_refed.additional_properties = additional_properties + return model_with_additional_properties_refed + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> AnEnum: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: AnEnum) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py new file mode 100644 index 000000000..7696b9753 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties.py @@ -0,0 +1,90 @@ +from typing import Any, Dict, List, Type, TypeVar, Union, cast + +import attr + +from ..models.model_with_any_json_properties_additional_property import ModelWithAnyJsonPropertiesAdditionalProperty +from ..types import Unset + +T = TypeVar("T", bound="ModelWithAnyJsonProperties") + + +@attr.s(auto_attribs=True) +class ModelWithAnyJsonProperties: + """ """ + + additional_properties: Dict[ + str, Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + ] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + if isinstance(prop, ModelWithAnyJsonPropertiesAdditionalProperty): + field_dict[prop_name] = prop.to_dict() + + elif isinstance(prop, list): + field_dict[prop_name] = prop + + else: + field_dict[prop_name] = prop + + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_with_any_json_properties = cls() + + additional_properties = {} + for prop_name, prop_dict in d.items(): + + def _parse_additional_property( + data: Any, + ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + data = None if isinstance(data, Unset) else data + additional_property: Union[ + ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool + ] + try: + additional_property = ModelWithAnyJsonPropertiesAdditionalProperty.from_dict(data) + + return additional_property + except: # noqa: E722 + pass + try: + additional_property = cast(List[str], data) + + return additional_property + except: # noqa: E722 + pass + return cast(Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool], data) + + additional_property = _parse_additional_property(prop_dict) + + additional_properties[prop_name] = additional_property + + model_with_any_json_properties.additional_properties = additional_properties + return model_with_any_json_properties + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__( + self, key: str + ) -> Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool]: + return self.additional_properties[key] + + def __setitem__( + self, key: str, value: Union[ModelWithAnyJsonPropertiesAdditionalProperty, List[str], str, float, int, bool] + ) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py new file mode 100644 index 000000000..69aa84641 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_any_json_properties_additional_property.py @@ -0,0 +1,44 @@ +from typing import Any, Dict, List, Type, TypeVar + +import attr + +T = TypeVar("T", bound="ModelWithAnyJsonPropertiesAdditionalProperty") + + +@attr.s(auto_attribs=True) +class ModelWithAnyJsonPropertiesAdditionalProperty: + """ """ + + additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_with_any_json_properties_additional_property = cls() + + model_with_any_json_properties_additional_property.additional_properties = d + return model_with_any_json_properties_additional_property + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py new file mode 100644 index 000000000..0066962ed --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties.py @@ -0,0 +1,64 @@ +from typing import Any, Dict, List, Type, TypeVar, Union, cast + +import attr + +from ..models.model_with_primitive_additional_properties_a_date_holder import ( + ModelWithPrimitiveAdditionalPropertiesADateHolder, +) +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithPrimitiveAdditionalProperties") + + +@attr.s(auto_attribs=True) +class ModelWithPrimitiveAdditionalProperties: + """ """ + + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET + additional_properties: Dict[str, str] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + a_date_holder: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.a_date_holder, Unset): + a_date_holder = self.a_date_holder.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({}) + if a_date_holder is not UNSET: + field_dict["a_date_holder"] = a_date_holder + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + a_date_holder: Union[Unset, ModelWithPrimitiveAdditionalPropertiesADateHolder] = UNSET + _a_date_holder = d.pop("a_date_holder", UNSET) + if _a_date_holder is not None and not isinstance(_a_date_holder, Unset): + a_date_holder = ModelWithPrimitiveAdditionalPropertiesADateHolder.from_dict( + cast(Dict[str, Any], _a_date_holder) + ) + + model_with_primitive_additional_properties = cls( + a_date_holder=a_date_holder, + ) + + model_with_primitive_additional_properties.additional_properties = d + return model_with_primitive_additional_properties + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py new file mode 100644 index 000000000..3df34635f --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_primitive_additional_properties_a_date_holder.py @@ -0,0 +1,54 @@ +import datetime +from typing import Any, Dict, List, Type, TypeVar + +import attr +from dateutil.parser import isoparse + +T = TypeVar("T", bound="ModelWithPrimitiveAdditionalPropertiesADateHolder") + + +@attr.s(auto_attribs=True) +class ModelWithPrimitiveAdditionalPropertiesADateHolder: + """ """ + + additional_properties: Dict[str, datetime.datetime] = attr.ib(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + + field_dict: Dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.isoformat() + + field_dict.update({}) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + model_with_primitive_additional_properties_a_date_holder = cls() + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = isoparse(prop_dict) + + additional_properties[prop_name] = additional_property + + model_with_primitive_additional_properties_a_date_holder.additional_properties = additional_properties + return model_with_primitive_additional_properties_a_date_holder + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> datetime.datetime: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: datetime.datetime) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py new file mode 100644 index 000000000..960360cdb --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -0,0 +1,68 @@ +from typing import Any, Dict, Type, TypeVar, Union + +import attr + +from ..models.an_enum import AnEnum +from ..models.an_int_enum import AnIntEnum +from ..types import UNSET, Unset + +T = TypeVar("T", bound="ModelWithUnionProperty") + + +@attr.s(auto_attribs=True) +class ModelWithUnionProperty: + """ """ + + a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET + + def to_dict(self) -> Dict[str, Any]: + a_property: Union[Unset, AnEnum, AnIntEnum] + if isinstance(self.a_property, Unset): + a_property = UNSET + elif isinstance(self.a_property, AnEnum): + a_property = UNSET + if not isinstance(self.a_property, Unset): + a_property = self.a_property + + else: + a_property = UNSET + if not isinstance(self.a_property, Unset): + a_property = self.a_property + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if a_property is not UNSET: + field_dict["a_property"] = a_property + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + + def _parse_a_property(data: Any) -> Union[Unset, AnEnum, AnIntEnum]: + data = None if isinstance(data, Unset) else data + a_property: Union[Unset, AnEnum, AnIntEnum] + try: + a_property = UNSET + _a_property = data + if _a_property is not None: + a_property = AnEnum(_a_property) + + return a_property + except: # noqa: E722 + pass + a_property = UNSET + _a_property = data + if _a_property is not None: + a_property = AnIntEnum(_a_property) + + return a_property + + a_property = _parse_a_property(d.pop("a_property", UNSET)) + + model_with_union_property = cls( + a_property=a_property, + ) + + return model_with_union_property diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py new file mode 100644 index 000000000..1ee542873 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_json_body.py @@ -0,0 +1,35 @@ +from typing import Any, Dict, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="TestInlineObjectsJsonBody") + + +@attr.s(auto_attribs=True) +class TestInlineObjectsJsonBody: + """ """ + + a_property: Union[Unset, str] = UNSET + + def to_dict(self) -> Dict[str, Any]: + a_property = self.a_property + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if a_property is not UNSET: + field_dict["a_property"] = a_property + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + a_property = d.pop("a_property", UNSET) + + test_inline_objects_json_body = cls( + a_property=a_property, + ) + + return test_inline_objects_json_body diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py new file mode 100644 index 000000000..6e44a5b14 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/test_inline_objects_response_200.py @@ -0,0 +1,35 @@ +from typing import Any, Dict, Type, TypeVar, Union + +import attr + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="TestInlineObjectsResponse_200") + + +@attr.s(auto_attribs=True) +class TestInlineObjectsResponse_200: + """ """ + + a_property: Union[Unset, str] = UNSET + + def to_dict(self) -> Dict[str, Any]: + a_property = self.a_property + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if a_property is not UNSET: + field_dict["a_property"] = a_property + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + a_property = d.pop("a_property", UNSET) + + test_inline_objects_response_200 = cls( + a_property=a_property, + ) + + return test_inline_objects_response_200 diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py new file mode 100644 index 000000000..a0cd07b51 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/models/validation_error.py @@ -0,0 +1,48 @@ +from typing import Any, Dict, List, Type, TypeVar, cast + +import attr + +T = TypeVar("T", bound="ValidationError") + + +@attr.s(auto_attribs=True) +class ValidationError: + """ """ + + loc: List[str] + msg: str + type: str + + def to_dict(self) -> Dict[str, Any]: + loc = self.loc + + msg = self.msg + type = self.type + + field_dict: Dict[str, Any] = {} + field_dict.update( + { + "loc": loc, + "msg": msg, + "type": type, + } + ) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + loc = cast(List[str], d.pop("loc")) + + msg = d.pop("msg") + + type = d.pop("type") + + validation_error = cls( + loc=loc, + msg=msg, + type=type, + ) + + return validation_error diff --git a/end_to_end_tests/golden-record/my_test_api_client/py.typed b/end_to_end_tests/golden-record/my_test_api_client/py.typed new file mode 100644 index 000000000..1aad32711 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561 \ No newline at end of file diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py new file mode 100644 index 000000000..2061b9f08 --- /dev/null +++ b/end_to_end_tests/golden-record/my_test_api_client/types.py @@ -0,0 +1,41 @@ +""" Contains some shared types for properties """ +from typing import BinaryIO, Generic, MutableMapping, Optional, TextIO, Tuple, TypeVar, Union + +import attr + + +class Unset: + def __bool__(self) -> bool: + return False + + +UNSET: Unset = Unset() + + +@attr.s(auto_attribs=True) +class File: + """ Contains information for file uploads """ + + payload: Union[BinaryIO, TextIO] + file_name: Optional[str] = None + mime_type: Optional[str] = None + + def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + """ Return a tuple representation that httpx will accept for multipart/form-data """ + return self.file_name, self.payload, self.mime_type + + +T = TypeVar("T") + + +@attr.s(auto_attribs=True) +class Response(Generic[T]): + """ A response from an endpoint """ + + status_code: int + content: bytes + headers: MutableMapping[str, str] + parsed: Optional[T] + + +__all__ = ["File", "Response"] diff --git a/end_to_end_tests/golden-record/pyproject.toml b/end_to_end_tests/golden-record/pyproject.toml new file mode 100644 index 000000000..d05055ecd --- /dev/null +++ b/end_to_end_tests/golden-record/pyproject.toml @@ -0,0 +1,41 @@ +[tool.poetry] +name = "my-test-api-client" +version = "0.1.0" +description = "A client library for accessing My Test API" + +authors = [] + +readme = "README.md" +packages = [ + {include = "my_test_api_client"}, +] +include = ["CHANGELOG.md", "my_test_api_client/py.typed"] + + +[tool.poetry.dependencies] +python = "^3.6" +httpx = ">=0.15.4,<0.17.0" +attrs = "^20.1.0" +python-dateutil = "^2.8.0" + +[tool.black] +line-length = 120 +target_version = ['py36', 'py37', 'py38'] +exclude = ''' +( + /( + | \.git + | \.venv + | \.mypy_cache + )/ +) +''' + +[tool.isort] +line_length = 120 +multi_line_output = 3 +include_trailing_comma = true + +[build-system] +requires = ["poetry>=1.0"] +build-backend = "poetry.masonry.api" \ No newline at end of file diff --git a/openapi_python_client/templates/endpoint_macros.pyi b/openapi_python_client/templates/endpoint_macros.pyi index 3e527b017..5b93fe4e3 100644 --- a/openapi_python_client/templates/endpoint_macros.pyi +++ b/openapi_python_client/templates/endpoint_macros.pyi @@ -22,7 +22,7 @@ if {{ parameter.python_name }} is not UNSET: {% endfor %} params: Dict[str, Any] = { {% for property in endpoint.query_parameters %} - {% if property.required %} + {% if property.required and not property.nullable %} {% if property.template %} "{{ property.name }}": {{ "json_" + property.python_name }}, {% else %} @@ -32,7 +32,7 @@ params: Dict[str, Any] = { {% endfor %} } {% for property in endpoint.query_parameters %} - {% if not property.required %} + {% if not property.required or property.nullable %} if {{ property.python_name }} is not UNSET and {{ property.python_name }} is not None: {% if property.template %} params["{{ property.name }}"] = {{ "json_" + property.python_name }} From 74444caae3a20067bae39c43db88ad18f30890cf Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 20 Jan 2021 09:13:59 -0500 Subject: [PATCH 12/19] Change tests to use parametrize --- .../test_parser/test_properties/test_init.py | 112 +++++++----------- 1 file changed, 41 insertions(+), 71 deletions(-) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index edf2e640b..09f9cf386 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -16,85 +16,55 @@ class TestProperty: - def test_get_type_string(self, mocker): - from openapi_python_client.parser.properties import Property - - mocker.patch.object(Property, "_type_string", "TestType") - p = Property(name="test", required=True, default=None, nullable=False) - - base_type_string = f"TestType" - - assert p.get_type_string() == base_type_string - - p = Property(name="test", required=True, default=None, nullable=True) - assert p.get_type_string() == f"Optional[{base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=True) - assert p.get_type_string() == f"Union[Unset, None, {base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=False) - assert p.get_type_string() == f"Union[Unset, {base_type_string}]" - assert p.get_type_string(no_optional=True) == base_type_string - - def test_get_type_string_query_parameter(self, mocker): + @pytest.mark.parametrize( + "query_parameter,nullable,required,no_optional,expected", + [ + (False, False, False, False, "Union[Unset, TestType]"), + (False, False, False, True, "TestType"), + (False, False, True, False, "TestType"), + (False, False, True, True, "TestType"), + (False, True, False, False, "Union[Unset, None, TestType]"), + (False, True, False, True, "TestType"), + (False, True, True, False, "Optional[TestType]"), + (False, True, True, True, "TestType"), + (True, False, False, False, "Union[Unset, None, TestType]"), + (True, False, False, True, "TestType"), + (True, False, True, False, "TestType"), + (True, False, True, True, "TestType"), + (True, True, False, False, "Union[Unset, None, TestType]"), + (True, True, False, True, "TestType"), + (True, True, True, False, "Optional[TestType]"), + (True, True, True, True, "TestType"), + ], + ) + def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import Property mocker.patch.object(Property, "_type_string", "TestType") - p = Property(name="test", required=True, default=None, nullable=False) - - base_type_string = f"TestType" + p = Property(name="test", required=required, default=None, nullable=nullable) + assert p.get_type_string(no_optional=no_optional, query_parameter=query_parameter) == expected - assert p.get_type_string(query_parameter=True) == base_type_string - - p = Property(name="test", required=True, default=None, nullable=True) - assert p.get_type_string(query_parameter=True) == f"Optional[{base_type_string}]" - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=True) - assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, {base_type_string}]" - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string - - p = Property(name="test", required=False, default=None, nullable=False) - assert p.get_type_string(query_parameter=True) == f"Union[Unset, None, {base_type_string}]" - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string - - def test_to_string(self, mocker): - from openapi_python_client.parser.properties import Property - - name = "test" - get_type_string = mocker.patch.object(Property, "get_type_string") - p = Property(name=name, required=True, default=None, nullable=False) - - assert p.to_string() == f"{name}: {get_type_string()}" - - p = Property(name=name, required=False, default=None, nullable=False) - assert p.to_string() == f"{name}: {get_type_string()} = UNSET" - - p = Property(name=name, required=True, default=None, nullable=False) - assert p.to_string() == f"{name}: {get_type_string()}" - - p = Property(name=name, required=True, default="TEST", nullable=False) - assert p.to_string() == f"{name}: {get_type_string()} = TEST" - - def test_to_string_query_parameter(self, mocker): + @pytest.mark.parametrize( + "query_parameter,default,required,expected", + [ + (False, None, False, "test: Union[Unset, TestType] = UNSET"), + (False, None, True, "test: TestType"), + (False, "Test", False, "test: Union[Unset, TestType] = Test"), + (False, "Test", True, "test: TestType = Test"), + (True, None, False, "test: Union[Unset, None, TestType] = UNSET"), + (True, None, True, "test: TestType"), + (True, "Test", False, "test: Union[Unset, None, TestType] = Test"), + (True, "Test", True, "test: TestType = Test"), + ], + ) + def test_to_string(self, mocker, query_parameter, default, required, expected): from openapi_python_client.parser.properties import Property name = "test" - get_type_string = mocker.patch.object(Property, "get_type_string") - p = Property(name=name, required=True, default=None, nullable=False) - - assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" - - p = Property(name=name, required=False, default=None, nullable=False) - assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = UNSET" - - p = Property(name=name, required=True, default=None, nullable=False) - assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)}" + mocker.patch.object(Property, "_type_string", "TestType") + p = Property(name=name, required=required, default=default, nullable=False) - p = Property(name=name, required=True, default="TEST", nullable=False) - assert p.to_string(query_parameter=True) == f"{name}: {get_type_string(query_parameter=True)} = TEST" + assert p.to_string(query_parameter=query_parameter) == expected def test_get_imports(self): from openapi_python_client.parser.properties import Property From e906b1a2ff8718737dd680f84d33fe82421ee544 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 20 Jan 2021 09:40:04 -0500 Subject: [PATCH 13/19] Add more e2e tests for datetime --- .../api/tests/defaults_tests_defaults_post.py | 40 ++++++++-- .../api/tests/defaults_tests_defaults_post.py | 78 +++++++++++++++---- end_to_end_tests/openapi.json | 41 +++++++++- 3 files changed, 134 insertions(+), 25 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index d1a9ef0bf..8da3af74f 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -7,7 +7,7 @@ Client = httpx.Client import datetime -from typing import Dict, List, Union +from typing import Dict, List, Optional, Union from dateutil.parser import isoparse @@ -41,7 +41,10 @@ def httpx_request( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -52,9 +55,24 @@ def httpx_request( enum_prop: Union[Unset, None, AnEnum] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: - json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset) and datetime_prop is not None: - json_datetime_prop = datetime_prop.isoformat() + json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET + if ( + not isinstance(not_required_not_nullable_datetime_prop, Unset) + and not_required_not_nullable_datetime_prop is not None + ): + json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() + + json_not_required_nullable_datetime_prop: Union[Unset, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset) and not_required_nullable_datetime_prop is not None: + json_not_required_nullable_datetime_prop = ( + not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None + ) + + json_required_not_nullable_datetime_prop = required_not_nullable_datetime_prop.isoformat() + + json_required_nullable_datetime_prop = ( + required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None + ) json_date_prop: Union[Unset, str] = UNSET if not isinstance(date_prop, Unset) and date_prop is not None: @@ -89,11 +107,17 @@ def httpx_request( if not isinstance(enum_prop, Unset) and enum_prop is not None: json_enum_prop = enum_prop - params: Dict[str, Any] = {} + params: Dict[str, Any] = { + "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, + } if string_prop is not UNSET and string_prop is not None: params["string_prop"] = string_prop - if datetime_prop is not UNSET and datetime_prop is not None: - params["datetime_prop"] = json_datetime_prop + if not_required_not_nullable_datetime_prop is not UNSET and not_required_not_nullable_datetime_prop is not None: + params["not_required_not_nullable_datetime_prop"] = json_not_required_not_nullable_datetime_prop + if not_required_nullable_datetime_prop is not UNSET and not_required_nullable_datetime_prop is not None: + params["not_required_nullable_datetime_prop"] = json_not_required_nullable_datetime_prop + if required_nullable_datetime_prop is not UNSET and required_nullable_datetime_prop is not None: + params["required_nullable_datetime_prop"] = json_required_nullable_datetime_prop if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop if float_prop is not UNSET and float_prop is not None: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index c54cb393c..f367f51ed 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -14,7 +14,10 @@ def _get_kwargs( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -28,9 +31,24 @@ def _get_kwargs( headers: Dict[str, Any] = client.get_headers() - json_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(datetime_prop, Unset) and datetime_prop is not None: - json_datetime_prop = datetime_prop.isoformat() + json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET + if ( + not isinstance(not_required_not_nullable_datetime_prop, Unset) + and not_required_not_nullable_datetime_prop is not None + ): + json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() + + json_not_required_nullable_datetime_prop: Union[Unset, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset) and not_required_nullable_datetime_prop is not None: + json_not_required_nullable_datetime_prop = ( + not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None + ) + + json_required_not_nullable_datetime_prop = required_not_nullable_datetime_prop.isoformat() + + json_required_nullable_datetime_prop = ( + required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None + ) json_date_prop: Union[Unset, str] = UNSET if not isinstance(date_prop, Unset) and date_prop is not None: @@ -65,11 +83,17 @@ def _get_kwargs( if not isinstance(enum_prop, Unset) and enum_prop is not None: json_enum_prop = enum_prop - params: Dict[str, Any] = {} + params: Dict[str, Any] = { + "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, + } if string_prop is not UNSET and string_prop is not None: params["string_prop"] = string_prop - if datetime_prop is not UNSET and datetime_prop is not None: - params["datetime_prop"] = json_datetime_prop + if not_required_not_nullable_datetime_prop is not UNSET and not_required_not_nullable_datetime_prop is not None: + params["not_required_not_nullable_datetime_prop"] = json_not_required_not_nullable_datetime_prop + if not_required_nullable_datetime_prop is not UNSET and not_required_nullable_datetime_prop is not None: + params["not_required_nullable_datetime_prop"] = json_not_required_nullable_datetime_prop + if required_nullable_datetime_prop is not UNSET and required_nullable_datetime_prop is not None: + params["required_nullable_datetime_prop"] = json_required_nullable_datetime_prop if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop if float_prop is not UNSET and float_prop is not None: @@ -121,7 +145,10 @@ def sync_detailed( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -134,7 +161,10 @@ def sync_detailed( kwargs = _get_kwargs( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -156,7 +186,10 @@ def sync( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -171,7 +204,10 @@ def sync( return sync_detailed( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -187,7 +223,10 @@ async def asyncio_detailed( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -200,7 +239,10 @@ async def asyncio_detailed( kwargs = _get_kwargs( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, @@ -221,7 +263,10 @@ async def asyncio( *, client: Client, string_prop: Union[Unset, None, str] = "the default string", - datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_not_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + not_required_nullable_datetime_prop: Union[Unset, None, datetime.datetime] = isoparse("1010-10-10T00:00:00"), + required_not_nullable_datetime_prop: datetime.datetime = isoparse("1010-10-10T00:00:00"), + required_nullable_datetime_prop: Optional[datetime.datetime] = isoparse("1010-10-10T00:00:00"), date_prop: Union[Unset, None, datetime.date] = isoparse("1010-10-10").date(), float_prop: Union[Unset, None, float] = 3.14, int_prop: Union[Unset, None, int] = 7, @@ -237,7 +282,10 @@ async def asyncio( await asyncio_detailed( client=client, string_prop=string_prop, - datetime_prop=datetime_prop, + not_required_not_nullable_datetime_prop=not_required_not_nullable_datetime_prop, + not_required_nullable_datetime_prop=not_required_nullable_datetime_prop, + required_not_nullable_datetime_prop=required_not_nullable_datetime_prop, + required_nullable_datetime_prop=required_nullable_datetime_prop, date_prop=date_prop, float_prop=float_prop, int_prop=int_prop, diff --git a/end_to_end_tests/openapi.json b/end_to_end_tests/openapi.json index 9e3d78908..931fc481e 100644 --- a/end_to_end_tests/openapi.json +++ b/end_to_end_tests/openapi.json @@ -290,12 +290,49 @@ { "required": false, "schema": { - "title": "Datetime Prop", + "title": "Not Required, Not Nullable Datetime Prop", + "nullable": false, "type": "string", "format": "date-time", "default": "1010-10-10T00:00:00" }, - "name": "datetime_prop", + "name": "not_required_not_nullable_datetime_prop", + "in": "query" + }, + { + "required": false, + "schema": { + "title": "Not Required, Nullable Datetime Prop", + "nullable": true, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "not_required_nullable_datetime_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "title": "Required, Not Nullable Datetime Prop", + "nullable": false, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "required_not_nullable_datetime_prop", + "in": "query" + }, + { + "required": true, + "schema": { + "title": "Required, Nullable Datetime Prop", + "nullable": true, + "type": "string", + "format": "date-time", + "default": "1010-10-10T00:00:00" + }, + "name": "required_nullable_datetime_prop", "in": "query" }, { From c11de5764c9107d22c0fd0106a9ae74b25c5b5d9 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 20 Jan 2021 10:29:30 -0500 Subject: [PATCH 14/19] Fix some tests --- .../api/tests/defaults_tests_defaults_post.py | 58 ++++++++++--------- .../custom_e2e/api/tests/get_user_list.py | 2 + ...tional_value_tests_optional_query_param.py | 9 ++- .../api/tests/defaults_tests_defaults_post.py | 58 ++++++++++--------- .../api/tests/get_user_list.py | 2 + ...tional_value_tests_optional_query_param.py | 9 ++- .../templates/endpoint_macros.pyi | 2 +- .../property_templates/date_property.pyi | 6 +- .../property_templates/datetime_property.pyi | 6 +- .../property_templates/enum_property.pyi | 6 +- .../property_templates/file_property.pyi | 6 +- .../property_templates/list_property.pyi | 8 +-- .../property_templates/model_property.pyi | 6 +- .../property_templates/union_property.pyi | 8 +-- 14 files changed, 104 insertions(+), 82 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 8da3af74f..e52982441 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -55,15 +55,14 @@ def httpx_request( enum_prop: Union[Unset, None, AnEnum] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: - json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET - if ( - not isinstance(not_required_not_nullable_datetime_prop, Unset) - and not_required_not_nullable_datetime_prop is not None - ): - json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() - - json_not_required_nullable_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(not_required_nullable_datetime_prop, Unset) and not_required_nullable_datetime_prop is not None: + json_not_required_not_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_not_nullable_datetime_prop, Unset): + json_not_required_not_nullable_datetime_prop = ( + not_required_not_nullable_datetime_prop.isoformat() if not_required_not_nullable_datetime_prop else None + ) + + json_not_required_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset): json_not_required_nullable_datetime_prop = ( not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None ) @@ -74,27 +73,34 @@ def httpx_request( required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None ) - json_date_prop: Union[Unset, str] = UNSET - if not isinstance(date_prop, Unset) and date_prop is not None: - json_date_prop = date_prop.isoformat() + json_date_prop: Union[Unset, None, str] = UNSET + if not isinstance(date_prop, Unset): + json_date_prop = date_prop.isoformat() if date_prop else None - json_list_prop: Union[Unset, List[Any]] = UNSET - if not isinstance(list_prop, Unset) and list_prop is not None: - json_list_prop = [] - for list_prop_item_data in list_prop: - list_prop_item = list_prop_item_data.value + json_list_prop: Union[Unset, None, List[Any]] = UNSET + if not isinstance(list_prop, Unset): + if list_prop is None: + json_list_prop = None + else: + json_list_prop = [] + for list_prop_item_data in list_prop: + list_prop_item = list_prop_item_data.value - json_list_prop.append(list_prop_item) + json_list_prop.append(list_prop_item) - json_union_prop: Union[Unset, float, str] - if isinstance(union_prop, Unset) or union_prop is None: + json_union_prop: Union[Unset, None, float, str] + if isinstance(union_prop, Unset): json_union_prop = UNSET + elif union_prop is None: + json_union_prop: Union[Unset, None, float, str] = None else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, float, AnEnum] - if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: + json_union_prop_with_ref: Union[Unset, None, float, AnEnum] + if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET + elif union_prop_with_ref is None: + json_union_prop_with_ref: Union[Unset, None, float, AnEnum] = None elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): @@ -103,9 +109,9 @@ def httpx_request( else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, AnEnum] = UNSET - if not isinstance(enum_prop, Unset) and enum_prop is not None: - json_enum_prop = enum_prop + json_enum_prop: Union[Unset, None, AnEnum] = UNSET + if not isinstance(enum_prop, Unset): + json_enum_prop = enum_prop if enum_prop else None params: Dict[str, Any] = { "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, @@ -116,7 +122,7 @@ def httpx_request( params["not_required_not_nullable_datetime_prop"] = json_not_required_not_nullable_datetime_prop if not_required_nullable_datetime_prop is not UNSET and not_required_nullable_datetime_prop is not None: params["not_required_nullable_datetime_prop"] = json_not_required_nullable_datetime_prop - if required_nullable_datetime_prop is not UNSET and required_nullable_datetime_prop is not None: + if required_nullable_datetime_prop is not None: params["required_nullable_datetime_prop"] = json_required_nullable_datetime_prop if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py index 72758fd75..87edc5094 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py @@ -53,6 +53,8 @@ def httpx_request( json_an_enum_value.append(an_enum_value_item) + if some_date is None: + json_some_date: Union[datetime.date, datetime.datetime] = None if isinstance(some_date, datetime.date): json_some_date = some_date.isoformat() else: diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py index 6dc28630b..8ff5a52a3 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/optional_value_tests_optional_query_param.py @@ -39,9 +39,12 @@ def httpx_request( query_param: Union[Unset, None, List[str]] = UNSET, ) -> Response[Union[None, HTTPValidationError]]: - json_query_param: Union[Unset, List[Any]] = UNSET - if not isinstance(query_param, Unset) and query_param is not None: - json_query_param = query_param + json_query_param: Union[Unset, None, List[Any]] = UNSET + if not isinstance(query_param, Unset): + if query_param is None: + json_query_param = None + else: + json_query_param = query_param params: Dict[str, Any] = {} if query_param is not UNSET and query_param is not None: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index f367f51ed..fdfa91c2e 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -31,15 +31,14 @@ def _get_kwargs( headers: Dict[str, Any] = client.get_headers() - json_not_required_not_nullable_datetime_prop: Union[Unset, str] = UNSET - if ( - not isinstance(not_required_not_nullable_datetime_prop, Unset) - and not_required_not_nullable_datetime_prop is not None - ): - json_not_required_not_nullable_datetime_prop = not_required_not_nullable_datetime_prop.isoformat() - - json_not_required_nullable_datetime_prop: Union[Unset, str] = UNSET - if not isinstance(not_required_nullable_datetime_prop, Unset) and not_required_nullable_datetime_prop is not None: + json_not_required_not_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_not_nullable_datetime_prop, Unset): + json_not_required_not_nullable_datetime_prop = ( + not_required_not_nullable_datetime_prop.isoformat() if not_required_not_nullable_datetime_prop else None + ) + + json_not_required_nullable_datetime_prop: Union[Unset, None, str] = UNSET + if not isinstance(not_required_nullable_datetime_prop, Unset): json_not_required_nullable_datetime_prop = ( not_required_nullable_datetime_prop.isoformat() if not_required_nullable_datetime_prop else None ) @@ -50,27 +49,34 @@ def _get_kwargs( required_nullable_datetime_prop.isoformat() if required_nullable_datetime_prop else None ) - json_date_prop: Union[Unset, str] = UNSET - if not isinstance(date_prop, Unset) and date_prop is not None: - json_date_prop = date_prop.isoformat() + json_date_prop: Union[Unset, None, str] = UNSET + if not isinstance(date_prop, Unset): + json_date_prop = date_prop.isoformat() if date_prop else None - json_list_prop: Union[Unset, List[Any]] = UNSET - if not isinstance(list_prop, Unset) and list_prop is not None: - json_list_prop = [] - for list_prop_item_data in list_prop: - list_prop_item = list_prop_item_data.value + json_list_prop: Union[Unset, None, List[Any]] = UNSET + if not isinstance(list_prop, Unset): + if list_prop is None: + json_list_prop = None + else: + json_list_prop = [] + for list_prop_item_data in list_prop: + list_prop_item = list_prop_item_data.value - json_list_prop.append(list_prop_item) + json_list_prop.append(list_prop_item) - json_union_prop: Union[Unset, float, str] - if isinstance(union_prop, Unset) or union_prop is None: + json_union_prop: Union[Unset, None, float, str] + if isinstance(union_prop, Unset): json_union_prop = UNSET + elif union_prop is None: + json_union_prop: Union[Unset, None, float, str] = None else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, float, AnEnum] - if isinstance(union_prop_with_ref, Unset) or union_prop_with_ref is None: + json_union_prop_with_ref: Union[Unset, None, float, AnEnum] + if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET + elif union_prop_with_ref is None: + json_union_prop_with_ref: Union[Unset, None, float, AnEnum] = None elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): @@ -79,9 +85,9 @@ def _get_kwargs( else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, AnEnum] = UNSET - if not isinstance(enum_prop, Unset) and enum_prop is not None: - json_enum_prop = enum_prop + json_enum_prop: Union[Unset, None, AnEnum] = UNSET + if not isinstance(enum_prop, Unset): + json_enum_prop = enum_prop if enum_prop else None params: Dict[str, Any] = { "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, @@ -92,7 +98,7 @@ def _get_kwargs( params["not_required_not_nullable_datetime_prop"] = json_not_required_not_nullable_datetime_prop if not_required_nullable_datetime_prop is not UNSET and not_required_nullable_datetime_prop is not None: params["not_required_nullable_datetime_prop"] = json_not_required_nullable_datetime_prop - if required_nullable_datetime_prop is not UNSET and required_nullable_datetime_prop is not None: + if required_nullable_datetime_prop is not None: params["required_nullable_datetime_prop"] = json_required_nullable_datetime_prop if date_prop is not UNSET and date_prop is not None: params["date_prop"] = json_date_prop diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index e43c92d9b..0e83d5111 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -26,6 +26,8 @@ def _get_kwargs( json_an_enum_value.append(an_enum_value_item) + if some_date is None: + json_some_date: Union[datetime.date, datetime.datetime] = None if isinstance(some_date, datetime.date): json_some_date = some_date.isoformat() else: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py index a593d7b55..2c14c2949 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/optional_value_tests_optional_query_param.py @@ -16,9 +16,12 @@ def _get_kwargs( headers: Dict[str, Any] = client.get_headers() - json_query_param: Union[Unset, List[Any]] = UNSET - if not isinstance(query_param, Unset) and query_param is not None: - json_query_param = query_param + json_query_param: Union[Unset, None, List[Any]] = UNSET + if not isinstance(query_param, Unset): + if query_param is None: + json_query_param = None + else: + json_query_param = query_param params: Dict[str, Any] = {} if query_param is not UNSET and query_param is not None: diff --git a/openapi_python_client/templates/endpoint_macros.pyi b/openapi_python_client/templates/endpoint_macros.pyi index 5b93fe4e3..7a1862be3 100644 --- a/openapi_python_client/templates/endpoint_macros.pyi +++ b/openapi_python_client/templates/endpoint_macros.pyi @@ -33,7 +33,7 @@ params: Dict[str, Any] = { } {% for property in endpoint.query_parameters %} {% if not property.required or property.nullable %} -if {{ property.python_name }} is not UNSET and {{ property.python_name }} is not None: +if {% if not property.required %}{{ property.python_name }} is not UNSET and {% endif %}{{ property.python_name }} is not None: {% if property.template %} params["{{ property.name }}"] = {{ "json_" + property.python_name }} {% else %} diff --git a/openapi_python_client/templates/property_templates/date_property.pyi b/openapi_python_client/templates/property_templates/date_property.pyi index 18fbf7735..74dbc90b2 100644 --- a/openapi_python_client/templates/property_templates/date_property.pyi +++ b/openapi_python_client/templates/property_templates/date_property.pyi @@ -13,9 +13,9 @@ if _{{ property.python_name }} is not None: {% if property.required %} {{ destination }} = {{ source }}.isoformat() {% if property.nullable %}if {{ source }} else None {%endif%} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}str]{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None {% else %} {{ destination }} = {{ source }}.isoformat() diff --git a/openapi_python_client/templates/property_templates/datetime_property.pyi b/openapi_python_client/templates/property_templates/datetime_property.pyi index 073db6822..034d896c4 100644 --- a/openapi_python_client/templates/property_templates/datetime_property.pyi +++ b/openapi_python_client/templates/property_templates/datetime_property.pyi @@ -22,9 +22,9 @@ if _{{ property.python_name }} is not None: {{ destination }} = {{ source }}.isoformat() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, str]{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}str]{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None {% else %} {{ destination }} = {{ source }}.isoformat() diff --git a/openapi_python_client/templates/property_templates/enum_property.pyi b/openapi_python_client/templates/property_templates/enum_property.pyi index a5f07a8e4..bee85da6e 100644 --- a/openapi_python_client/templates/property_templates/enum_property.pyi +++ b/openapi_python_client/templates/property_templates/enum_property.pyi @@ -17,9 +17,9 @@ if _{{ property.python_name }} is not None: {{ destination }} = {{ source }}.value {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} {{ destination }} = {{ source }} if {{ source }} else None {% else %} {{ destination }} = {{ source }} diff --git a/openapi_python_client/templates/property_templates/file_property.pyi b/openapi_python_client/templates/property_templates/file_property.pyi index 3833a93ea..ffb6869ef 100644 --- a/openapi_python_client/templates/property_templates/file_property.pyi +++ b/openapi_python_client/templates/property_templates/file_property.pyi @@ -12,9 +12,9 @@ {{ destination }} = {{ source }}.to_tuple() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.to_tuple() if {{ source }} else None {% else %} {{ destination }} = {{ source }}.to_tuple() diff --git a/openapi_python_client/templates/property_templates/list_property.pyi b/openapi_python_client/templates/property_templates/list_property.pyi index 317bb19e8..43b039648 100644 --- a/openapi_python_client/templates/property_templates/list_property.pyi +++ b/openapi_python_client/templates/property_templates/list_property.pyi @@ -44,13 +44,13 @@ else: {{ _transform(property, source, destination) }} {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, List[Any]]{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}List[Any]]{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} if {{ source }} is None: {{ destination }} = None else: - {{ _transform(property, source, destination) | indent(4)}} + {{ _transform(property, source, destination) | indent(8)}} {% else %} {{ _transform(property, source, destination) | indent(4)}} {% endif %} diff --git a/openapi_python_client/templates/property_templates/model_property.pyi b/openapi_python_client/templates/property_templates/model_property.pyi index 0ad78c991..c28467540 100644 --- a/openapi_python_client/templates/property_templates/model_property.pyi +++ b/openapi_python_client/templates/property_templates/model_property.pyi @@ -23,9 +23,9 @@ if _{{ property.python_name }} is not None and not isinstance(_{{ property.pytho {{ destination }} = {{ source }}.to_dict() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[{% if property.nullable %}None, {% endif %}Unset, Dict[str, Any]]{% endif %} = UNSET -if not isinstance({{ source }}, Unset){%if query_parameter %} and {{ source }} is not None{% endif %}: -{% if property.nullable %} +{{ destination }}{% if declare_type %}: Union[{% if property.nullable or query_parameter %}None, {% endif %}Unset, Dict[str, Any]]{% endif %} = UNSET +if not isinstance({{ source }}, Unset): +{% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None {% else %} {{ destination }} = {{ source }}.to_dict() diff --git a/openapi_python_client/templates/property_templates/union_property.pyi b/openapi_python_client/templates/property_templates/union_property.pyi index fadef57e5..219af605a 100644 --- a/openapi_python_client/templates/property_templates/union_property.pyi +++ b/openapi_python_client/templates/property_templates/union_property.pyi @@ -26,18 +26,18 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string( {% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if not property.required %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} -if isinstance({{ source }}, Unset){%if query_parameter %} or {{ source }} is None{% endif %}: +if isinstance({{ source }}, Unset): {{ destination }} = UNSET {% endif %} -{% if property.nullable %} +{% if property.nullable or query_parameter %} {% if property.required %} if {{ source }} is None: {% else %}{# There's an if UNSET statement before this #} elif {{ source }} is None: {% endif %} - {{ destination }}{% if declare_type %}: {{ property.get_type_string() }}{% endif %} = None + {{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = None {% endif %} {% for inner_property in property.inner_properties_with_template() %} {% if loop.first and property.required and not property.nullable %}{# No if UNSET or if None statement before this #} From a045cf3e116c449e1c1e17b648456bce5acafcaa Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 20 Jan 2021 10:33:02 -0500 Subject: [PATCH 15/19] Fix remaining tests --- .../custom_e2e/api/tests/defaults_tests_defaults_post.py | 4 ++-- .../custom_e2e/api/tests/get_user_list.py | 2 -- .../api/tests/defaults_tests_defaults_post.py | 4 ++-- .../my_test_api_client/api/tests/get_user_list.py | 2 -- .../templates/property_templates/union_property.pyi | 6 +++--- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index e52982441..26eb6f6f7 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -92,7 +92,7 @@ def httpx_request( if isinstance(union_prop, Unset): json_union_prop = UNSET elif union_prop is None: - json_union_prop: Union[Unset, None, float, str] = None + json_union_prop = None else: json_union_prop = union_prop @@ -100,7 +100,7 @@ def httpx_request( if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif union_prop_with_ref is None: - json_union_prop_with_ref: Union[Unset, None, float, AnEnum] = None + json_union_prop_with_ref = None elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py index 87edc5094..72758fd75 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/get_user_list.py @@ -53,8 +53,6 @@ def httpx_request( json_an_enum_value.append(an_enum_value_item) - if some_date is None: - json_some_date: Union[datetime.date, datetime.datetime] = None if isinstance(some_date, datetime.date): json_some_date = some_date.isoformat() else: diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index fdfa91c2e..a40137b2f 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -68,7 +68,7 @@ def _get_kwargs( if isinstance(union_prop, Unset): json_union_prop = UNSET elif union_prop is None: - json_union_prop: Union[Unset, None, float, str] = None + json_union_prop = None else: json_union_prop = union_prop @@ -76,7 +76,7 @@ def _get_kwargs( if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif union_prop_with_ref is None: - json_union_prop_with_ref: Union[Unset, None, float, AnEnum] = None + json_union_prop_with_ref = None elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py index 0e83d5111..e43c92d9b 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/get_user_list.py @@ -26,8 +26,6 @@ def _get_kwargs( json_an_enum_value.append(an_enum_value_item) - if some_date is None: - json_some_date: Union[datetime.date, datetime.datetime] = None if isinstance(some_date, datetime.date): json_some_date = some_date.isoformat() else: diff --git a/openapi_python_client/templates/property_templates/union_property.pyi b/openapi_python_client/templates/property_templates/union_property.pyi index 219af605a..ee6d8f119 100644 --- a/openapi_python_client/templates/property_templates/union_property.pyi +++ b/openapi_python_client/templates/property_templates/union_property.pyi @@ -25,19 +25,19 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string( {% endmacro %} {% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} -{% if not property.required %} +{% if not property.required or property.nullable %} {{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} if isinstance({{ source }}, Unset): {{ destination }} = UNSET {% endif %} -{% if property.nullable or query_parameter %} +{% if property.nullable or (query_parameter and not property.required) %} {% if property.required %} if {{ source }} is None: {% else %}{# There's an if UNSET statement before this #} elif {{ source }} is None: {% endif %} - {{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = None + {{ destination }} = None {% endif %} {% for inner_property in property.inner_properties_with_template() %} {% if loop.first and property.required and not property.nullable %}{# No if UNSET or if None statement before this #} From fa92f9a2dd4425f4bdbe4ff1947d1fbc93e75b37 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 20 Jan 2021 10:47:17 -0500 Subject: [PATCH 16/19] Fix unit tests --- .../test_parser/test_properties/test_init.py | 114 ++++-------------- .../test_date_property/optional_nullable.py | 2 +- 2 files changed, 26 insertions(+), 90 deletions(-) diff --git a/tests/test_parser/test_properties/test_init.py b/tests/test_parser/test_properties/test_init.py index 09f9cf386..2f1c71cc5 100644 --- a/tests/test_parser/test_properties/test_init.py +++ b/tests/test_parser/test_properties/test_init.py @@ -252,57 +252,28 @@ def test_get_type_imports(self, mocker): class TestUnionProperty: - def test_get_type_string(self, mocker): - from openapi_python_client.parser.properties import UnionProperty - - inner_property_1 = mocker.MagicMock() - inner_property_1.get_type_string.return_value = "inner_type_string_1" - inner_property_2 = mocker.MagicMock() - inner_property_2.get_type_string.return_value = "inner_type_string_2" - p = UnionProperty( - name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=False, - ) - - base_type_string = f"Union[inner_type_string_1, inner_type_string_2]" - - assert p.get_type_string() == base_type_string - - p = UnionProperty( - name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert p.get_type_string() == f"Union[None, inner_type_string_1, inner_type_string_2]" - assert p.get_type_string(no_optional=True) == base_type_string - - base_type_string_with_unset = f"Union[Unset, inner_type_string_1, inner_type_string_2]" - p = UnionProperty( - name="test", - required=False, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert p.get_type_string() == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" - assert p.get_type_string(no_optional=True) == base_type_string - - p = UnionProperty( - name="test", - required=False, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=False, - ) - assert p.get_type_string() == base_type_string_with_unset - assert p.get_type_string(no_optional=True) == base_type_string - - def test_get_type_string_query_parameter(self, mocker): + @pytest.mark.parametrize( + "query_parameter,nullable,required,no_optional,expected", + [ + (False, False, False, False, "Union[Unset, inner_type_string_1, inner_type_string_2]"), + (False, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (False, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (False, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (False, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (False, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, False, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, True, False, "Union[inner_type_string_1, inner_type_string_2]"), + (True, False, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, False, False, "Union[Unset, None, inner_type_string_1, inner_type_string_2]"), + (True, True, False, True, "Union[inner_type_string_1, inner_type_string_2]"), + (True, True, True, False, "Union[None, inner_type_string_1, inner_type_string_2]"), + (True, True, True, True, "Union[inner_type_string_1, inner_type_string_2]"), + ], + ) + def test_get_type_string(self, mocker, query_parameter, nullable, required, no_optional, expected): from openapi_python_client.parser.properties import UnionProperty inner_property_1 = mocker.MagicMock() @@ -311,48 +282,13 @@ def test_get_type_string_query_parameter(self, mocker): inner_property_2.get_type_string.return_value = "inner_type_string_2" p = UnionProperty( name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=False, - ) - - base_type_string = f"Union[inner_type_string_1, inner_type_string_2]" - - assert p.get_type_string(query_parameter=True) == base_type_string - - p = UnionProperty( - name="test", - required=True, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert p.get_type_string(query_parameter=True) == f"Union[None, inner_type_string_1, inner_type_string_2]" - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string - - base_type_string_with_unset = f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" - p = UnionProperty( - name="test", - required=False, + required=required, default=None, inner_properties=[inner_property_1, inner_property_2], - nullable=True, - ) - assert ( - p.get_type_string(query_parameter=True) == f"Union[Unset, None, inner_type_string_1, inner_type_string_2]" + nullable=nullable, ) - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string - p = UnionProperty( - name="test", - required=False, - default=None, - inner_properties=[inner_property_1, inner_property_2], - nullable=False, - ) - assert p.get_type_string(query_parameter=True) == base_type_string_with_unset - assert p.get_type_string(no_optional=True, query_parameter=True) == base_type_string + assert p.get_type_string(query_parameter=query_parameter, no_optional=no_optional) == expected def test_get_imports(self, mocker): from openapi_python_client.parser.properties import UnionProperty diff --git a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py index cf8780024..be32cfbd3 100644 --- a/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py +++ b/tests/test_templates/test_property_templates/test_date_property/optional_nullable.py @@ -6,7 +6,7 @@ some_source = date(2020, 10, 12) -some_destination: Union[Unset, str] = UNSET +some_destination: Union[Unset, None, str] = UNSET if not isinstance(some_source, Unset): some_destination = some_source.isoformat() if some_source else None From 15122250a54122f5b070201ca64313315a50356f Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Thu, 21 Jan 2021 09:26:55 -0500 Subject: [PATCH 17/19] Refactor out logic for JSON types and fix enum value bug --- .../api/tests/defaults_tests_defaults_post.py | 8 ++--- .../models/model_with_union_property.py | 6 ++-- .../golden-record-custom/custom_e2e/types.py | 5 +++- .../api/tests/defaults_tests_defaults_post.py | 8 ++--- .../models/model_with_union_property.py | 6 ++-- .../golden-record/my_test_api_client/types.py | 5 +++- .../parser/properties/__init__.py | 29 +++++++++++++------ .../parser/properties/enum_property.py | 1 + .../parser/properties/model_property.py | 1 + .../parser/properties/property.py | 10 +++++-- .../property_templates/date_property.pyi | 2 +- .../property_templates/datetime_property.pyi | 2 +- .../property_templates/enum_property.pyi | 6 ++-- .../property_templates/file_property.pyi | 2 +- .../property_templates/list_property.pyi | 2 +- .../property_templates/model_property.pyi | 2 +- .../property_templates/union_property.pyi | 2 +- openapi_python_client/templates/types.py | 5 +++- 18 files changed, 65 insertions(+), 37 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py index 26eb6f6f7..4a2c9074b 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/api/tests/defaults_tests_defaults_post.py @@ -96,7 +96,7 @@ def httpx_request( else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, None, float, AnEnum] + json_union_prop_with_ref: Union[Unset, None, float, int] if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif union_prop_with_ref is None: @@ -104,14 +104,14 @@ def httpx_request( elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): - json_union_prop_with_ref = union_prop_with_ref + json_union_prop_with_ref = union_prop_with_ref.value else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, None, AnEnum] = UNSET + json_enum_prop: Union[Unset, None, int] = UNSET if not isinstance(enum_prop, Unset): - json_enum_prop = enum_prop if enum_prop else None + json_enum_prop = enum_prop.value if enum_prop else None params: Dict[str, Any] = { "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py index 960360cdb..4f62d3d7c 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/model_with_union_property.py @@ -16,18 +16,18 @@ class ModelWithUnionProperty: a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, AnEnum, AnIntEnum] + a_property: Union[Unset, int] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value else: a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value field_dict: Dict[str, Any] = {} field_dict.update({}) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/types.py b/end_to_end_tests/golden-record-custom/custom_e2e/types.py index 2061b9f08..a354a2192 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/types.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/types.py @@ -11,6 +11,9 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type diff --git a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py index a40137b2f..1f865570d 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py +++ b/end_to_end_tests/golden-record/my_test_api_client/api/tests/defaults_tests_defaults_post.py @@ -72,7 +72,7 @@ def _get_kwargs( else: json_union_prop = union_prop - json_union_prop_with_ref: Union[Unset, None, float, AnEnum] + json_union_prop_with_ref: Union[Unset, None, float, int] if isinstance(union_prop_with_ref, Unset): json_union_prop_with_ref = UNSET elif union_prop_with_ref is None: @@ -80,14 +80,14 @@ def _get_kwargs( elif isinstance(union_prop_with_ref, AnEnum): json_union_prop_with_ref = UNSET if not isinstance(union_prop_with_ref, Unset): - json_union_prop_with_ref = union_prop_with_ref + json_union_prop_with_ref = union_prop_with_ref.value else: json_union_prop_with_ref = union_prop_with_ref - json_enum_prop: Union[Unset, None, AnEnum] = UNSET + json_enum_prop: Union[Unset, None, int] = UNSET if not isinstance(enum_prop, Unset): - json_enum_prop = enum_prop if enum_prop else None + json_enum_prop = enum_prop.value if enum_prop else None params: Dict[str, Any] = { "required_not_nullable_datetime_prop": json_required_not_nullable_datetime_prop, diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py index 960360cdb..4f62d3d7c 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/model_with_union_property.py @@ -16,18 +16,18 @@ class ModelWithUnionProperty: a_property: Union[Unset, AnEnum, AnIntEnum] = UNSET def to_dict(self) -> Dict[str, Any]: - a_property: Union[Unset, AnEnum, AnIntEnum] + a_property: Union[Unset, int] if isinstance(self.a_property, Unset): a_property = UNSET elif isinstance(self.a_property, AnEnum): a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value else: a_property = UNSET if not isinstance(self.a_property, Unset): - a_property = self.a_property + a_property = self.a_property.value field_dict: Dict[str, Any] = {} field_dict.update({}) diff --git a/end_to_end_tests/golden-record/my_test_api_client/types.py b/end_to_end_tests/golden-record/my_test_api_client/types.py index 2061b9f08..a354a2192 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/types.py +++ b/end_to_end_tests/golden-record/my_test_api_client/types.py @@ -11,6 +11,9 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index 8da587b1e..e6eacb467 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -19,6 +19,7 @@ class NoneProperty(Property): """ A property that is always None (used for empty schemas) """ _type_string: ClassVar[str] = "None" + _json_type_string: ClassVar[str] = "None" template: ClassVar[Optional[str]] = "none_property.pyi" @@ -29,6 +30,7 @@ class StringProperty(Property): max_length: Optional[int] = None pattern: Optional[str] = None _type_string: ClassVar[str] = "str" + _json_type_string: ClassVar[str] = "str" @attr.s(auto_attribs=True, frozen=True) @@ -38,6 +40,7 @@ class DateTimeProperty(Property): """ _type_string: ClassVar[str] = "datetime.datetime" + _json_type_string: ClassVar[str] = "str" template: ClassVar[str] = "datetime_property.pyi" def get_imports(self, *, prefix: str) -> Set[str]: @@ -58,6 +61,7 @@ class DateProperty(Property): """ A property of type datetime.date """ _type_string: ClassVar[str] = "datetime.date" + _json_type_string: ClassVar[str] = "str" template: ClassVar[str] = "date_property.pyi" def get_imports(self, *, prefix: str) -> Set[str]: @@ -78,6 +82,8 @@ class FileProperty(Property): """ A property used for uploading files """ _type_string: ClassVar[str] = "File" + # Return type of File.to_tuple() + _json_type_string: ClassVar[str] = "Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]" template: ClassVar[str] = "file_property.pyi" def get_imports(self, *, prefix: str) -> Set[str]: @@ -98,6 +104,7 @@ class FloatProperty(Property): """ A property of type float """ _type_string: ClassVar[str] = "float" + _json_type_string: ClassVar[str] = "float" @attr.s(auto_attribs=True, frozen=True) @@ -105,6 +112,7 @@ class IntProperty(Property): """ A property of type int """ _type_string: ClassVar[str] = "int" + _json_type_string: ClassVar[str] = "int" @attr.s(auto_attribs=True, frozen=True) @@ -112,6 +120,7 @@ class BooleanProperty(Property): """ Property for bool """ _type_string: ClassVar[str] = "bool" + _json_type_string: ClassVar[str] = "bool" InnerProp = TypeVar("InnerProp", bound=Property) @@ -122,6 +131,7 @@ class ListProperty(Property, Generic[InnerProp]): """ A property representing a list (array) of other properties """ inner_property: InnerProp + _json_type_string: ClassVar[str] = "List[Any]" template: ClassVar[str] = "list_property.pyi" def get_base_type_string(self) -> str: @@ -159,37 +169,38 @@ def __attrs_post_init__(self) -> None: self, "has_properties_without_templates", any(prop.template is None for prop in self.inner_properties) ) - def _get_inner_prop_string(self) -> str: - inner_types = [p.get_type_string(no_optional=True) for p in self.inner_properties] - return ", ".join(inner_types) + def _get_inner_prop_string(self, json: bool = False) -> str: + inner_types = [p.get_type_string(no_optional=True, json=json) for p in self.inner_properties] + unique_inner_types = list(dict.fromkeys(inner_types)) + return ", ".join(unique_inner_types) def get_base_type_string(self) -> str: return f"Union[{self._get_inner_prop_string()}]" - def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: + def get_type_string(self, no_optional: bool = False, query_parameter: bool = False, json: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property. This implementation differs slightly from `Property.get_type_string` in order to collapse nested union types. """ - type_string = self.get_base_type_string() + type_string = f"Union[{self._get_inner_prop_string(json=json)}]" if no_optional: return type_string if self.required: if self.nullable: - return f"Union[None, {self._get_inner_prop_string()}]" + return f"Union[None, {self._get_inner_prop_string(json=json)}]" else: return type_string else: if self.nullable: - return f"Union[Unset, None, {self._get_inner_prop_string()}]" + return f"Union[Unset, None, {self._get_inner_prop_string(json=json)}]" else: if query_parameter: # For query parameters, None has the same meaning as Unset - return f"Union[Unset, None, {self._get_inner_prop_string()}]" + return f"Union[Unset, None, {self._get_inner_prop_string(json=json)}]" else: - return f"Union[Unset, {self._get_inner_prop_string()}]" + return f"Union[Unset, {self._get_inner_prop_string(json=json)}]" def get_imports(self, *, prefix: str) -> Set[str]: """ diff --git a/openapi_python_client/parser/properties/enum_property.py b/openapi_python_client/parser/properties/enum_property.py index 08fce294d..6938dd716 100644 --- a/openapi_python_client/parser/properties/enum_property.py +++ b/openapi_python_client/parser/properties/enum_property.py @@ -18,6 +18,7 @@ class EnumProperty(Property): values: Dict[str, ValueType] reference: Reference value_type: Type[ValueType] + _json_type_string: ClassVar[str] = "int" default: Optional[Any] = attr.ib() template: ClassVar[str] = "enum_property.pyi" diff --git a/openapi_python_client/parser/properties/model_property.py b/openapi_python_client/parser/properties/model_property.py index 03f217d52..3ab145af4 100644 --- a/openapi_python_client/parser/properties/model_property.py +++ b/openapi_python_client/parser/properties/model_property.py @@ -17,6 +17,7 @@ class ModelProperty(Property): description: str relative_imports: Set[str] additional_properties: Union[bool, Property] + _json_type_string: ClassVar[str] = "Dict[str, Any]" template: ClassVar[str] = "model_property.pyi" diff --git a/openapi_python_client/parser/properties/property.py b/openapi_python_client/parser/properties/property.py index 80390a5ec..651370ae2 100644 --- a/openapi_python_client/parser/properties/property.py +++ b/openapi_python_client/parser/properties/property.py @@ -24,6 +24,7 @@ class Property: required: bool nullable: bool _type_string: ClassVar[str] = "" + _json_type_string: ClassVar[str] = "" # Type of the property after JSON serialization default: Optional[str] = attr.ib() python_name: str = attr.ib(init=False) @@ -35,15 +36,20 @@ def __attrs_post_init__(self) -> None: def get_base_type_string(self) -> str: return self._type_string - def get_type_string(self, no_optional: bool = False, query_parameter: bool = False) -> str: + def get_type_string(self, no_optional: bool = False, query_parameter: bool = False, json: bool = False) -> str: """ Get a string representation of type that should be used when declaring this property Args: no_optional: Do not include Optional or Unset even if the value is optional (needed for isinstance checks) query_parameter: True if the property's type is being used for a query parameter + json: True if the type refers to the property after JSON serialization """ - type_string = self.get_base_type_string() + if json: + type_string = self._json_type_string + else: + type_string = self.get_base_type_string() + if no_optional: return type_string if self.required: diff --git a/openapi_python_client/templates/property_templates/date_property.pyi b/openapi_python_client/templates/property_templates/date_property.pyi index 74dbc90b2..bc2cae912 100644 --- a/openapi_python_client/templates/property_templates/date_property.pyi +++ b/openapi_python_client/templates/property_templates/date_property.pyi @@ -13,7 +13,7 @@ if _{{ property.python_name }} is not None: {% if property.required %} {{ destination }} = {{ source }}.isoformat() {% if property.nullable %}if {{ source }} else None {%endif%} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}str]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/datetime_property.pyi b/openapi_python_client/templates/property_templates/datetime_property.pyi index 034d896c4..91ce0cacc 100644 --- a/openapi_python_client/templates/property_templates/datetime_property.pyi +++ b/openapi_python_client/templates/property_templates/datetime_property.pyi @@ -22,7 +22,7 @@ if _{{ property.python_name }} is not None: {{ destination }} = {{ source }}.isoformat() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}str]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.isoformat() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/enum_property.pyi b/openapi_python_client/templates/property_templates/enum_property.pyi index bee85da6e..831f633d5 100644 --- a/openapi_python_client/templates/property_templates/enum_property.pyi +++ b/openapi_python_client/templates/property_templates/enum_property.pyi @@ -17,12 +17,12 @@ if _{{ property.python_name }} is not None: {{ destination }} = {{ source }}.value {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} - {{ destination }} = {{ source }} if {{ source }} else None + {{ destination }} = {{ source }}.value if {{ source }} else None {% else %} - {{ destination }} = {{ source }} + {{ destination }} = {{ source }}.value {% endif %} {% endif %} {% endmacro %} diff --git a/openapi_python_client/templates/property_templates/file_property.pyi b/openapi_python_client/templates/property_templates/file_property.pyi index ffb6869ef..50a331851 100644 --- a/openapi_python_client/templates/property_templates/file_property.pyi +++ b/openapi_python_client/templates/property_templates/file_property.pyi @@ -12,7 +12,7 @@ {{ destination }} = {{ source }}.to_tuple() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.to_tuple() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/list_property.pyi b/openapi_python_client/templates/property_templates/list_property.pyi index 43b039648..5f58bcd30 100644 --- a/openapi_python_client/templates/property_templates/list_property.pyi +++ b/openapi_python_client/templates/property_templates/list_property.pyi @@ -44,7 +44,7 @@ else: {{ _transform(property, source, destination) }} {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[Unset, {% if property.nullable or query_parameter %}None, {% endif %}List[Any]]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} if {{ source }} is None: diff --git a/openapi_python_client/templates/property_templates/model_property.pyi b/openapi_python_client/templates/property_templates/model_property.pyi index c28467540..dfda61d97 100644 --- a/openapi_python_client/templates/property_templates/model_property.pyi +++ b/openapi_python_client/templates/property_templates/model_property.pyi @@ -23,7 +23,7 @@ if _{{ property.python_name }} is not None and not isinstance(_{{ property.pytho {{ destination }} = {{ source }}.to_dict() {% endif %} {% else %} -{{ destination }}{% if declare_type %}: Union[{% if property.nullable or query_parameter %}None, {% endif %}Unset, Dict[str, Any]]{% endif %} = UNSET +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} = UNSET if not isinstance({{ source }}, Unset): {% if property.nullable or query_parameter %} {{ destination }} = {{ source }}.to_dict() if {{ source }} else None diff --git a/openapi_python_client/templates/property_templates/union_property.pyi b/openapi_python_client/templates/property_templates/union_property.pyi index ee6d8f119..509c7f34e 100644 --- a/openapi_python_client/templates/property_templates/union_property.pyi +++ b/openapi_python_client/templates/property_templates/union_property.pyi @@ -26,7 +26,7 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string( {% macro transform(property, source, destination, declare_type=True, query_parameter=False) %} {% if not property.required or property.nullable %} -{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter) }}{% endif %} +{{ destination }}{% if declare_type %}: {{ property.get_type_string(query_parameter=query_parameter, json=True) }}{% endif %} if isinstance({{ source }}, Unset): {{ destination }} = UNSET diff --git a/openapi_python_client/templates/types.py b/openapi_python_client/templates/types.py index 2061b9f08..a354a2192 100644 --- a/openapi_python_client/templates/types.py +++ b/openapi_python_client/templates/types.py @@ -11,6 +11,9 @@ def __bool__(self) -> bool: UNSET: Unset = Unset() +# Used as `FileProperty._json_type_string` +FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]] + @attr.s(auto_attribs=True) class File: @@ -20,7 +23,7 @@ class File: file_name: Optional[str] = None mime_type: Optional[str] = None - def to_tuple(self) -> Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]: + def to_tuple(self) -> FileJsonType: """ Return a tuple representation that httpx will accept for multipart/form-data """ return self.file_name, self.payload, self.mime_type From 4b8fc70d9af24ea56b5b89e12a42e2290806774c Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Wed, 27 Jan 2021 09:26:43 -0500 Subject: [PATCH 18/19] Refactor union base type string --- openapi_python_client/parser/properties/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openapi_python_client/parser/properties/__init__.py b/openapi_python_client/parser/properties/__init__.py index e6eacb467..e3a3f69b7 100644 --- a/openapi_python_client/parser/properties/__init__.py +++ b/openapi_python_client/parser/properties/__init__.py @@ -174,8 +174,8 @@ def _get_inner_prop_string(self, json: bool = False) -> str: unique_inner_types = list(dict.fromkeys(inner_types)) return ", ".join(unique_inner_types) - def get_base_type_string(self) -> str: - return f"Union[{self._get_inner_prop_string()}]" + def get_base_type_string(self, json: bool = False) -> str: + return f"Union[{self._get_inner_prop_string(json=json)}]" def get_type_string(self, no_optional: bool = False, query_parameter: bool = False, json: bool = False) -> str: """ @@ -184,7 +184,7 @@ def get_type_string(self, no_optional: bool = False, query_parameter: bool = Fal This implementation differs slightly from `Property.get_type_string` in order to collapse nested union types. """ - type_string = f"Union[{self._get_inner_prop_string(json=json)}]" + type_string = self.get_base_type_string(json=json) if no_optional: return type_string if self.required: From 05d284e8d82755a7761600d4a07356dc341c2035 Mon Sep 17 00:00:00 2001 From: Forest Tong Date: Mon, 1 Feb 2021 13:25:20 -0500 Subject: [PATCH 19/19] Regenerate tests --- .../golden-record-custom/custom_e2e/models/a_model.py | 8 ++++---- .../golden-record/my_test_api_client/models/a_model.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py index b321979c3..d7d8acff8 100644 --- a/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py +++ b/end_to_end_tests/golden-record-custom/custom_e2e/models/a_model.py @@ -31,8 +31,8 @@ class AModel: attr_1_leading_digit: Union[Unset, str] = UNSET not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET - not_required_nullable_model: Union[Optional[AModelNotRequiredNullableModel], Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET + not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET def to_dict(self) -> Dict[str, Any]: an_enum_value = self.an_enum_value.value @@ -70,7 +70,7 @@ def to_dict(self) -> Dict[str, Any]: if not isinstance(self.not_required_model, Unset): not_required_model = self.not_required_model.to_dict() - not_required_nullable_model: Union[None, Unset, Dict[str, Any]] = UNSET + not_required_nullable_model: Union[Unset, None, Dict[str, Any]] = UNSET if not isinstance(self.not_required_nullable_model, Unset): not_required_nullable_model = ( self.not_required_nullable_model.to_dict() if self.not_required_nullable_model else None @@ -160,7 +160,7 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat if _nullable_model is not None: nullable_model = AModelNullableModel.from_dict(cast(Dict[str, Any], _nullable_model)) - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET _not_required_model = d.pop("not_required_model", UNSET) if not isinstance(_not_required_model, Unset): not_required_model = AModelNotRequiredModel.from_dict(cast(Dict[str, Any], _not_required_model)) diff --git a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py index b321979c3..d7d8acff8 100644 --- a/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py +++ b/end_to_end_tests/golden-record/my_test_api_client/models/a_model.py @@ -31,8 +31,8 @@ class AModel: attr_1_leading_digit: Union[Unset, str] = UNSET not_required_nullable: Union[Unset, None, str] = UNSET not_required_not_nullable: Union[Unset, str] = UNSET - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET - not_required_nullable_model: Union[Optional[AModelNotRequiredNullableModel], Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET + not_required_nullable_model: Union[Unset, None, AModelNotRequiredNullableModel] = UNSET def to_dict(self) -> Dict[str, Any]: an_enum_value = self.an_enum_value.value @@ -70,7 +70,7 @@ def to_dict(self) -> Dict[str, Any]: if not isinstance(self.not_required_model, Unset): not_required_model = self.not_required_model.to_dict() - not_required_nullable_model: Union[None, Unset, Dict[str, Any]] = UNSET + not_required_nullable_model: Union[Unset, None, Dict[str, Any]] = UNSET if not isinstance(self.not_required_nullable_model, Unset): not_required_nullable_model = ( self.not_required_nullable_model.to_dict() if self.not_required_nullable_model else None @@ -160,7 +160,7 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat if _nullable_model is not None: nullable_model = AModelNullableModel.from_dict(cast(Dict[str, Any], _nullable_model)) - not_required_model: Union[AModelNotRequiredModel, Unset] = UNSET + not_required_model: Union[Unset, AModelNotRequiredModel] = UNSET _not_required_model = d.pop("not_required_model", UNSET) if not isinstance(_not_required_model, Unset): not_required_model = AModelNotRequiredModel.from_dict(cast(Dict[str, Any], _not_required_model))