PYTHON-5508 - Add built-in DecimalEncoder and DecimalDecoder (#2499)
This commit is contained in:
parent
9a9a65c617
commit
5e96353797
@ -20,8 +20,11 @@ from __future__ import annotations
|
||||
|
||||
import decimal
|
||||
import struct
|
||||
from decimal import Decimal
|
||||
from typing import Any, Sequence, Tuple, Type, Union
|
||||
|
||||
from bson.codec_options import TypeDecoder, TypeEncoder
|
||||
|
||||
_PACK_64 = struct.Struct("<Q").pack
|
||||
_UNPACK_64 = struct.Struct("<Q").unpack
|
||||
|
||||
@ -58,6 +61,42 @@ _DEC128_CTX = decimal.Context(**_CTX_OPTIONS.copy()) # type: ignore
|
||||
_VALUE_OPTIONS = Union[decimal.Decimal, float, str, Tuple[int, Sequence[int], int]]
|
||||
|
||||
|
||||
class DecimalEncoder(TypeEncoder):
|
||||
"""Converts Python :class:`decimal.Decimal` to BSON :class:`Decimal128`.
|
||||
|
||||
For example::
|
||||
opts = CodecOptions(type_registry=TypeRegistry([DecimalEncoder()]))
|
||||
bson.encode({"d": decimal.Decimal('1.0')}, codec_options=opts)
|
||||
|
||||
.. versionadded:: 4.15
|
||||
"""
|
||||
|
||||
@property
|
||||
def python_type(self) -> Type[Decimal]:
|
||||
return Decimal
|
||||
|
||||
def transform_python(self, value: Any) -> Decimal128:
|
||||
return Decimal128(value)
|
||||
|
||||
|
||||
class DecimalDecoder(TypeDecoder):
|
||||
"""Converts BSON :class:`Decimal128` to Python :class:`decimal.Decimal`.
|
||||
|
||||
For example::
|
||||
opts = CodecOptions(type_registry=TypeRegistry([DecimalDecoder()]))
|
||||
bson.decode(data, codec_options=opts)
|
||||
|
||||
.. versionadded:: 4.15
|
||||
"""
|
||||
|
||||
@property
|
||||
def bson_type(self) -> Type[Decimal128]:
|
||||
return Decimal128
|
||||
|
||||
def transform_bson(self, value: Any) -> decimal.Decimal:
|
||||
return value.to_decimal()
|
||||
|
||||
|
||||
def create_decimal128_context() -> decimal.Context:
|
||||
"""Returns an instance of :class:`decimal.Context` appropriate
|
||||
for working with IEEE-754 128-bit decimal floating point values.
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
Changelog
|
||||
=========
|
||||
Changes in Version 4.15.0 (XXXX/XX/XX)
|
||||
--------------------------------------
|
||||
PyMongo 4.15 brings a number of changes including:
|
||||
|
||||
- Added :class:`bson.decimal128.DecimalEncoder` and :class:`bson.decimal128.DecimalDecoder`
|
||||
to support encoding and decoding of BSON Decimal128 values to decimal.Decimal values using the TypeRegistry API.
|
||||
|
||||
Changes in Version 4.14.1 (2025/08/19)
|
||||
--------------------------------------
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ from decimal import Decimal
|
||||
from random import random
|
||||
from typing import Any, Tuple, Type, no_type_check
|
||||
|
||||
from bson.decimal128 import DecimalDecoder, DecimalEncoder
|
||||
from gridfs.asynchronous.grid_file import AsyncGridIn, AsyncGridOut
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
@ -59,29 +60,7 @@ from pymongo.message import _CursorAddress
|
||||
_IS_SYNC = False
|
||||
|
||||
|
||||
class DecimalEncoder(TypeEncoder):
|
||||
@property
|
||||
def python_type(self):
|
||||
return Decimal
|
||||
|
||||
def transform_python(self, value):
|
||||
return Decimal128(value)
|
||||
|
||||
|
||||
class DecimalDecoder(TypeDecoder):
|
||||
@property
|
||||
def bson_type(self):
|
||||
return Decimal128
|
||||
|
||||
def transform_bson(self, value):
|
||||
return value.to_decimal()
|
||||
|
||||
|
||||
class DecimalCodec(DecimalDecoder, DecimalEncoder):
|
||||
pass
|
||||
|
||||
|
||||
DECIMAL_CODECOPTS = CodecOptions(type_registry=TypeRegistry([DecimalCodec()]))
|
||||
DECIMAL_CODECOPTS = CodecOptions(type_registry=TypeRegistry([DecimalEncoder(), DecimalDecoder()]))
|
||||
|
||||
|
||||
class UndecipherableInt64Type:
|
||||
|
||||
@ -23,6 +23,7 @@ from decimal import Decimal
|
||||
from random import random
|
||||
from typing import Any, Tuple, Type, no_type_check
|
||||
|
||||
from bson.decimal128 import DecimalDecoder, DecimalEncoder
|
||||
from gridfs.synchronous.grid_file import GridIn, GridOut
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
@ -59,29 +60,7 @@ from pymongo.synchronous.helpers import next
|
||||
_IS_SYNC = True
|
||||
|
||||
|
||||
class DecimalEncoder(TypeEncoder):
|
||||
@property
|
||||
def python_type(self):
|
||||
return Decimal
|
||||
|
||||
def transform_python(self, value):
|
||||
return Decimal128(value)
|
||||
|
||||
|
||||
class DecimalDecoder(TypeDecoder):
|
||||
@property
|
||||
def bson_type(self):
|
||||
return Decimal128
|
||||
|
||||
def transform_bson(self, value):
|
||||
return value.to_decimal()
|
||||
|
||||
|
||||
class DecimalCodec(DecimalDecoder, DecimalEncoder):
|
||||
pass
|
||||
|
||||
|
||||
DECIMAL_CODECOPTS = CodecOptions(type_registry=TypeRegistry([DecimalCodec()]))
|
||||
DECIMAL_CODECOPTS = CodecOptions(type_registry=TypeRegistry([DecimalEncoder(), DecimalDecoder()]))
|
||||
|
||||
|
||||
class UndecipherableInt64Type:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user