- [FEAT] add the
Programming Language :: Python :: Free Threading :: 3 - Stableclassifier - [CHORE] clarify in the thread-safety docs that the free-threaded CPython build is supported and covered by the test suite
- [CHORE] treat free-threaded CPython (
3.13t,3.14t) CI jobs as normal required test runs instead of experimental jobs
- [FIX] avoid a shared default
EncodeOptions()instance inencode()by constructing defaults per call - [CHORE] document the library's thread-safety boundary for concurrent
encode()/decode()use and shared read-only options - [CHORE] add concurrent regression coverage for
encode(),decode(),WeakWrapper, andKeyPathNodecache behavior - [CHORE] scale deep stack-safety and thread-stress canaries for older PyPy 3.8 CI runners while preserving coverage on other interpreters
- [CHORE] optimize
encodehot paths with lower-overhead iterative traversal, cheaper container checks, and deep linear mapping fast paths - [CHORE] optimize
EncodeUtilsASCII/BMP handling andKeyPathNodepath materialization caching for repeated encode workloads - [FIX] preserve legacy
max_depthvs circular-reference error precedence in both generic and fast-path encoding - [FIX] keep
EncodeOptionsfree of encode-time mutable cache state while preserving encoder/equality behavior - [CHORE] expand encode regression coverage for deep nesting, cycle handling, key-path caching, and
EncodeOptionssemantics
- [CHORE] optimize
decodehot paths via structured-key pre-scan/bypass logic and lower-overhead default decoder dispatch - [FIX] align
decodeedge cases with Nodeqsfor mixed flat/structured keys and leading-zero bracket roots (e.g.[01]) - [FIX] avoid incorrect list forcing when
[]=appears only in the value token - [FIX] restore Python 3.8 compatibility in
decodeby avoiding runtime subscripting ofcollections.abc.Mapping - [CHORE] refactor
encodetraversal internals into dedicated frame/state models and constants - [CHORE] add repeatable local benchmark snapshots for decode (
C1/C2/C3) and deep encode traversal - [CHORE] expand decode/utils regression coverage for collision semantics and parser compatibility paths
- [CHORE] optimize
encodetraversal internals and hot paths with lower allocation overhead - [CHORE] add internal
KeyPathNodepath caching for lazy materialization and dot-encoded path reuse - [FIX] avoid
RecursionErrorin deep key-path dot encoding by makingKeyPathNode.as_dot_encodediterative - [FIX] ensure strict null handling applies RFC formatter behavior for bare-key output (e.g. RFC1738 space handling)
- [FIX] avoid mutating caller-owned root list/tuple elements when
EncodeOptions.filteris callable - [CHORE] remove unused
KeyPathNode.total_lengthstate to keep nodes lightweight - [CHORE] expand encode regression and internal helper tests (path caching, list format generators, strict-null formatting, mutation safety)
- [CHORE] optimize
decodeby skipping dot-in-keys normalization when "%2" is not present in key segments
- [FIX] harden encoder traversal to an iterative implementation to avoid recursion-based crashes on very deep nested input
- [FIX] harden decode merge path (
Utils.merge) with iterative traversal to preventRecursionErroron deep conflicting merges - [FIX] update
EncodeOptions.max_depthsemantics:Noneis unbounded by this option; explicit limits are enforced directly - [FIX] preserve legacy map-merge key collision semantics for mixed key types (
'1'vs1) in iterative merge - [CHORE] optimize deep encode performance by replacing per-frame side-channel chain scans with O(1) ancestry cycle state lookups
- [CHORE] add deep stack-safety regressions (depth 12_000) and cycle-state compatibility tests
- [CHORE] update encoding depth documentation
- [FEAT] add
EncodeOptions.max_depthto cap encoding traversal depth (capped to the current recursion limit) - [FIX] avoid
RecursionErroron deeply nested input by enforcing a configurable encoding depth guard - [FIX] make
WeakWrapperhashing identity-based to keep weak-key lookups stable after mutations - [CHORE] optimize encode/merge paths (shallow-copy root mappings, reuse dict targets in internal merges)
- [CHORE] expand tests and documentation for encoding depth limits
- [CHORE] stricter static type checking with pyright
- [FIX] implement
DecodeOptions.list_limithandling inUtils.combinefunction to prevent DoS via memory exhaustion
- [CHORE] pin mypy<1.19 on PyPy to avoid new
librtbuild failures while keeping newer mypy on CPython
- [FEAT] add support for PyPy 3.8, 3.9, 3.10 and 3.11
- [FEAT] add
EncodeOptions.comma_compact_nulls, allowing omission ofNoneentries in lists when using theListFormat.COMMA. This results in cleaner output (e.g.,[True, False, None, True]becomes"true,false,true").
- [CHORE] add support for Python 3.14
- [CHORE] reinstate Python 3.8 support
- [FIX] encode booleans in lowercase to match JavaScript behavior
- [CHORE] add tests for boolean encoding and decoding parity
- [CHORE] add highlights section to README and docs with key features and usage notes
- [CHORE] update pyproject.toml with improved metadata, optional dev dependencies, and wheel build config
- [CHORE] add project logo to README and documentation
- [FIX] fix top-level dot splitting in keys to preserve encoded dots and handle degenerate cases
- [FIX] normalize percent-encoded dots in bracketed keys when
decode_dot_in_keysis enabled - [FIX] handle leading dot in keys by converting to bracket segment in
dot_to_bracket_top_level - [FIX] fix strict_depth enforcement to avoid raising on unterminated bracket groups in decode logic
- [FIX] fix dot-to-bracket decoding to preserve leading dots in consecutive dot sequences
- [FIX] fix percent-decoding to handle dot in keys and clarify top-level percent sequence handling
- [FIX] handle ambiguous '.]' in key decoding and prevent bracket segment overrun on closing brackets
- [CHORE]️ refactor
DecodeOptionsto support legacy decoders and add unified decode methods - [CHORE]️ update type annotations in
decode_options_testfor decoder andlegacy_decodersignatures - [CHORE] add tests for
DecodeOptionsdot-in-keys and custom decoder behaviors - [CHORE] add C# port (QsNet) parity tests for encoded dot behavior in
DecodeOptions - [CHORE] add tests for decoder precedence over
legacy_decoderand non-stringdecoderresults inDecodeOptions - [CHORE] add tests for dot encoding and decoding parity across
DecodeOptionsconfigurations - [CHORE] revise decode test to avoid duplicate dict key assertion and ensure decoder invocation for dot-encoded and bracketed keys
- [CHORE] add tests for
split_key_into_segmentsremainder handling and strict depth enforcement
- [FIX] preserve percent-encoded dots in keys during decoding
- [CHORE] refactor merge logic for improved readability and performance in utils
- [CHORE] optimize encoding logic for improved performance and clarity in encode_utils
- [CHORE] optimize decode logic for improved performance and clarity in decode_utils
- [CHORE] optimize key handling and object normalization for improved performance and clarity in encode.py
- [CHORE] optimize delimiter splitting and list parsing logic for improved performance and clarity in decode.py
- [CHORE] optimize proxy caching and dict hashing logic for improved performance and determinism in weak_wrapper
- [CHORE] optimize Undefined singleton logic for thread safety and clarity; prevent subclassing and ensure identity preservation
- [CHORE] optimize EncodeOptions initialization and equality logic for improved clarity and determinism
- [CHORE] optimize DecodeOptions post-init logic for improved determinism and enforce consistency between decode_dot_in_keys and allow_dots
- [CHORE] optimize list merging logic in Utils.merge for improved determinism and handling of Undefined values
- [CHORE] optimize type checking in list merging logic for improved clarity and consistency in Utils.merge
- [CHORE] optimize encode logic for improved determinism and clarity; use UNDEFINED singleton and refine ListFormat.COMMA comparison
- [CHORE] optimize decode logic to use UNDEFINED singleton for list initialization
- [FIX] fix stable hashing for mappings and sets by sorting on hashed keys and elements to prevent ordering errors
- [FIX] fix percent-encoding to operate on UTF-16 code units for accurate surrogate pair handling and JS compatibility
- [FIX] handle surrogate pairs only when valid high+low combination is present in UTF-8 encoding
- [FIX] replace code_unit_at with ord for direct code unit retrieval in EncodeUtils methods
- [FIX] fix WeakWrapper equality to compare underlying object identity instead of proxy instance
- [FIX] ensure thread-safe access to _proxy_cache with RLock in get_proxy
- [CHORE] add tests for EncodeUtils._encode_string with RFC3986 format and emoji handling
- [CHORE] update documentation
- [CHORE] optimize
decodeperformance
- [FIX] remove redundant
WeakWrapperinstances inencode
- [FEAT] add
loadandloadsalias methods fordecode - [FEAT] add
dumpanddumpsalias methods forencode
- [CHORE] update readme for clarity around RFC 3986 and RFC 1738 space encoding
- [FIX] fix list with indices always getting parsed into a dict (#19)
- [FEAT] WeakWrapper now fully supports using mutable objects (e.g.
dict,list,set) as weak-keys- shared proxy layer stored in a
WeakValueDictionary→ automatic cleanup when the original object is GC’d - deep-content hashing + identity-based equality
- safeguards for circular references and configurable depth limit
- shared proxy layer stored in a
- [FIX] prevent recursion crashes when hashing very deep or cyclic structures (raises
RecursionError/ValueErrorwith clear messages) - [CHORE] refactor
WeakWrapperinternals for clarity and performance - [CHORE] add an extensive WeakWrapper test-suite (proxy sharing, GC removal, stable hashes, error conditions)
- [CHORE] tighten type-hints
- use
weakref.ReferenceType[_Refable]
- use
- [CHORE] enhance type hints and improve code clarity (#17)
- [CHORE] drop support for Python 3.8 and update dependencies for Python 3.9+
- [FIX] fix
EncodeUtils.encodefor non-BMP characters - [CHORE] refactor
EncodeUtilsandDecodeUtils - [CHORE] add more tests
- [FIX] fix encoding non-BMP characters when using
charset=Charset.LATIN1
- [FEAT] add
DecodeOptions.raise_on_limit_exceededoption (#11) - [CHORE] remove dead code in
Utils - [CHORE] add more tests
- [CHORE] update dependencies
- [FIX]
decode: avoid a crash withcomma=True,charset=Charset.LATIN1,interpret_numeric_entities=True - [CHORE] add more tests
- [FEAT] add
DecodeOptions.strict_depthoption to throw when input is beyond depth (#8)
- [FIX] fix
decodeoutput when bothstrict_null_handlingandallow_empty_listsare set toTrue(#5)
- [CHORE] update documentation
- [CHORE] first stable release
- [FEAT]
decodereturnsdict[str, Any]instead ofdict(#4) - [FIX] fix decoding encoded square brackets in key names
- [CHORE] update dependencies
- [CHORE] update dependencies
- [CHORE] update README
- [CHORE] update README with links to documentation
- [CHORE] added Sphinx documentation
- [FIX] incorrect parsing of nested params with closing square bracket
]in the property name (#1)
- [CHORE] update README.md
- [CHORE] add comparison test between output of qs_codec and qs
- [CHORE] minor improvements
- [CHORE] update README.md
- [CHORE] initial release