Skip to content

Commit f1d67dc

Browse files
authored
python: Update api_resource template to support sub-resources (#1840)
Part of svix/monorepo-private#10043.
2 parents a813400 + aa5b8b1 commit f1d67dc

File tree

5 files changed

+149
-4
lines changed

5 files changed

+149
-4
lines changed

codegen.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ output_dir = "svix-cli/src/cmds/api"
6161
[python]
6262
template_dir = "python/templates"
6363
extra_shell_commands = [
64-
"rm python/svix/api/{environment,health,ingest,operational_webhook}.py",
64+
"rm python/svix/api/{health,ingest}.py",
6565
]
6666
[[python.task]]
6767
template = "python/templates/api_resource.py.jinja"

python/svix/api/environment.py

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# This file is @generated
2+
import typing as t
3+
from dataclasses import dataclass
4+
5+
from ..models import EnvironmentIn, EnvironmentOut
6+
from .common import ApiBase, BaseOptions, serialize_params
7+
8+
9+
@dataclass
10+
class EnvironmentExportOptions(BaseOptions):
11+
idempotency_key: t.Optional[str] = None
12+
13+
def _header_params(self) -> t.Dict[str, str]:
14+
return serialize_params(
15+
{
16+
"idempotency-key": self.idempotency_key,
17+
}
18+
)
19+
20+
21+
@dataclass
22+
class EnvironmentImportOptions(BaseOptions):
23+
idempotency_key: t.Optional[str] = None
24+
25+
def _header_params(self) -> t.Dict[str, str]:
26+
return serialize_params(
27+
{
28+
"idempotency-key": self.idempotency_key,
29+
}
30+
)
31+
32+
33+
class EnvironmentAsync(ApiBase):
34+
async def export(
35+
self, options: EnvironmentExportOptions = EnvironmentExportOptions()
36+
) -> EnvironmentOut:
37+
"""Download a JSON file containing all org-settings and event types."""
38+
response = await self._request_asyncio(
39+
method="post",
40+
path="/api/v1/environment/export",
41+
path_params={},
42+
query_params=options._query_params(),
43+
header_params=options._header_params(),
44+
)
45+
return EnvironmentOut.model_validate(response.json())
46+
47+
async def import_(
48+
self,
49+
environment_in: EnvironmentIn,
50+
options: EnvironmentImportOptions = EnvironmentImportOptions(),
51+
) -> None:
52+
"""Import a configuration into the active organization.
53+
54+
It doesn't delete anything, only adds / updates what was passed to it."""
55+
await self._request_asyncio(
56+
method="post",
57+
path="/api/v1/environment/import",
58+
path_params={},
59+
query_params=options._query_params(),
60+
header_params=options._header_params(),
61+
json_body=environment_in.model_dump_json(exclude_unset=True, by_alias=True),
62+
)
63+
64+
65+
class Environment(ApiBase):
66+
def export(
67+
self, options: EnvironmentExportOptions = EnvironmentExportOptions()
68+
) -> EnvironmentOut:
69+
"""Download a JSON file containing all org-settings and event types."""
70+
response = self._request_sync(
71+
method="post",
72+
path="/api/v1/environment/export",
73+
path_params={},
74+
query_params=options._query_params(),
75+
header_params=options._header_params(),
76+
)
77+
return EnvironmentOut.model_validate(response.json())
78+
79+
def import_(
80+
self,
81+
environment_in: EnvironmentIn,
82+
options: EnvironmentImportOptions = EnvironmentImportOptions(),
83+
) -> None:
84+
"""Import a configuration into the active organization.
85+
86+
It doesn't delete anything, only adds / updates what was passed to it."""
87+
self._request_sync(
88+
method="post",
89+
path="/api/v1/environment/import",
90+
path_params={},
91+
query_params=options._query_params(),
92+
header_params=options._header_params(),
93+
json_body=environment_in.model_dump_json(exclude_unset=True, by_alias=True),
94+
)
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# This file is @generated
2+
from .common import ApiBase
3+
from .operational_webhook_endpoint import (
4+
OperationalWebhookEndpoint,
5+
OperationalWebhookEndpointAsync,
6+
)
7+
8+
9+
class OperationalWebhookAsync(ApiBase):
10+
@property
11+
def endpoint(self) -> OperationalWebhookEndpointAsync:
12+
return OperationalWebhookEndpointAsync(self._client)
13+
14+
15+
class OperationalWebhook(ApiBase):
16+
@property
17+
def endpoint(self) -> OperationalWebhookEndpoint:
18+
return OperationalWebhookEndpoint(self._client)

python/svix/api/svix.py

+18
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
from .application import Application, ApplicationAsync
55
from .authentication import Authentication, AuthenticationAsync
66
from .endpoint import Endpoint, EndpointAsync
7+
from .environment import Environment, EnvironmentAsync
78
from .event_type import EventType, EventTypeAsync
89
from .integration import Integration, IntegrationAsync
910
from .message import Message, MessageAsync
1011
from .message_attempt import MessageAttempt, MessageAttemptAsync
12+
from .operational_webhook import OperationalWebhook, OperationalWebhookAsync
1113
from .operational_webhook_endpoint import (
1214
OperationalWebhookEndpoint,
1315
OperationalWebhookEndpointAsync,
@@ -87,6 +89,10 @@ def application(self) -> ApplicationAsync:
8789
def endpoint(self) -> EndpointAsync:
8890
return EndpointAsync(self._client)
8991

92+
@property
93+
def environment(self) -> EnvironmentAsync:
94+
return EnvironmentAsync(self._client)
95+
9096
@property
9197
def event_type(self) -> EventTypeAsync:
9298
return EventTypeAsync(self._client)
@@ -107,6 +113,10 @@ def message_attempt(self) -> MessageAttemptAsync:
107113
def statistics(self) -> StatisticsAsync:
108114
return StatisticsAsync(self._client)
109115

116+
@property
117+
def operational_webhook(self) -> OperationalWebhookAsync:
118+
return OperationalWebhookAsync(self._client)
119+
110120
@property
111121
def operational_webhook_endpoint(self) -> OperationalWebhookEndpointAsync:
112122
return OperationalWebhookEndpointAsync(self._client)
@@ -125,6 +135,10 @@ def application(self) -> Application:
125135
def endpoint(self) -> Endpoint:
126136
return Endpoint(self._client)
127137

138+
@property
139+
def environment(self) -> Environment:
140+
return Environment(self._client)
141+
128142
@property
129143
def event_type(self) -> EventType:
130144
return EventType(self._client)
@@ -145,6 +159,10 @@ def message_attempt(self) -> MessageAttempt:
145159
def statistics(self) -> Statistics:
146160
return Statistics(self._client)
147161

162+
@property
163+
def operational_webhook(self) -> OperationalWebhook:
164+
return OperationalWebhook(self._client)
165+
148166
@property
149167
def operational_webhook_endpoint(self) -> OperationalWebhookEndpoint:
150168
return OperationalWebhookEndpoint(self._client)

python/templates/api_resource.py.jinja

+18-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ from .. import models
1111

1212
{% for c in referenced_components -%}
1313
from ..models import {{ c | to_upper_camel_case }}
14+
{% endfor -%}
15+
{% for _, sub in resource.subresources | items -%}
16+
from .{{ sub.name | to_snake_case }} import (
17+
{{ sub.name | to_upper_camel_case }},
18+
{{ sub.name | to_upper_camel_case }}Async,
19+
)
1420
{% endfor %}
1521

1622

@@ -65,7 +71,15 @@ class {{ resource_type_name }}{{ op.name | to_upper_camel_case }}Options(BaseOpt
6571

6672
{% for is_async in [true, false] %}
6773
class {{ resource.name | to_upper_camel_case }}{% if is_async %}Async{% endif %}(ApiBase):
68-
{%- if resource.operations | length != 0 %}
74+
{%- for name, sub in resource.subresources | items %}
75+
{%- set sub_type_name %}{{ sub.name | to_upper_camel_case }}{% if is_async %}Async{% endif %}{% endset %}
76+
@property
77+
def {{ name | to_snake_case }}(self) -> {{ sub_type_name }}:
78+
return {{ sub_type_name }}(self._client)
79+
80+
{% endfor %}
81+
82+
{%- if resource.operations | length > 0 %}
6983
{%- for op in resource.operations %}
7084
{% if op.response_body_schema_name is defined -%}
7185
{% set return_type = op.response_body_schema_name | to_upper_camel_case -%}
@@ -142,8 +156,9 @@ class {{ resource.name | to_upper_camel_case }}{% if is_async %}Async{% endif %}
142156

143157
{{ code | indent(4, true) }}
144158
{% endfor -%}
145-
{% else %}
146-
{# empty class with no functions, so we have a pass here #}
159+
{% endif %}
160+
{% if resource.subresources | length == 0 and resource.operations | length == 0 %}
161+
{# empty class with no members, so we have a pass here -#}
147162
pass
148163
{% endif %}
149164
{% endfor %}

0 commit comments

Comments
 (0)