Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(deps): Bump httpx from 0.16.1 to 0.17.0 #26

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AModel:
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
Expand Down Expand Up @@ -47,6 +48,8 @@ def to_dict(self) -> Dict[str, Any]:

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
Expand All @@ -59,6 +62,7 @@ def to_dict(self) -> Dict[str, Any]:
"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,
}
)
Expand Down Expand Up @@ -109,6 +113,9 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat

nested_list_of_enums.append(nested_list_of_enums_item)

a_nullable_date = d.pop("a_nullable_date")
a_nullable_date = isoparse(a_nullable_date).date() if a_nullable_date else None

attr_1_leading_digit = d.pop("1_leading_digit", UNSET)

required_nullable = d.pop("required_nullable")
Expand All @@ -123,6 +130,7 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class AModel:
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
Expand Down Expand Up @@ -47,6 +48,8 @@ def to_dict(self) -> Dict[str, Any]:

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
Expand All @@ -59,6 +62,7 @@ def to_dict(self) -> Dict[str, Any]:
"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,
}
)
Expand Down Expand Up @@ -109,6 +113,9 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat

nested_list_of_enums.append(nested_list_of_enums_item)

a_nullable_date = d.pop("a_nullable_date")
a_nullable_date = isoparse(a_nullable_date).date() if a_nullable_date else None

attr_1_leading_digit = d.pop("1_leading_digit", UNSET)

