geniespec 0.1.2.dev4__tar.gz → 0.1.2.dev5__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.dev4 → geniespec-0.1.2.dev5}/PKG-INFO +3 -1
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/README.md +2 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/pyproject.toml +1 -1
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/pyproject.toml.orig +1 -1
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/api_schema.yaml +3 -3
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/languages.py +27 -4
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/endpoints.py.j2 +3 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/exceptions.py.j2 +3 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/internal.py.j2 +3 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/resources.py.j2 +3 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/types.py +2 -1
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/__init__.py +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/cli.py +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/genie.py +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/renderable_types.py +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/python-server/{service}/v{version}/api.py.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/typescript-client/{service}/v{version}/client.ts.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/typescript-client/{service}/v{version}/endpoints.ts.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/src/geniespec/templates/typescript-client/{service}/v{version}/index.ts.j2 +0 -0
- {geniespec-0.1.2.dev4 → geniespec-0.1.2.dev5}/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.dev5
|
|
4
4
|
Summary: Generate API code from an api.yaml spec
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Dist: jinja2>=3.1.6
|
|
@@ -68,6 +68,8 @@ resources:
|
|
|
68
68
|
|
|
69
69
|
Fields use it like any other type (`type: ViewContent`, also inside `List` and `Mapping`). `python-server` generates a `ViewContentV1` pydantic discriminated union in `resources`; `typescript-client` generates a `ViewContentV1` union type and a `viewContentV1FromObject` function that builds the member class named by the discriminator (and throws for unknown values).
|
|
70
70
|
|
|
71
|
+
`type: Uuid` is a string that must be a valid UUID. It works anywhere `String` does, including as a primary attribute in paths. `python-server` types it as `uuid.UUID`, so pydantic rejects other strings with a 400, internal methods get `uuid.UUID` objects and responses write them in the standard lowercase hyphenated form; `typescript-client` types it as `string`.
|
|
72
|
+
|
|
71
73
|
## Rate limits
|
|
72
74
|
|
|
73
75
|
Name rate limits at the top level, then pick one per transition with `rateLimit`. `defaultRateLimit` applies to every transition that doesn't set one, and `rateLimit: none` turns it off for a transition, the same way `defaultAuthentication` and `authentication` work:
|
|
@@ -54,6 +54,8 @@ resources:
|
|
|
54
54
|
|
|
55
55
|
Fields use it like any other type (`type: ViewContent`, also inside `List` and `Mapping`). `python-server` generates a `ViewContentV1` pydantic discriminated union in `resources`; `typescript-client` generates a `ViewContentV1` union type and a `viewContentV1FromObject` function that builds the member class named by the discriminator (and throws for unknown values).
|
|
56
56
|
|
|
57
|
+
`type: Uuid` is a string that must be a valid UUID. It works anywhere `String` does, including as a primary attribute in paths. `python-server` types it as `uuid.UUID`, so pydantic rejects other strings with a 400, internal methods get `uuid.UUID` objects and responses write them in the standard lowercase hyphenated form; `typescript-client` types it as `string`.
|
|
58
|
+
|
|
57
59
|
## Rate limits
|
|
58
60
|
|
|
59
61
|
Name rate limits at the top level, then pick one per transition with `rateLimit`. `defaultRateLimit` applies to every transition that doesn't set one, and `rateLimit: none` turns it off for a transition, the same way `defaultAuthentication` and `authentication` work:
|
|
@@ -48,7 +48,7 @@ properties:
|
|
|
48
48
|
type:
|
|
49
49
|
- "null"
|
|
50
50
|
- string
|
|
51
|
-
pattern: '^[a-z][a-z0-
|
|
51
|
+
pattern: '^[a-z][a-z0-9_-]*$'
|
|
52
52
|
rateLimits:
|
|
53
53
|
type: array
|
|
54
54
|
items:
|
|
@@ -230,7 +230,7 @@ definitions:
|
|
|
230
230
|
type:
|
|
231
231
|
- "null"
|
|
232
232
|
- string
|
|
233
|
-
pattern: '^[a-z][a-z0-
|
|
233
|
+
pattern: '^[a-z][a-z0-9_-]*$'
|
|
234
234
|
rateLimit:
|
|
235
235
|
type:
|
|
236
236
|
- "null"
|
|
@@ -266,7 +266,7 @@ definitions:
|
|
|
266
266
|
type:
|
|
267
267
|
- "null"
|
|
268
268
|
- string
|
|
269
|
-
pattern: '^[a-z][a-z0-
|
|
269
|
+
pattern: '^[a-z][a-z0-9_-]*$'
|
|
270
270
|
rateLimit:
|
|
271
271
|
type:
|
|
272
272
|
- "null"
|
|
@@ -73,6 +73,9 @@ class BaseLanguageDefinition:
|
|
|
73
73
|
def string_type(self, isNullable: bool) -> str:
|
|
74
74
|
raise NotImplementedError
|
|
75
75
|
|
|
76
|
+
def uuid_type(self, isNullable: bool) -> str:
|
|
77
|
+
raise NotImplementedError
|
|
78
|
+
|
|
76
79
|
def enum_type(self, isNullable: bool, renderableType: RenderableType, apiVersion: Version, isLocalReference: bool) -> str:
|
|
77
80
|
raise NotImplementedError
|
|
78
81
|
|
|
@@ -110,6 +113,8 @@ class BaseLanguageDefinition:
|
|
|
110
113
|
return self.double_type(isNullable=isNullable)
|
|
111
114
|
if yamlType == PrimitiveTypes.STRING:
|
|
112
115
|
return self.string_type(isNullable=isNullable)
|
|
116
|
+
if yamlType == PrimitiveTypes.UUID:
|
|
117
|
+
return self.uuid_type(isNullable=isNullable)
|
|
113
118
|
if yamlType == PrimitiveTypes.BOOLEAN:
|
|
114
119
|
return self.boolean_type(isNullable=isNullable)
|
|
115
120
|
if yamlType == PrimitiveTypes.DATETIME:
|
|
@@ -227,9 +232,9 @@ class BaseLanguageDefinition:
|
|
|
227
232
|
return output
|
|
228
233
|
if component.attribute.isUnique and not component.attribute.isPrimary:
|
|
229
234
|
output.append(self.kebab_name(name=component.attribute.name))
|
|
230
|
-
if component.attribute.fieldType.rawType not in (PrimitiveTypes.INTEGER, PrimitiveTypes.LONG_INTEGER, PrimitiveTypes.STRING):
|
|
231
|
-
raise KibaException(message=f'ResourceEndpointComponent created with an invalid attribute type of {component.attribute.fieldType}. Valid types are: integer, long integer and
|
|
232
|
-
output.append(self.path_parameter_segment(parameterName=self.identifier(name=component.attribute.name), isInteger=component.attribute.fieldType.rawType
|
|
235
|
+
if component.attribute.fieldType.rawType not in (PrimitiveTypes.INTEGER, PrimitiveTypes.LONG_INTEGER, PrimitiveTypes.STRING, PrimitiveTypes.UUID):
|
|
236
|
+
raise KibaException(message=f'ResourceEndpointComponent created with an invalid attribute type of {component.attribute.fieldType}. Valid types are: integer, long integer, string and uuid.')
|
|
237
|
+
output.append(self.path_parameter_segment(parameterName=self.identifier(name=component.attribute.name), isInteger=component.attribute.fieldType.rawType in (PrimitiveTypes.INTEGER, PrimitiveTypes.LONG_INTEGER)))
|
|
233
238
|
return output
|
|
234
239
|
raise KibaException(message=f'Unsupported endpoint component: {type(component)}')
|
|
235
240
|
|
|
@@ -343,6 +348,9 @@ class PythonLanguageDefinition(BaseLanguageDefinition):
|
|
|
343
348
|
def string_type(self, isNullable: bool) -> str:
|
|
344
349
|
return 'str | None' if isNullable else 'str'
|
|
345
350
|
|
|
351
|
+
def uuid_type(self, isNullable: bool) -> str:
|
|
352
|
+
return 'uuid.UUID | None' if isNullable else 'uuid.UUID'
|
|
353
|
+
|
|
346
354
|
def enum_type(self, isNullable: bool, renderableType: RenderableType, apiVersion: Version, isLocalReference: bool) -> str:
|
|
347
355
|
if renderableType.className is None:
|
|
348
356
|
typeName = self.enum_literal(values=renderableType.enumValues)
|
|
@@ -423,6 +431,18 @@ class PythonLanguageDefinition(BaseLanguageDefinition):
|
|
|
423
431
|
return PythonLanguageDefinition._contains_json(renderableType=renderableType.keyType) or PythonLanguageDefinition._contains_json(renderableType=renderableType.valueType)
|
|
424
432
|
return renderableType.rawType == PrimitiveTypes.JSON
|
|
425
433
|
|
|
434
|
+
@staticmethod
|
|
435
|
+
def _contains_uuid(renderableType: RenderableType) -> bool:
|
|
436
|
+
if isinstance(renderableType, MappingRenderableType):
|
|
437
|
+
return PythonLanguageDefinition._contains_uuid(renderableType=renderableType.keyType) or PythonLanguageDefinition._contains_uuid(renderableType=renderableType.valueType)
|
|
438
|
+
return renderableType.rawType == PrimitiveTypes.UUID
|
|
439
|
+
|
|
440
|
+
def requires_uuid(self, api: RenderableApi) -> bool:
|
|
441
|
+
fieldTypes = [attribute.fieldType for resource in api.resources for attribute in [*resource.attributes, *resource.independentAttributes]]
|
|
442
|
+
fieldTypes += [parameter.fieldType for operation in api.operations for parameter in operation.parameters] + [field.fieldType for operation in api.operations for field in operation.responseFields or []]
|
|
443
|
+
fieldTypes += [field.fieldType for exception in api.exceptions for field in exception.fields]
|
|
444
|
+
return any(self._contains_uuid(renderableType=fieldType) for fieldType in fieldTypes)
|
|
445
|
+
|
|
426
446
|
def resources_require_json(self, api: RenderableApi) -> bool:
|
|
427
447
|
return any(self._contains_json(renderableType=attribute.fieldType) for resource in api.resources for attribute in resource.attributes)
|
|
428
448
|
|
|
@@ -562,6 +582,9 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
562
582
|
def string_type(self, isNullable: bool) -> str:
|
|
563
583
|
return self._nullable(typeName='string', isNullable=isNullable)
|
|
564
584
|
|
|
585
|
+
def uuid_type(self, isNullable: bool) -> str:
|
|
586
|
+
return self._nullable(typeName='string', isNullable=isNullable)
|
|
587
|
+
|
|
565
588
|
def enum_type(self, isNullable: bool, renderableType: RenderableType, apiVersion: Version, isLocalReference: bool) -> str:
|
|
566
589
|
if renderableType.className is None:
|
|
567
590
|
return self._nullable(typeName=f'({self.enum_union(values=renderableType.enumValues)})', isNullable=isNullable)
|
|
@@ -680,7 +703,7 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
680
703
|
return f'{parserName if isLocalReference else f"Resources.{parserName}"}({value} as RawObject)'
|
|
681
704
|
if renderableType.rawType == 'class' and renderableType.className is not None:
|
|
682
705
|
return f'{self.type(renderableType=renderableType, apiVersion=apiVersion, isLocalReference=isLocalReference)}.fromObject({value} as RawObject)'
|
|
683
|
-
if renderableType.rawType
|
|
706
|
+
if renderableType.rawType in (PrimitiveTypes.STRING, PrimitiveTypes.UUID):
|
|
684
707
|
return f'String({value})'
|
|
685
708
|
if renderableType.rawType in (PrimitiveTypes.INTEGER, PrimitiveTypes.LONG_INTEGER, PrimitiveTypes.FLOAT, PrimitiveTypes.DOUBLE):
|
|
686
709
|
return f'Number({value})'
|
|
@@ -4,6 +4,9 @@ import datetime
|
|
|
4
4
|
{% if target.requires_optional_field_default(api=api) or target.operations_require_typing(api=api) %}
|
|
5
5
|
import typing
|
|
6
6
|
{% endif %}
|
|
7
|
+
{% if target.requires_uuid(api=api) %}
|
|
8
|
+
import uuid
|
|
9
|
+
{% endif %}
|
|
7
10
|
|
|
8
11
|
{% if target.operations_require_json(api=api) %}
|
|
9
12
|
import pydantic
|
|
@@ -12,11 +12,12 @@ class PrimitiveTypes:
|
|
|
12
12
|
FLOAT = 'Float'
|
|
13
13
|
DOUBLE = 'Double'
|
|
14
14
|
STRING = 'String'
|
|
15
|
+
UUID = 'Uuid'
|
|
15
16
|
BOOLEAN = 'Boolean'
|
|
16
17
|
DATETIME = 'Datetime'
|
|
17
18
|
DATE = 'Date'
|
|
18
19
|
JSON = 'Json'
|
|
19
|
-
ALL: ClassVar[list[str]] = [LONG_INTEGER, INTEGER, FLOAT, DOUBLE, STRING, BOOLEAN, DATETIME, DATE, JSON]
|
|
20
|
+
ALL: ClassVar[list[str]] = [LONG_INTEGER, INTEGER, FLOAT, DOUBLE, STRING, UUID, BOOLEAN, DATETIME, DATE, JSON]
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
class FieldSources:
|
|
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
|