-
-
Notifications
You must be signed in to change notification settings - Fork 277
Expand file tree
/
Copy pathconst.py
More file actions
119 lines (103 loc) · 3.73 KB
/
const.py
File metadata and controls
119 lines (103 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
from __future__ import annotations
from typing import Any, ClassVar, overload
from attr import define
from ...utils import PythonIdentifier
from ... import schema as oai
from ..errors import PropertyError
from .protocol import PropertyProtocol, Value
from .string import StringProperty
@define
class ConstProperty(PropertyProtocol):
"""A property representing a const value"""
name: str
required: bool
value: Value
default: Value | None
python_name: PythonIdentifier
description: str | None
example: None
data: oai.Schema
template: ClassVar[str] = "const_property.py.jinja"
@classmethod
def build(
cls,
*,
const: str | int | float | bool,
default: Any,
name: str,
python_name: PythonIdentifier,
required: bool,
description: str | None,
data: oai.Schema,
) -> ConstProperty | PropertyError:
"""
Create a `ConstProperty` the right way.
Args:
const: The `const` value of the schema, indicating the literal value this represents
default: The default value of this property, if any. Must be equal to `const` if set.
name: The name of the property where it appears in the OpenAPI document.
required: Whether this property is required where it's being used.
python_name: The name used to represent this variable/property in generated Python code
description: The description of this property, used for docstrings
"""
value = cls._convert_value(const)
prop = cls(
value=value,
python_name=python_name,
name=name,
required=required,
default=None,
description=description,
example=None,
data=data,
)
converted_default = prop.convert_value(default)
if isinstance(converted_default, PropertyError):
return converted_default
prop.default = converted_default
return prop
def convert_value(self, value: Any) -> Value | None | PropertyError:
value = self._convert_value(value)
if value is None:
return value
if value != self.value:
return PropertyError(
detail=f"Invalid value for const {self.name}; {value.raw_value} != {self.value.raw_value}"
)
return value
@staticmethod
@overload
def _convert_value(value: None) -> None: # type: ignore[misc]
... # pragma: no cover
@staticmethod
@overload
def _convert_value(value: Any) -> Value: ... # pragma: no cover
@staticmethod
def _convert_value(value: Any) -> Value | None:
if value is None or isinstance(value, Value):
return value
if isinstance(value, str):
return StringProperty.convert_value(value)
return Value(python_code=str(value), raw_value=value)
def get_type_string(
self,
no_optional: bool = False,
json: bool = False,
) -> str:
lit = f"Literal[{self.value.python_code}]"
if not no_optional and not self.required:
return f"{lit} | Unset"
return lit
def get_imports(self, *, prefix: str) -> set[str]:
"""
Get a set of import strings that should be included when this property is used somewhere
Args:
prefix: A prefix to put before any relative (local) module names. This should be the number of . to get
back to the root of the generated client.
"""
if self.required:
return {"from typing import Literal, cast"}
return {
"from typing import Literal, cast",
f"from {prefix}types import UNSET, Unset",
}