Skip to content

Support numeric constraints for decimal.Decimal#998

Closed
Siyet wants to merge 19 commits intojcrist:mainfrom
Siyet:decimal-constraints-683
Closed

Support numeric constraints for decimal.Decimal#998
Siyet wants to merge 19 commits intojcrist:mainfrom
Siyet:decimal-constraints-683

Conversation

@Siyet
Copy link
Copy Markdown
Collaborator

@Siyet Siyet commented Apr 1, 2026

Fixes #683.

Previously, the numeric constraints gt, ge, lt, le, and multiple_of in msgspec.Meta were only valid for int and float types. This PR extends support to decimal.Decimal.

PR #692 by @cocorigon (the issue author) has been open since May 2024. The author has since explicitly declined to continue it and invited others to take it over. This PR is a fresh implementation with documentation and full test coverage.

Changes

  • _core.c: Added five new TypeNode constraint flags (MS_CONSTR_DECIMAL_GT/GE/LT/LE/MULTIPLE_OF) backed by PyObject* slots storing Decimal instances. Constraint values are converted to Decimal at type-node build time (floats go through string conversion to avoid precision loss). A new ms_check_decimal_constraints() function is called after every Decimal decode path (JSON string, int, uint64, float, msgpack, convert).

  • __init__.pyi: Updated Meta.__init__ parameter types and attribute annotations from Union[int, float, None] to Union[int, float, Decimal, None].

  • docs/constraints.rst: Updated the Numeric Constraints section to mention decimal.Decimal, added a multiple_of usage example, and converted the multiple_of warning to a note - also adding that Decimal is the recommended solution for sub-integer precision constraints.

  • tests/unit/test_constraints.py: Added TestDecimalConstraints covering gt/ge/lt/le (parametrized), multiple_of, combined constraints, and convert().

Notable design decisions

  • multiple_of for Decimal uses Python's % operator (PyNumber_Remainder), which gives exact arithmetic - addressing the precision limitation that motivated this issue.
  • Constraint bounds passed as float are converted to Decimal via string representation to preserve precision (e.g. Meta(gt=0.1) becomes Decimal('0.1'), not Decimal('0.1000000000000000055...')).

aleksandr.tseluyko and others added 19 commits March 31, 2026 14:06
Add explicit -lm linkage for the _core C extension on non-Windows
platforms. Fixes undefined symbol errors (nextafter, fmod, lround)
on aarch64 Linux systems where libm is not implicitly linked.

Closes #971
Derive constraint_kind from non-None union members so that
Annotated[X | None, Meta(...)] constraints are validated correctly.
Previously any constraint on an Optional[X] type raised TypeError
because the union branch left kind as CK_OTHER.

Closes #804
Cover API mapping, option equivalents, typed decoding, error handling,
and features without direct equivalent.

Closes #642
Add MS_TYPE_BOOLLITERAL_TRUE/FALSE flags and handle PyBool_Type
before PyLong_Type in typenode_collect_literal. Update decode paths
(JSON, msgpack, convert) to validate against specific bool literal
values.

Closes #859
Store the computed tuple of FieldInfo on the class as
__struct_field_info__ to avoid expensive get_class_annotations()
and FieldInfo recreation on every call. Generic aliases are not
cached since type parameters affect annotations.

Closes #963
PyPI distribution name changed to msgspec-arise, import name stays msgspec.
Updated URLs, badges, docs, CI references to Siyet/msgspec-arise.
Rename package to msgspec-arise
Update doc links to fork domain
Fix missing libm linkage for _core extension on Linux
Support constraints on Optional (union with None) types
Add porting guide for users coming from orjson
Support Literal[True] and Literal[False] types
Cache structs.fields() result for non-generic structs
Extends gt, ge, lt, le, and multiple_of Meta constraints to work with
decimal.Decimal types, enabling exact arithmetic comparisons and
sub-integer precision constraints without floating point issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Siyet Siyet force-pushed the decimal-constraints-683 branch from a723b9a to 1d5fbb5 Compare April 8, 2026 09:09
@Siyet
Copy link
Copy Markdown
Collaborator Author

Siyet commented Apr 8, 2026

Resolved in the community fork msgspec-arise: PR #14, released in v0.20.2.

@Siyet Siyet closed this by deleting the head repository Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support numeric constraints for Decimal values

1 participant