geniespec 0.1.2.dev8__tar.gz → 0.1.2.dev11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/PKG-INFO +2 -1
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/README.md +1 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/pyproject.toml +2 -6
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/pyproject.toml.orig +2 -7
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/api_schema.yaml +11 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/genie.py +21 -7
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/types.py +5 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/__init__.py +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/cli.py +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/languages.py +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/renderable_types.py +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/api.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/endpoints.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/exceptions.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/internal.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/python-server/{service}/v{version}/resources.py.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/typescript-client/{service}/v{version}/client.ts.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/typescript-client/{service}/v{version}/endpoints.ts.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/typescript-client/{service}/v{version}/index.ts.j2 +0 -0
- {geniespec-0.1.2.dev8 → geniespec-0.1.2.dev11}/src/geniespec/templates/typescript-client/{service}/v{version}/resources.ts.j2 +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: geniespec
|
|
3
|
-
Version: 0.1.2.
|
|
3
|
+
Version: 0.1.2.dev11
|
|
4
4
|
Summary: Generate API code from an api.yaml spec
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Dist: jinja2>=3.1.6
|
|
@@ -124,6 +124,7 @@ resources:
|
|
|
124
124
|
`overrides` keep an API that existed before genie working the same way once it moves to genie. They are meant to be dropped in the next major version of that API.
|
|
125
125
|
|
|
126
126
|
- `shouldPrefixParentName: false` on a child resource names it without its parent's name: `Agent` under `User` stays `Agent` (not `UserAgent`), so its primary attribute is `agent-id` rather than `user-agent-id` and its fields keep their names. Its path is unchanged (`/users/{userId}/agents/{agentId}`).
|
|
127
|
+
- `responseFieldName` on a `GET`, `LIST`, `CREATE` or `UPDATE` transition renames the field its response puts the resource in (for example `memories` instead of `agentMemories`). Custom transitions name it with `responseField`.
|
|
127
128
|
|
|
128
129
|
# Development
|
|
129
130
|
|
|
@@ -110,6 +110,7 @@ resources:
|
|
|
110
110
|
`overrides` keep an API that existed before genie working the same way once it moves to genie. They are meant to be dropped in the next major version of that API.
|
|
111
111
|
|
|
112
112
|
- `shouldPrefixParentName: false` on a child resource names it without its parent's name: `Agent` under `User` stays `Agent` (not `UserAgent`), so its primary attribute is `agent-id` rather than `user-agent-id` and its fields keep their names. Its path is unchanged (`/users/{userId}/agents/{agentId}`).
|
|
113
|
+
- `responseFieldName` on a `GET`, `LIST`, `CREATE` or `UPDATE` transition renames the field its response puts the resource in (for example `memories` instead of `agentMemories`). Custom transitions name it with `responseField`.
|
|
113
114
|
|
|
114
115
|
# Development
|
|
115
116
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "geniespec"
|
|
3
|
-
version = "0.1.2.
|
|
3
|
+
version = "0.1.2.dev11"
|
|
4
4
|
description = "Generate API code from an api.yaml spec"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -21,7 +21,7 @@ repository = "https://github.com/kibalabs/genie"
|
|
|
21
21
|
|
|
22
22
|
[dependency-groups]
|
|
23
23
|
dev = [
|
|
24
|
-
"kiba-build==0.1.11.
|
|
24
|
+
"kiba-build==0.1.11.dev24",
|
|
25
25
|
"kiba-core[core-api,requester]>=0.5.3.dev87,<0.5.4",
|
|
26
26
|
]
|
|
27
27
|
|
|
@@ -31,7 +31,3 @@ build-backend = "uv_build"
|
|
|
31
31
|
|
|
32
32
|
[tool.pytest.ini_options]
|
|
33
33
|
pythonpath = ["src"]
|
|
34
|
-
|
|
35
|
-
[tool.bumpversion]
|
|
36
|
-
search = 'version = "{current_version}"'
|
|
37
|
-
replace = 'version = "{new_version}"'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "geniespec"
|
|
3
|
-
version = "0.1.2.
|
|
3
|
+
version = "0.1.2.dev11"
|
|
4
4
|
description = "Generate API code from an api.yaml spec"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "MIT"
|
|
@@ -21,7 +21,7 @@ repository = "https://github.com/kibalabs/genie"
|
|
|
21
21
|
|
|
22
22
|
[dependency-groups]
|
|
23
23
|
dev = [
|
|
24
|
-
"kiba-build==0.1.11.
|
|
24
|
+
"kiba-build==0.1.11.dev24",
|
|
25
25
|
"kiba-core[core-api,requester]>=0.5.3.dev87,<0.5.4",
|
|
26
26
|
]
|
|
27
27
|
|
|
@@ -31,8 +31,3 @@ build-backend = "uv_build"
|
|
|
31
31
|
|
|
32
32
|
[tool.pytest.ini_options]
|
|
33
33
|
pythonpath = ["src"]
|
|
34
|
-
|
|
35
|
-
# NOTE(krishan711): without this, bumping the version also rewrites dependency pins that contain it (e.g. 0.1.1 inside kiba-build==0.1.11.dev15)
|
|
36
|
-
[tool.bumpversion]
|
|
37
|
-
search = "version = \"{current_version}\""
|
|
38
|
-
replace = "version = \"{new_version}\""
|
|
@@ -263,6 +263,8 @@ definitions:
|
|
|
263
263
|
type: string
|
|
264
264
|
extensions:
|
|
265
265
|
type: object
|
|
266
|
+
overrides:
|
|
267
|
+
$ref: '#/definitions/TransitionOverrides'
|
|
266
268
|
Transition:
|
|
267
269
|
type: object
|
|
268
270
|
additionalProperties: false
|
|
@@ -319,6 +321,15 @@ definitions:
|
|
|
319
321
|
type: string
|
|
320
322
|
extensions:
|
|
321
323
|
type: object
|
|
324
|
+
overrides:
|
|
325
|
+
$ref: '#/definitions/TransitionOverrides'
|
|
326
|
+
TransitionOverrides:
|
|
327
|
+
type: object
|
|
328
|
+
additionalProperties: false
|
|
329
|
+
properties:
|
|
330
|
+
responseFieldName:
|
|
331
|
+
type: string
|
|
332
|
+
pattern: '^[a-z][A-Za-z0-9-]*$'
|
|
322
333
|
RootTransition:
|
|
323
334
|
type: object
|
|
324
335
|
allOf:
|
|
@@ -264,6 +264,15 @@ class Renderer:
|
|
|
264
264
|
def _operation_documentation(transition: BaseTransition) -> dict[str, object]:
|
|
265
265
|
return {'operationId': transition.operationId, 'summary': transition.summary, 'description': transition.description, 'tags': transition.tags, 'extensions': transition.extensions}
|
|
266
266
|
|
|
267
|
+
def _with_transition_fields(self, operation: RenderableOperation, transition: BaseTransition, isStandard: bool) -> RenderableOperation:
|
|
268
|
+
update = self._operation_documentation(transition=transition)
|
|
269
|
+
responseFieldName = transition.overrides.responseFieldName
|
|
270
|
+
if responseFieldName is not None:
|
|
271
|
+
if not isStandard or not operation.responseFields:
|
|
272
|
+
raise SemanticValidationException(message=f'Only GET, LIST, CREATE and UPDATE transitions can override responseFieldName: {transition.action}')
|
|
273
|
+
update['responseFields'] = [field.model_copy(update={'name': RenderableString.from_kebab_case_string(string=responseFieldName)}) for field in operation.responseFields]
|
|
274
|
+
return operation.model_copy(update=update)
|
|
275
|
+
|
|
267
276
|
@staticmethod
|
|
268
277
|
def _resource_full_name(resource: Resource, name: str) -> str:
|
|
269
278
|
return f'{resource.parentResource or ""}{name}' if resource.overrides.shouldPrefixParentName else name
|
|
@@ -462,13 +471,17 @@ class Renderer:
|
|
|
462
471
|
if resourceErrors:
|
|
463
472
|
raise SemanticValidationException(message='\n'.join(resourceErrors))
|
|
464
473
|
renderableOperations = [
|
|
465
|
-
self.
|
|
474
|
+
self._with_transition_fields(
|
|
475
|
+
operation=self._action_operation(
|
|
476
|
+
transition=transition,
|
|
477
|
+
endpoint=RenderableEndpoint(components=[ActionEndpointComponent(actionName=RenderableString.from_separated_string(string=transition.action, separator='-'))]),
|
|
478
|
+
knownTypeNames=knownTypeNames,
|
|
479
|
+
defaultAuthentication=api.defaultAuthentication,
|
|
480
|
+
defaultRateLimit=api.defaultRateLimit,
|
|
481
|
+
),
|
|
466
482
|
transition=transition,
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
defaultAuthentication=api.defaultAuthentication,
|
|
470
|
-
defaultRateLimit=api.defaultRateLimit,
|
|
471
|
-
).model_copy(update=self._operation_documentation(transition=transition))
|
|
483
|
+
isStandard=False,
|
|
484
|
+
)
|
|
472
485
|
for transition in api.transitions
|
|
473
486
|
]
|
|
474
487
|
renderableExceptions = [
|
|
@@ -574,7 +587,8 @@ class Renderer:
|
|
|
574
587
|
for endpoint in customEndpoints:
|
|
575
588
|
customEndpoint = RenderableEndpoint(components=[*endpoint.components, ActionEndpointComponent(actionName=RenderableString.from_separated_string(string=transition.action, separator='-'))])
|
|
576
589
|
renderableApi.operations.append(self._action_operation(transition=transition, endpoint=customEndpoint, knownTypeNames=knownTypeNames, defaultAuthentication=api.defaultAuthentication, defaultRateLimit=api.defaultRateLimit, isIndirectAction=transition.isIndirectAction))
|
|
577
|
-
|
|
590
|
+
isStandard = transition.action.upper() in {'CREATE', 'UPDATE', 'GET', 'LIST'}
|
|
591
|
+
renderableApi.operations[operationCount:] = [self._with_transition_fields(operation=operation, transition=transition, isStandard=isStandard) for operation in renderableApi.operations[operationCount:]]
|
|
578
592
|
if len(renderableApi.operations) == operationCount:
|
|
579
593
|
uncoveredTransitions.append(f'{renderableResource.singleName.pascalCaseString} {transition.action}')
|
|
580
594
|
if uncoveredTransitions:
|
|
@@ -117,6 +117,10 @@ class RequestField(BaseModel):
|
|
|
117
117
|
description: str | None = None
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
class TransitionOverrides(BaseModel):
|
|
121
|
+
responseFieldName: str | None = None
|
|
122
|
+
|
|
123
|
+
|
|
120
124
|
class BaseTransition(BaseModel):
|
|
121
125
|
action: str
|
|
122
126
|
method: str | None = None
|
|
@@ -130,6 +134,7 @@ class BaseTransition(BaseModel):
|
|
|
130
134
|
description: str | None = None
|
|
131
135
|
tags: list[str] = []
|
|
132
136
|
extensions: dict[str, pydantic.JsonValue] = {}
|
|
137
|
+
overrides: TransitionOverrides = TransitionOverrides()
|
|
133
138
|
|
|
134
139
|
|
|
135
140
|
class Transition(BaseTransition):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|