required_nullable = d.pop("required_nullable")
Expand All @@ -123,6 +130,7 @@ def _parse_a_camel_date_time(data: Any) -> Union[datetime.datetime, datetime.dat
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,
Expand Down
8 changes: 7 additions & 1 deletion end_to_end_tests/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@
"schemas": {
"AModel": {
"title": "AModel",
"required": ["an_enum_value", "aCamelDateTime", "a_date", "required_nullable", "required_not_nullable"],
"required": ["an_enum_value", "aCamelDateTime", "a_date", "a_nullable_date", "required_nullable", "required_not_nullable"],
"type": "object",
"properties": {
"an_enum_value": {
Expand Down Expand Up @@ -657,6 +657,12 @@
"type": "string",
"format": "date"
},
"a_nullable_date": {
"title": "A Nullable Date",
"type": "string",
"format": "date",
"nullable": true
},
"1_leading_digit": {
"title": "Leading Digit",
"type": "string"
Expand Down
25 changes: 21 additions & 4 deletions openapi_python_client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ def __init__(self, *, openapi: GeneratorData, custom_template_path: Optional[Pat
self.package_description: str = utils.remove_string_escapes(
f"A client library for accessing {self.openapi.title}"
)
self.client_name: str = f'{utils.pascal_case(openapi.title)}Client'
self.version: str = self.package_version_override or openapi.version

self.env.filters.update(self.TEMPLATE_FILTERS)

def build(self) -> Sequence[GeneratorError]:
Expand Down Expand Up @@ -117,7 +117,9 @@ def _create_package(self) -> None:
package_init = self.package_dir / "__init__.py"

package_init_template = self.env.get_template("package_init.pyi")
package_init.write_text(package_init_template.render(description=self.package_description))
package_init.write_text(
package_init_template.render(client_name=self.client_name, description=self.package_description)
)

pytyped = self.package_dir / "py.typed"
pytyped.write_text("# Marker file for PEP 561")
Expand Down Expand Up @@ -184,7 +186,20 @@ def _build_api(self) -> None:
# Generate Client
client_path = self.package_dir / "client.py"
client_template = self.env.get_template("client.pyi")
client_path.write_text(client_template.render())
client_path.write_text(client_template.render(title=self.openapi.title))

# Generate wrapper
imports = [m.reference.class_name for m in self.openapi.models.values()]
imports.extend([e.reference.class_name for e in self.openapi.enums.values()])
wrapper = self.package_dir / "wrapper.py"
wrapper_template = self.env.get_template("wrapper.pyi")
wrapper.write_text(
wrapper_template.render(
client_name=self.client_name,
imports=imports,
endpoint_collections=self.openapi.endpoint_collections_by_tag,
)
)

# Generate endpoints
api_dir = self.package_dir / "api"
Expand All @@ -197,7 +212,9 @@ def _build_api(self) -> None:
tag = utils.snake_case(tag)
tag_dir = api_dir / tag
tag_dir.mkdir()
(tag_dir / "__init__.py").touch()
tag_init = tag_dir / "__init__.py"
tag_init_template = self.env.get_template("tag_init.pyi")
tag_init.write_text(tag_init_template.render(tag=tag, collection=collection))

for endpoint in collection.endpoints:
module_path = tag_dir / f"{snake_case(endpoint.name)}.py"
Expand Down
13 changes: 11 additions & 2 deletions openapi_python_client/templates/client.pyi
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
from typing import Dict
import os
from typing import Dict, Optional

import attr

@attr.s(auto_attribs=True)
class Client:
""" A class for keeping track of data related to the API """

base_url: str
base_url: Optional[str] = attr.ib(None, kw_only=True)
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 __attrs_post_init__(self):
env_base_url = os.environ.get('{{ title | snakecase | upper }}_BASE_URL')
self.base_url = self.base_url or env_base_url
if self.base_url is None:
raise ValueError(f'"base_url" has to be set either from the '
f'environment variable "{env_base_url}", or '
f'passed with the "base_url" argument')

def get_headers(self) -> Dict[str, str]:
""" Get headers to be used in all endpoints """
return {**self.headers}
Expand Down
6 changes: 5 additions & 1 deletion openapi_python_client/templates/endpoint_macros.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,18 @@ Union[
{% endmacro %}

{# The all the kwargs passed into an endpoint (and variants thereof)) #}
{% macro arguments(endpoint) %}
{% macro arguments(endpoint, client=True) %}
{% if endpoint.path_parameters or endpoint.form_body_reference or endpoint.multipart_body_reference or endpoint.query_parameters or endpoint.json_body or endpoint.header_parameters %}
*,
{% endif %}
{# Proper client based on whether or not the endpoint requires authentication #}
{% if client %}
{% if endpoint.requires_security %}
client: AuthenticatedClient,
{% else %}
client: Client,
{% endif %}
{% endif %}
{# path parameters #}
{% for parameter in endpoint.path_parameters %}
{{ parameter.to_string() }},
Expand Down
3 changes: 2 additions & 1 deletion openapi_python_client/templates/package_init.pyi
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
""" {{ description }} """
from .client import AuthenticatedClient, Client

from .wrapper import Sync{{ client_name }}, {{ client_name }}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{% macro construct(property, source, initial_value="None") %}
{% if property.required %}
{% if property.nullable %}
{{ property.python_name }} = {{ source }}
{{ property.python_name }} = isoparse({{ property.python_name }}).date() if {{ property.python_name }} else None
{% else %}
{{ property.python_name }} = isoparse({{ source }}).date()
{% endif %}
{% else %}
{{ property.python_name }} = {{ initial_value }}
_{{ property.python_name }} = {{ source }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
{% macro construct(property, source, initial_value="None") %}
{% if property.required %}
{% if property.nullable %}
{{ property.python_name }} = {{ source }}
{{ property.python_name }} = isoparse({{ property.python_name }}) if {{ property.python_name }} else None
{% else %}
{{ property.python_name }} = isoparse({{ source }})
{% endif %}
{% else %}
{{ property.python_name }} = {{ initial_value }}
_{{ property.python_name }} = {{ source }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@ def _parse_{{ property.python_name }}(data: Any) -> {{ property.get_type_string(
{% endif %}
{% endfor %}

{% if not property.nullable %}
{{ property.python_name }} = _parse_{{ property.python_name }}({{ source }})
{% else %}
{{ property.python_name }} = {{ source }}
if {{ property.python_name }} is not None:
{{ property.python_name }} = _parse_{{ property.python_name }}({{ property.python_name }})
{% endif %}

{% endmacro %}

{% macro transform(property, source, destination, declare_type=True) %}
Expand Down
2 changes: 2 additions & 0 deletions openapi_python_client/templates/tag_init.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import {% for e in collection.endpoints %} {{e.name | snakecase }}, {% endfor %}

84 changes: 84 additions & 0 deletions openapi_python_client/templates/wrapper.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
from typing import Any, Dict, Optional, Union, cast, List
from .client import Client as InnerClient, AuthenticatedClient
from .types import UNSET, Unset


from .models import (
{% for import in imports | sort %}
{{ import }},
{% endfor %}
)

from .api import (
{% for tag, collection in endpoint_collections.items() %}
{{ tag | snakecase }},
{% endfor %}
)

{% from "endpoint_macros.pyi" import arguments, client, kwargs %}

{% for tag, collection in endpoint_collections.items() %}

class {{ tag | pascalcase }}Api:

def __init__(self, client: InnerClient):
self._client = client

{% for endpoint in collection.endpoints %}
async def {{ endpoint.name | snakecase }}(
self,
{{ arguments(endpoint, False) | indent(8) }}
):
{% if endpoint.requires_security %}
client = cast(AuthenticatedClient, self._client)
{% else %}
client = self._client
{% endif %}
return await {{ tag }}.{{ endpoint.name | snakecase }}.asyncio(
{{ kwargs(endpoint) | indent(12) }}
)

{% endfor %}


class Sync{{ tag | pascalcase }}Api:

def __init__(self, client: InnerClient):
self._client = client

{% for endpoint in collection.endpoints %}
def {{ endpoint.name | snakecase }}(
self,
{{ arguments(endpoint, False) | indent(8) }}
):
{% if endpoint.requires_security %}
client = cast(AuthenticatedClient, self._client)
{% else %}
client = self._client
{% endif %}
return {{ tag }}.{{ endpoint.name | snakecase }}.sync(
{{ kwargs(endpoint) | indent(12) }}
)

{% endfor %}

{% endfor %}

{% for prefix in '', 'Sync' %}

class {{ prefix }}{{ client_name }}:
def __init__(self, base_url: Optional[str] = None, timeout: float = 5.0, token: Optional[str] = None):
if token is None:
self.connection = InnerClient(
base_url=base_url,
timeout=timeout)
else:
self.connection = AuthenticatedClient(
base_url=base_url,
timeout=timeout,
token=token)
{% for tag, collection in endpoint_collections.items() %}
self.{{ tag | snakecase }} = {{ prefix }}{{ tag | pascalcase }}Api(self.connection)
{% endfor %}

{% endfor %}
Loading