geniespec 0.1.2.dev7__tar.gz → 0.1.2.dev8__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.dev7 → geniespec-0.1.2.dev8}/PKG-INFO +3 -1
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/README.md +2 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/pyproject.toml +1 -1
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/pyproject.toml.orig +1 -1
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/languages.py +27 -7
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/resources.py.j2 +5 -1
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/types.py +2 -1
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/__init__.py +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/api_schema.yaml +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/cli.py +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/genie.py +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/renderable_types.py +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/__init__.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/api.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/endpoints.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/exceptions.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/python-server/{service}/v{version}/internal.py.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/typescript-client/{service}/v{version}/client.ts.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/typescript-client/{service}/v{version}/endpoints.ts.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/src/geniespec/templates/typescript-client/{service}/v{version}/index.ts.j2 +0 -0
- {geniespec-0.1.2.dev7 → geniespec-0.1.2.dev8}/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.dev8
|
|
4
4
|
Summary: Generate API code from an api.yaml spec
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Requires-Dist: jinja2>=3.1.6
|
|
@@ -70,6 +70,8 @@ Fields use it like any other type (`type: ViewContent`, also inside `List` and `
|
|
|
70
70
|
|
|
71
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
72
|
|
|
73
|
+
`type: BigInt` is an integer of any size that travels as a JSON string, because JSON numbers past 2^53 lose precision in JavaScript. `python-server` types it as `int` (a `BigInt` alias in `resources`), accepts `"123"` or `123` in requests, always writes it as a string and documents it as `{"type": "string"}`; `typescript-client` types it as `bigint`, parsed with `BigInt(...)` and sent with `String(...)`.
|
|
74
|
+
|
|
73
75
|
## Rate limits
|
|
74
76
|
|
|
75
77
|
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:
|
|
@@ -56,6 +56,8 @@ Fields use it like any other type (`type: ViewContent`, also inside `List` and `
|
|
|
56
56
|
|
|
57
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
58
|
|
|
59
|
+
`type: BigInt` is an integer of any size that travels as a JSON string, because JSON numbers past 2^53 lose precision in JavaScript. `python-server` types it as `int` (a `BigInt` alias in `resources`), accepts `"123"` or `123` in requests, always writes it as a string and documents it as `{"type": "string"}`; `typescript-client` types it as `bigint`, parsed with `BigInt(...)` and sent with `String(...)`.
|
|
60
|
+
|
|
59
61
|
## Rate limits
|
|
60
62
|
|
|
61
63
|
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:
|
|
@@ -78,6 +78,9 @@ class BaseLanguageDefinition:
|
|
|
78
78
|
def uuid_type(self, isNullable: bool) -> str:
|
|
79
79
|
raise NotImplementedError
|
|
80
80
|
|
|
81
|
+
def big_int_type(self, isNullable: bool, isLocalReference: bool) -> str:
|
|
82
|
+
raise NotImplementedError
|
|
83
|
+
|
|
81
84
|
def enum_type(self, isNullable: bool, renderableType: RenderableType, apiVersion: Version, isLocalReference: bool) -> str:
|
|
82
85
|
raise NotImplementedError
|
|
83
86
|
|
|
@@ -117,6 +120,8 @@ class BaseLanguageDefinition:
|
|
|
117
120
|
return self.string_type(isNullable=isNullable)
|
|
118
121
|
if yamlType == PrimitiveTypes.UUID:
|
|
119
122
|
return self.uuid_type(isNullable=isNullable)
|
|
123
|
+
if yamlType == PrimitiveTypes.BIG_INT:
|
|
124
|
+
return self.big_int_type(isNullable=isNullable, isLocalReference=isLocalReference)
|
|
120
125
|
if yamlType == PrimitiveTypes.BOOLEAN:
|
|
121
126
|
return self.boolean_type(isNullable=isNullable)
|
|
122
127
|
if yamlType == PrimitiveTypes.DATETIME:
|
|
@@ -353,6 +358,10 @@ class PythonLanguageDefinition(BaseLanguageDefinition):
|
|
|
353
358
|
def uuid_type(self, isNullable: bool) -> str:
|
|
354
359
|
return 'uuid.UUID | None' if isNullable else 'uuid.UUID'
|
|
355
360
|
|
|
361
|
+
def big_int_type(self, isNullable: bool, isLocalReference: bool) -> str:
|
|
362
|
+
typeName = 'BigInt' if isLocalReference else 'resources.BigInt'
|
|
363
|
+
return f'{typeName} | None' if isNullable else typeName
|
|
364
|
+
|
|
356
365
|
def enum_type(self, isNullable: bool, renderableType: RenderableType, apiVersion: Version, isLocalReference: bool) -> str:
|
|
357
366
|
if renderableType.className is None:
|
|
358
367
|
typeName = self.enum_literal(values=renderableType.enumValues)
|
|
@@ -412,10 +421,6 @@ class PythonLanguageDefinition(BaseLanguageDefinition):
|
|
|
412
421
|
hasResponseDescriptions = any(field.description is not None for operation in api.operations for field in operation.responseFields or [])
|
|
413
422
|
return self.requires_optional_field_default(api=api) or hasRequestDescriptions or hasResponseDescriptions
|
|
414
423
|
|
|
415
|
-
@staticmethod
|
|
416
|
-
def resources_require_field(api: RenderableApi) -> bool:
|
|
417
|
-
return any(attribute.description is not None for resource in api.resources for attribute in resource.attributes)
|
|
418
|
-
|
|
419
424
|
@staticmethod
|
|
420
425
|
def _field_default(default: str | None, description: str | None, fieldFunction: str = 'Field', shouldUseField: bool = False) -> str:
|
|
421
426
|
if description is None and not shouldUseField:
|
|
@@ -487,13 +492,21 @@ class PythonLanguageDefinition(BaseLanguageDefinition):
|
|
|
487
492
|
'collections': lambda part: part.isList or isinstance(part, MappingRenderableType),
|
|
488
493
|
'datetime': lambda part: part.rawType in (PrimitiveTypes.DATETIME, PrimitiveTypes.DATE),
|
|
489
494
|
'json': lambda part: part.rawType == PrimitiveTypes.JSON,
|
|
490
|
-
'resources': lambda part: part.className is not None,
|
|
495
|
+
'resources': lambda part: part.className is not None or part.rawType == PrimitiveTypes.BIG_INT,
|
|
491
496
|
'uuid': lambda part: part.rawType == PrimitiveTypes.UUID,
|
|
492
497
|
}
|
|
493
498
|
return any(predicates[requirement](part) for fieldType in self._module_field_types(api=api, module=module) for part in self._type_parts(renderableType=fieldType))
|
|
494
499
|
|
|
500
|
+
def requires_big_int(self, api: RenderableApi) -> bool:
|
|
501
|
+
return any(part.rawType == PrimitiveTypes.BIG_INT for module in ('resources', 'internal', 'exceptions') for fieldType in self._module_field_types(api=api, module=module) for part in self._type_parts(renderableType=fieldType))
|
|
502
|
+
|
|
495
503
|
def resources_require_typing(self, api: RenderableApi) -> bool:
|
|
496
|
-
|
|
504
|
+
hasInlineEnums = any(self.is_inline_enum(renderableType=attribute.fieldType) for resource in api.resources for attribute in resource.attributes)
|
|
505
|
+
return len(api.enums) > 0 or len(api.oneOfs) > 0 or hasInlineEnums or self.requires_big_int(api=api)
|
|
506
|
+
|
|
507
|
+
def resources_require_pydantic(self, api: RenderableApi) -> bool:
|
|
508
|
+
hasDescriptions = any(attribute.description is not None for resource in api.resources for attribute in resource.attributes)
|
|
509
|
+
return len(api.oneOfs) > 0 or hasDescriptions or self.module_requires(api=api, module='resources', requirement='json') or self.requires_big_int(api=api)
|
|
497
510
|
|
|
498
511
|
def one_of_alias(self, oneOf: RenderableOneOf, apiVersion: Version) -> str:
|
|
499
512
|
return f'typing.Annotated[{" | ".join(self.one_of_member_class_names(oneOf=oneOf, apiVersion=apiVersion))}, pydantic.Field(discriminator={self.identifier(name=oneOf.discriminator)!r})]'
|
|
@@ -602,6 +615,9 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
602
615
|
def long_integer_type(self, isNullable: bool) -> str:
|
|
603
616
|
return self._nullable(typeName='number', isNullable=isNullable)
|
|
604
617
|
|
|
618
|
+
def big_int_type(self, isNullable: bool, isLocalReference: bool) -> str: # noqa: ARG002
|
|
619
|
+
return self._nullable(typeName='bigint', isNullable=isNullable)
|
|
620
|
+
|
|
605
621
|
def mapping_type(self, isNullable: bool, keyType: str, valueType: str) -> str: # noqa: ARG002
|
|
606
622
|
# NOTE(krishan711): json object keys are always strings
|
|
607
623
|
return self._nullable(typeName=f'Record<string, {valueType}>', isNullable=isNullable)
|
|
@@ -752,6 +768,8 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
752
768
|
return f'String({value})'
|
|
753
769
|
if renderableType.rawType in (PrimitiveTypes.INTEGER, PrimitiveTypes.LONG_INTEGER, PrimitiveTypes.FLOAT, PrimitiveTypes.DOUBLE):
|
|
754
770
|
return f'Number({value})'
|
|
771
|
+
if renderableType.rawType == PrimitiveTypes.BIG_INT:
|
|
772
|
+
return f'BigInt(String({value}))'
|
|
755
773
|
if renderableType.rawType == PrimitiveTypes.BOOLEAN:
|
|
756
774
|
return f'Boolean({value})'
|
|
757
775
|
if renderableType.rawType in (PrimitiveTypes.DATE, PrimitiveTypes.DATETIME):
|
|
@@ -765,7 +783,7 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
765
783
|
def _is_serialized_as_is(self, renderableType: RenderableType) -> bool:
|
|
766
784
|
if isinstance(renderableType, MappingRenderableType):
|
|
767
785
|
return self._is_serialized_as_is(renderableType=renderableType.valueType)
|
|
768
|
-
return renderableType.rawType not in ('class', RenderableRawTypes.ONE_OF, PrimitiveTypes.DATE, PrimitiveTypes.DATETIME)
|
|
786
|
+
return renderableType.rawType not in ('class', RenderableRawTypes.ONE_OF, PrimitiveTypes.DATE, PrimitiveTypes.DATETIME, PrimitiveTypes.BIG_INT)
|
|
769
787
|
|
|
770
788
|
def to_object(self, renderableType: RenderableType, value: str, apiVersion: Version, isOptional: bool = False, isLocalReference: bool = False) -> str:
|
|
771
789
|
if self._is_serialized_as_is(renderableType=renderableType):
|
|
@@ -787,4 +805,6 @@ class TypeScriptLanguageDefinition(BaseLanguageDefinition):
|
|
|
787
805
|
return f'dateToString({value})'
|
|
788
806
|
if renderableType.rawType == PrimitiveTypes.DATE:
|
|
789
807
|
return f"dateToString({value}, 'yyyy-MM-dd')"
|
|
808
|
+
if renderableType.rawType == PrimitiveTypes.BIG_INT:
|
|
809
|
+
return f'String({value})'
|
|
790
810
|
raise KibaException(f'Failed to render conversion to object for: {renderableType}')
|
|
@@ -14,13 +14,17 @@ import typing
|
|
|
14
14
|
import uuid
|
|
15
15
|
{% endif %}
|
|
16
16
|
|
|
17
|
-
{% if target.
|
|
17
|
+
{% if target.resources_require_pydantic(api=api) %}
|
|
18
18
|
import pydantic
|
|
19
19
|
{% endif %}
|
|
20
20
|
{% if api.resources %}
|
|
21
21
|
from pydantic import BaseModel
|
|
22
22
|
{% endif %}
|
|
23
23
|
|
|
24
|
+
{% if target.requires_big_int(api=api) %}
|
|
25
|
+
BigInt = typing.Annotated[int, pydantic.PlainSerializer(str, return_type=str), pydantic.WithJsonSchema({'type': 'string'})]
|
|
26
|
+
|
|
27
|
+
{% endif %}
|
|
24
28
|
{% for enum in api.enums %}
|
|
25
29
|
{{ target.enum_class_name(enum=enum, apiVersion=api.version) }} = {{ target.enum_literal(values=enum.values) }}
|
|
26
30
|
{% if loop.last %}
|
|
@@ -13,11 +13,12 @@ class PrimitiveTypes:
|
|
|
13
13
|
DOUBLE = 'Double'
|
|
14
14
|
STRING = 'String'
|
|
15
15
|
UUID = 'Uuid'
|
|
16
|
+
BIG_INT = 'BigInt'
|
|
16
17
|
BOOLEAN = 'Boolean'
|
|
17
18
|
DATETIME = 'Datetime'
|
|
18
19
|
DATE = 'Date'
|
|
19
20
|
JSON = 'Json'
|
|
20
|
-
ALL: ClassVar[list[str]] = [LONG_INTEGER, INTEGER, FLOAT, DOUBLE, STRING, UUID, BOOLEAN, DATETIME, DATE, JSON]
|
|
21
|
+
ALL: ClassVar[list[str]] = [LONG_INTEGER, INTEGER, FLOAT, DOUBLE, STRING, UUID, BIG_INT, BOOLEAN, DATETIME, DATE, JSON]
|
|
21
22
|
|
|
22
23
|
|
|
23
24
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|