Skip to content

Commit

Permalink
Simplify handles_type for decimals
Browse files Browse the repository at this point in the history
  • Loading branch information
faph committed Nov 18, 2023
1 parent cb607ff commit 2782da9
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 9 deletions.
13 changes: 6 additions & 7 deletions src/py_avro_schema/_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,12 +456,11 @@ class DecimalSchema(Schema):
@classmethod
def handles_type(cls, py_type: Type) -> bool:
"""Whether this schema class can represent a given Python class"""
try:
# A decimal.Decimal type with annotations indicating precision and optionally scale.
cls._decimal_meta(py_type)
return True
except TypeError:
return False
# Here we are greedy: we catch any decimal.Decimal. However, data() might fail if the annotation is not correct.
return (
_is_class(py_type, decimal.Decimal) # Using DecimalMeta
or get_origin(py_type) is decimal.Decimal # Deprecated: DecimalType
)

@classmethod
def _decimal_meta(cls, py_type: Type) -> py_avro_schema._typing.DecimalMeta:
Expand All @@ -474,7 +473,7 @@ def _decimal_meta(cls, py_type: Type) -> py_avro_schema._typing.DecimalMeta:
# At least one of the annotations should be a DecimalMeta object
(meta,) = (arg for arg in args[1:] if isinstance(arg, py_avro_schema._typing.DecimalMeta))
except ValueError: # not enough values to unpack
raise TypeError(f"{py_type} is not annotated with a 'py_avro_schema.DecimalMeta` object")
raise TypeError(f"{py_type} is not annotated with a 'py_avro_schema.DecimalMeta' object")
return meta
elif origin is decimal.Decimal:
# Deprecated pas.DecimalType[4, 2]
Expand Down
15 changes: 13 additions & 2 deletions tests/test_logicals.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import datetime
import decimal
import re
import uuid
from typing import Annotated, Any, Dict, List

Expand Down Expand Up @@ -162,13 +163,23 @@ def test_annotated_decimal_additional_meta():

def test_annotated_decimal_no_meta():
py_type = Annotated[decimal.Decimal, ...]
with pytest.raises(pas.TypeNotSupportedError):
with pytest.raises(
TypeError,
match=re.escape(
"typing.Annotated[decimal.Decimal, Ellipsis] is not annotated with a 'py_avro_schema.DecimalMeta' object"
),
):
assert_schema(py_type, {})


def test_annotated_decimal_tuple():
py_type = Annotated[decimal.Decimal, (5, 2)]
with pytest.raises(pas.TypeNotSupportedError):
with pytest.raises(
TypeError,
match=re.escape(
"typing.Annotated[decimal.Decimal, (5, 2)] is not annotated with a 'py_avro_schema.DecimalMeta' object"
),
):
assert_schema(py_type, {})


Expand Down

0 comments on commit 2782da9

Please sign in to comment.