Skip to content

Commit 737be58

Browse files
authored
Adding schema for typing.Final (#9)
1 parent d11e720 commit 737be58

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

src/py_avro_schema/_schemas.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
Annotated,
3434
Any,
3535
Dict,
36+
Final,
3637
ForwardRef,
3738
List,
3839
Literal,
@@ -378,6 +379,31 @@ def data(self, names: NamesType) -> JSONType:
378379
return self.literal_value_schema.data(names=names)
379380

380381

382+
@register_schema
383+
class FinalSchema(Schema):
384+
"""An Avro schema for Python ``typing.Final``"""
385+
386+
def __init__(self, py_type: Type, namespace: Optional[str] = None, options: Option = Option(0)):
387+
"""An Avro schema for Python ``typing.Final``"""
388+
super().__init__(py_type, namespace, options)
389+
py_type = _type_from_annotated(py_type)
390+
try:
391+
real_type = get_args(py_type)[0]
392+
except IndexError:
393+
raise TypeError("Can't generate Avro schema from Python typing.Final without a type parameter")
394+
self.real_schema = _schema_obj(real_type, namespace=namespace, options=options)
395+
396+
def data(self, names: NamesType) -> JSONType:
397+
"""Return the schema data"""
398+
return self.real_schema.data(names=names)
399+
400+
@classmethod
401+
def handles_type(cls, py_type: Type) -> bool:
402+
"""Whether this schema class can represent a given Python class"""
403+
py_type = _type_from_annotated(py_type)
404+
return get_origin(py_type) is Final or py_type is Final
405+
406+
381407
@register_schema
382408
class DictAsJSONSchema(Schema):
383409
"""An Avro string schema representing a Python Dict[str, Any] or List[Dict[str, Any]] assuming JSON serialization"""

tests/test_plain_class.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
# specific language governing permissions and limitations under the License.
1111

1212
import re
13-
from typing import Annotated
13+
from typing import Annotated, Final
1414

1515
import pytest
1616

@@ -160,3 +160,22 @@ def test_type_aliases_future():
160160

161161
expected = {"fields": [{"name": "name", "type": "string"}], "name": "PyClass", "type": "record"}
162162
assert_schema(PyClass, expected)
163+
164+
165+
def test_typing_final():
166+
167+
class PyType:
168+
var: Final[str]
169+
field: Final[dict[str, int]]
170+
171+
def __init__(self):
172+
self.var = "Hello World"
173+
self.field = {"John": 123}
174+
175+
expected = {
176+
"fields": [{"name": "var", "type": "string"}, {"name": "field", "type": {"type": "map", "values": "long"}}],
177+
"name": "PyType",
178+
"type": "record",
179+
}
180+
181+
assert_schema(PyType, expected)

0 commit comments

Comments
 (0)