### Running the Test Suite Source: https://github.com/techouse/qs_codec/blob/main/CONTRIBUTING.md Commands to set up a virtual environment, install dependencies, and run the test suite using tox for the qs_codec project. ```bash git clone https://github.com/techouse/qs_codec cd qs_codec python3 -m venv env source env/bin/activate pip install -e . pip install -r requirements_dev.txt tox ``` -------------------------------- ### Charset Sentinel Example Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to use the `charset_sentinel` option to announce the character set by including a `utf8=✓` parameter with the proper encoding of the checkmark. ```python import qs_codec as qs assert qs.encode( {'a': '☺'}, qs.EncodeOptions(charset_sentinel=True) ) == 'utf8=%E2%9C%93&a=%E2%98%BA' assert qs.encode( {'a': 'æ'}, qs.EncodeOptions(charset=qs.Charset.LATIN1, charset_sentinel=True) ) == 'utf8=%26%2310003%3B&a=%E6' ``` -------------------------------- ### Git Commit Message Convention Source: https://github.com/techouse/qs_codec/blob/main/CONTRIBUTING.md Example of a multi-line git commit message format for substantial changes, including a brief summary and a detailed explanation. ```bash git commit -m "A brief summary of the commit A paragraph describing what changed and its impact." ``` -------------------------------- ### Parameter Limit Configuration Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to limit the maximum number of parameters decoded from a query string using the `parameter_limit` option in `DecodeOptions`. Shows an example with a limit of 1. ```python import qs_codec as qs assert qs.decode( 'a=b&c=d', qs.DecodeOptions(parameter_limit=1), ) == {'a': 'b'} ``` -------------------------------- ### Custom Decoder Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates using a custom decoder function to alter how values are parsed. This example converts numeric strings to integers. ```python import qs_codec as qs, typing as t def custom_decoder( value: t.Any, charset: t.Optional[qs.Charset], ) -> t.Union[int, str]: try: return int(value) except ValueError: return value assert qs.decode( 'foo=123', qs.DecodeOptions(decoder=custom_decoder), ) == {'foo': 123} ``` -------------------------------- ### Custom Decoder Function Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to use the `decoder` option in `DecodeOptions` to provide a custom function for parsing values. This example converts numeric strings to integers. ```python import qs_codec as qs import typing as t def custom_decoder(value: t.Any, charset: t.Optional[qs.Charset]) -> t.Union[int, str]: try: return int(value) except ValueError: return value assert qs.decode( 'foo=123', qs.DecodeOptions(decoder=custom_decoder), ) == {'foo': 123} ``` -------------------------------- ### Custom Encoder Function Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Illustrates how to provide a custom encoder function via `EncodeOptions.encoder` to control how specific values are encoded. The example shows replacing 'č' with 'c'. ```python import qs_codec as qs import typing as t def custom_encoder(value: str, charset: t.Optional[qs.Charset], format: t.Optional[qs.Format]) -> str: if value == 'č': return 'c' return value assert qs.encode( {'a': {'b': 'č'}}, qs.EncodeOptions(encoder=custom_encoder), ) == 'a[b]=c' ``` -------------------------------- ### Custom Encoder Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates how to use a custom encoder function to modify how values are encoded. The example replaces 'č' with 'c'. ```python import qs_codec as qs import typing as t def custom_encoder( value: str, charset: t.Optional[qs.Charset], format: t.Optional[qs.Format], ) -> str: if value == 'č': return 'c' return value assert qs.encode( {'a': {'b': 'č'}}, qs.EncodeOptions(encoder=custom_encoder), ) == 'a[b]=c' ``` -------------------------------- ### Serialize Datetime Objects Source: https://github.com/techouse/qs_codec/blob/main/README.rst Provides an example of overriding the default serialization for `datetime` objects by providing a custom callable to the `serialize_date` option. This example shows encoding a datetime object to an ISO 8601 string. ```python import qs_codec as qs import datetime import sys # First case: encoding a datetime object to an ISO 8601 string assert ( qs.encode( { "a": ( datetime.datetime.fromtimestamp(7, datetime.UTC) if sys.version_info.major == 3 and sys.version_info.minor >= 11 else datetime.datetime.utcfromtimestamp(7) ) }, qs.EncodeOptions(encode=False), ) == "a=1970-01-01T00:00:07+00:00" if sys.version_info.major == 3 and sys.version_info.minor >= 11 else "a=1970-01-01T00:00:07" ) ``` -------------------------------- ### Basic Encoding and Decoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates the fundamental encoding and decoding operations of the qs-codec library. ```python import qs_codec as qs # Encoding assert qs.encode({'a': 'b'}) == 'a=b' # Decoding assert qs.decode('a=b') == {'a': 'b'} ``` -------------------------------- ### qs_codec.models Module Contents Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.models.rst Documentation for the main qs_codec.models module, listing its members, undocumented members, and inheritance information. ```python import qs_codec.models # Accessing members of the models package (example) # print(dir(qs_codec.models)) ``` -------------------------------- ### Running Linters with Tox Source: https://github.com/techouse/qs_codec/blob/main/CONTRIBUTING.md Command to execute linters for code formatting and quality checks using tox, ensuring adherence to coding standards. ```bash tox -e linters ``` -------------------------------- ### qs_codec.utils.utils Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.utils.rst Provides general utility functions for the qs_codec project. This module contains miscellaneous helper functions that do not fit into other specific utility modules. ```python from qs_codec.utils.utils import * # Example usage (assuming functions are defined in utils) # result = process_data(input_data) # status = check_status() ``` -------------------------------- ### Handling Duplicate Keys with DecodeOptions Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Illustrates the `duplicates` option in `DecodeOptions` for managing duplicate keys during decoding, supporting COMBINE, FIRST, and LAST strategies. ```python import qs_codec as qs assert qs.decode('foo=bar&foo=baz') == {'foo': ['bar', 'baz']} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.COMBINE), ) == {'foo': ['bar', 'baz']} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.FIRST), ) == {'foo': 'bar'} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.LAST), ) == {'foo': 'baz'} ``` -------------------------------- ### qs_codec.models.encode_options Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.models.rst Documentation for the encode_options module within the qs_codec.models package. This module likely contains options related to encoding data. ```python from qs_codec.models.encode_options import EncodeOptions # Example usage (assuming EncodeOptions class exists) options = EncodeOptions() print(options) ``` -------------------------------- ### Basic Encoding and Decoding Source: https://github.com/techouse/qs_codec/blob/main/docs/index.rst Demonstrates the fundamental usage of the qs-codec library for encoding Python dictionaries into query strings and decoding query strings back into dictionaries. ```python import qs_codec as qs # Encoding assert qs.encode({'a': 'b'}) == 'a=b' # Decoding assert qs.decode('a=b') == {'a': 'b'} ``` -------------------------------- ### Basic Dictionary Decoding Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates decoding a simple query string with nested dictionary keys using square bracket notation. Shows how URI encoded strings are handled. ```python import qs_codec as qs assert qs.decode('foo[bar]=baz') == {'foo': {'bar': 'baz'}} ``` ```python import qs_codec as qs assert qs.decode('a%5Bb%5D=c') == {'a': {'b': 'c'}} ``` -------------------------------- ### qs_codec.utils Package Contents Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.utils.rst Exposes members from submodules, providing access to all utility functions within the qs_codec.utils package. This allows for importing all utilities at once. ```python from qs_codec.utils import * # Accessing functions from any submodule # decoded_data = decode_base64(encoded_string) # encoded_string = encode_url(data) # cleaned_string = clean_string(text) # result = process_data(input_data) ``` -------------------------------- ### Handle Duplicate Keys Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates different strategies for handling duplicate keys in query strings. Options include combining values into a list, taking the first value, or taking the last value. ```python import qs_codec as qs assert qs.decode('foo=bar&foo=baz') == {'foo': ['bar', 'baz']} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.COMBINE), ) == {'foo': ['bar', 'baz']} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.FIRST), ) == {'foo': 'bar'} assert qs.decode( 'foo=bar&foo=baz', qs.DecodeOptions(duplicates=qs.Duplicates.LAST), ) == {'foo': 'baz'} ``` -------------------------------- ### qs_codec.models.decode_options Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.models.rst Documentation for the decode_options module within the qs_codec.models package. This module likely contains options related to decoding data. ```python from qs_codec.models.decode_options import DecodeOptions # Example usage (assuming DecodeOptions class exists) options = DecodeOptions() print(options) ``` -------------------------------- ### Create Lists of Dictionaries Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to construct a list of dictionaries during decoding by using empty brackets for list indices and then specifying dictionary keys. ```python import qs_codec as qs assert qs.decode('a[][b]=c') == {'a': [{'b': 'c'}]} ``` -------------------------------- ### qs_codec.models.weak_wrapper Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.models.rst Documentation for the weak_wrapper module within the qs_codec.models package. This module could provide a weak reference wrapper for objects. ```python from qs_codec.models.weak_wrapper import WeakWrapper # Example usage (assuming WeakWrapper class exists) obj = object() wrapper = WeakWrapper(obj) print(wrapper.get()) ``` -------------------------------- ### Basic Encoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates the basic usage of qs.encode with a nested dictionary. Encoding is disabled for keys. ```python import qs_codec as qs assert qs.encode( {'a': {'b': 'c'}}, qs.EncodeOptions(encode=False), ) == 'a[b]=c' ``` -------------------------------- ### Handling Empty Strings and None Values Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Describes that empty strings and None values result in the key being present with an equals sign, but no value. ```python import qs_codec as qs assert qs.encode({'a': ''}) == 'a=' ``` -------------------------------- ### Strict Null Handling for Decoding Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to decode query strings where None values are represented without an equals sign back into None. ```python import qs_codec as qs assert qs.decode( 'a&b=', qs.DecodeOptions(strict_null_handling=True), ) == {'a': None, 'b': ''} ``` -------------------------------- ### Project Dependencies Source: https://github.com/techouse/qs_codec/blob/main/requirements_dev.txt These are the core Python dependencies for the qs_codec project. They include pytest for testing, pytest-cov for code coverage, mypy for static type checking, and TOML for configuration file parsing. Tox is also listed, which is commonly used for automating Python testing and development tasks. ```python pytest>=8.3.5 pytest-cov>=6.0.0 mypy>=1.15.0 toml>=0.10.2 tox ``` -------------------------------- ### Strict Null Handling (Decoding) Source: https://github.com/techouse/qs_codec/blob/main/README.rst Shows how to use the `strict_null_handling` flag in `DecodeOptions` to correctly decode query strings where `None` values are represented without an equals sign back into `None`. ```python import qs_codec as qs assert qs.decode( 'a&b=', qs.DecodeOptions(strict_null_handling=True), ) == {'a': None, 'b': ''} ``` -------------------------------- ### qs_codec Module Contents Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.rst Provides access to the main functionalities of the qs_codec package, including members, undocumented members, and inheritance information. ```python import qs_codec # Access members of the qs_codec module # print(dir(qs_codec)) # Access undocumented members (if any) # print(qs_codec.__dict__) # Show inheritance information (if applicable) # print(qs_codec.__bases__) ``` -------------------------------- ### Using Charset Sentinel for UTF-8 Detection Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Explains and demonstrates the `charset_sentinel` option in `DecodeOptions` for handling the `utf8=✓` mechanism to detect the correct character encoding. ```python import qs_codec as qs assert qs.decode( 'utf8=%E2%9C%93&a=%C3%B8', qs.DecodeOptions( charset=qs.Charset.LATIN1, charset_sentinel=True, ), ) == {'a': 'ø'} assert qs.decode( 'utf8=%26%2310003%3B&a=%F8', qs.DecodeOptions( charset=qs.Charset.UTF8, charset_sentinel=True, ), ) == {'a': 'ø'} ``` -------------------------------- ### List Encoding Formats Source: https://github.com/techouse/qs_codec/blob/main/README.rst Explains and demonstrates different list formatting options for encoding lists, including INDICES, BRACKETS, REPEAT, and COMMA. ```python import qs_codec as qs # ListFormat.INDICES (default) assert qs.encode( {'a': ['b', 'c', 'd']}, qs.EncodeOptions(encode=False) ) == 'a[0]=b&a[1]=c&a[2]=d' ``` ```python import qs_codec as qs # ListFormat.REPEAT (using indices=False) assert qs.encode( {'a': ['b', 'c', 'd']}, qs.EncodeOptions( encode=False, indices=False, ), ) == 'a=b&a=c&a=d' ``` ```python import qs_codec as qs # ListFormat.INDICES assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.INDICES, ), ) == 'a[0]=b&a[1]=c' ``` ```python import qs_codec as qs # ListFormat.BRACKETS assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.BRACKETS, ), ) == 'a[]=b&a[]=c' ``` ```python import qs_codec as qs # ListFormat.REPEAT assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.REPEAT, ), ) == 'a=b&a=c' ``` ```python import qs_codec as qs # ListFormat.COMMA assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.COMMA, ), ) == 'a=b,c' ``` -------------------------------- ### Add Query String Prefix Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to prepend a question mark ('?') to the query string by setting the `add_query_prefix` option to True. ```python import qs_codec as qs assert qs.encode( {'a': 'b', 'c': 'd'}, qs.EncodeOptions(add_query_prefix=True), ) == '?a=b&c=d' ``` -------------------------------- ### Handling Empty String Values in Lists Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how empty string values are preserved when decoding lists, both with sequential and indexed notation. ```python import qs_codec as qs assert qs.decode('a[]=&a[]=b') == {'a': ['', 'b']} assert qs.decode('a[0]=b&a[1]=&a[2]=c') == {'a': ['b', '', 'c']} ``` -------------------------------- ### Basic Encoding with Custom Delimiter Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to encode a dictionary into a query string using a custom delimiter (semicolon). ```python import qs_codec as qs assert qs.encode( {'a': 'b', 'c': 'd', }, qs.EncodeOptions(delimiter=';') ) == 'a=b;c=d' ``` -------------------------------- ### qs_codec.utils.str_utils Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.utils.rst Provides utility functions for string manipulation. This module is part of the qs_codec project and offers various string processing capabilities. ```python from qs_codec.utils.str_utils import * # Example usage (assuming functions are defined in str_utils) # cleaned_string = clean_string(text) # formatted_string = format_string(template, data) ``` -------------------------------- ### Encoding Lists with Different Formats Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to encode lists using different formats like INDICES, BRACKETS, REPEAT, and COMMA by setting the 'list_format' option in EncodeOptions. ```python import qs_codec as qs # ListFormat.INDICES assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.INDICES, ), ) == 'a[0]=b&a[1]=c' ``` ```python import qs_codec as qs # ListFormat.BRACKETS assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.BRACKETS, ), ) == 'a[]=b&a[]=c' ``` ```python import qs_codec as qs # ListFormat.REPEAT assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.REPEAT, ), ) == 'a=b&a=c' ``` ```python import qs_codec as qs # ListFormat.COMMA assert qs.encode( {'a': ['b', 'c']}, qs.EncodeOptions( encode=False, list_format=qs.ListFormat.COMMA, ), ) == 'a=b,c' ``` -------------------------------- ### Basic Encoding Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates the basic usage of `qs.encode` to convert a dictionary into a query string. By default, it URI encodes the output. ```python import qs_codec as qs assert qs.encode({'a': 'b'}) == 'a=b' assert qs.encode({'a': {'b': 'c'}}) == 'a%5Bb%5D=c' ``` -------------------------------- ### Sphinx Dependency Source: https://github.com/techouse/qs_codec/blob/main/docs/requirements.txt Specifies the Sphinx version required for the project. Sphinx is a powerful documentation generator that converts reStructuredText or Markdown files into various output formats like HTML, PDF, and ePub. ```python Sphinx==8.2.3 ``` -------------------------------- ### Adding Query String Prefix Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to prepend a question mark to the query string by setting 'add_query_prefix' to True. ```python import qs_codec as qs assert qs.encode( {'a': 'b', 'c': 'd'}, qs.EncodeOptions(add_query_prefix=True), ) == '?a=b&c=d' ``` -------------------------------- ### Decoding Lists with Indexed Array Notation Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Illustrates decoding lists with specific indices using bracket notation, including compacting sparse lists. ```python import qs_codec as qs assert qs.decode('a[1]=c&a[0]=b') == {'a': ['b', 'c']} assert qs.decode('a[1]=b&a[15]=c') == {'a': ['b', 'c']} ``` -------------------------------- ### Overriding Parameter Limit Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates how to override the default parameter limit using DecodeOptions. ```python import qs_codec as qs assert qs.decode( 'a=b&c=d', qs.DecodeOptions(parameter_limit=1), ) == {'a': 'b'} ``` -------------------------------- ### Strict Null Handling for Encoding Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to encode None values without an equals sign when strict null handling is enabled. ```python import qs_codec as qs assert qs.encode( {'a': None, 'b': ''}, qs.EncodeOptions(strict_null_handling=True), ) == 'a&b=' ``` -------------------------------- ### qs_codec.enums.list_format Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.enums.rst Provides enumeration for various list formatting options in qs_codec. ```python import qs_codec.enums.list_format # Example usage (assuming ListFormat.COMMA_SEPARATED is defined): # print(qs_codec.enums.list_format.ListFormat.COMMA_SEPARATED) ``` -------------------------------- ### Filtering Query String Keys with a List Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates using a list to select specific keys for inclusion in the encoded query string. ```python import qs_codec as qs # Second case: using a list as filter assert qs.encode( {'a': 'b', 'c': 'd', 'e': 'f'}, qs.EncodeOptions( encode=False, filter=['a', 'e'] ) ) == 'a=b&e=f' ``` -------------------------------- ### qs_codec.utils.encode_utils Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.utils.rst Provides utility functions for encoding various data formats. This module is part of the qs_codec project and is used for handling encoding operations. ```python from qs_codec.utils.encode_utils import * # Example usage (assuming functions are defined in encode_utils) # encoded_string = encode_base64(data) # encoded_string = encode_url(data) ``` -------------------------------- ### qs_codec.models.undefined Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.models.rst Documentation for the undefined module within the qs_codec.models package. This module might handle or represent undefined values. ```python from qs_codec.models.undefined import Undefined # Example usage (assuming Undefined class exists) value = Undefined() print(value) ``` -------------------------------- ### qs_codec.utils.decode_utils Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.utils.rst Provides utility functions for decoding various data formats. This module is part of the qs_codec project and is used for handling decoding operations. ```python from qs_codec.utils.decode_utils import * # Example usage (assuming functions are defined in decode_utils) # decoded_data = decode_base64(encoded_string) # decoded_data = decode_url(encoded_string) ``` -------------------------------- ### Override List Index Limit Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates overriding the default list index limit using DecodeOptions. ```python import qs_codec as qs assert qs.decode( 'a[1]=b', qs.DecodeOptions(list_limit=0), ) == {'a': {'1': 'b'}} ``` -------------------------------- ### Regular Expression Delimiter Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates using a regular expression as a delimiter for query string parsing. ```python import qs_codec as qs import re assert qs.decode( 'a=b&c=d', qs.DecodeOptions(delimiter=re.compile('&')), ) == {'a': 'b', 'c': 'd'} ``` -------------------------------- ### Allow Empty Lists in DecodeOptions Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to use the `allow_empty_lists` option in `DecodeOptions` to permit empty list values within a dictionary. ```python import qs_codec as qs assert qs.decode( 'foo[]&bar=baz', qs.DecodeOptions(allow_empty_lists=True), ) == {'foo': [], 'bar': 'baz'} ``` -------------------------------- ### Custom Character Set Decoding (Shift JIS) Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to define and use a custom decoder function to handle character sets like Shift JIS for decoding query strings. ```python import qs_codec as qs import re import codecs import typing as t def custom_decoder( string: str, charset: t.Optional[qs.Charset], ) -> t.Optional[str]: if string: result: t.List[int] = [] while string: match: t.Optional[t.Match[str]] = re.search(r'%([0-9A-F]{2})', string, re.IGNORECASE) if match: result.append(int(match.group(1), 16)) string = string[match.end():] else: break buf: bytes = bytes(result) return codecs.decode(buf, 'shift_jis') return None assert qs.decode( '%61=%82%b1%82%f1%82%c9%82%bf%82%cd%81%49', qs.DecodeOptions(decoder=custom_decoder) ) == {'a': 'こんにちは!'} ``` -------------------------------- ### Strict Null Handling (Encoding) Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to use the `strict_null_handling` flag in `EncodeOptions` to differentiate between `None` values and empty strings during encoding. `None` values are rendered without an equals sign. ```python import qs_codec as qs assert qs.encode( {'a': None, 'b': ''}, qs.EncodeOptions(strict_null_handling=True), ) == 'a&b=' ``` -------------------------------- ### Decoding Percent-Encoded Octets with LATIN1 Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to decode percent-encoded octets using the `LATIN1` charset option in `DecodeOptions` for legacy compatibility. ```python import qs_codec as qs assert qs.decode( 'a=%A7', qs.DecodeOptions(charset=qs.Charset.LATIN1), ) == {'a': '§'} ``` -------------------------------- ### Decode Mixed List and Dictionary Notations Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates how mixed list and dictionary notations are merged into a dictionary. ```python import qs_codec as qs assert qs.decode('a[0]=b&a[b]=c') == {'a': {'0': 'b', 'b': 'c'}} ``` -------------------------------- ### Strict Depth Handling Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to enable strict depth checking to throw an error when the depth limit is exceeded. ```python import qs_codec as qs try: qs.decode( 'a[b][c][d][e][f][g][h][i]=j', qs.DecodeOptions(depth=1, strict_depth=True), ) except IndexError as e: assert str(e) == 'Input depth exceeded depth option of 1 and strict_depth is True' ``` -------------------------------- ### Handling None Values as Empty Strings (Default) Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Illustrates the default behavior where None values are encoded as empty strings in the query string. ```python import qs_codec as qs assert qs.encode({'a': None, 'b': ''}) == 'a=&b=' ``` -------------------------------- ### Filtering Query String Keys with a Callable Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to use a callable function to filter and transform keys and values during query string encoding. ```python import qs_codec as qs import datetime import sys # First case: using a Callable as filter assert ( qs.encode( { "a": "b", "c": "d", "e": { "f": ( datetime.datetime.fromtimestamp(123, datetime.UTC) if sys.version_info.major == 3 and sys.version_info.minor >= 11 else datetime.datetime.utcfromtimestamp(123) ), "g": [2], }, }, qs.EncodeOptions( encode=False, filter=lambda prefix, value: { "b": None, "e[f]": int(value.timestamp()) if isinstance(value, datetime.datetime) else value, "e[g][0]": value * 2 if isinstance(value, int) else value, }.get(prefix, value), ), ) == "a=b&c=d&e[f]=123&e[g][0]=4" ) ``` -------------------------------- ### qs_codec.enums.format Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.enums.rst Provides enumeration for different data format specifications in qs_codec. ```python import qs_codec.enums.format # Example usage (assuming Format.JSON is defined): # print(qs_codec.enums.format.Format.JSON) ``` -------------------------------- ### Ensuring JavaScript Package Compatibility Source: https://github.com/techouse/qs_codec/blob/main/CONTRIBUTING.md Bash script to compare the output of the Python qs_codec package with its JavaScript counterpart (qs) by running Node.js and Python scripts. ```bash # cd into the test/comparison directory pushd test/comparison || exit 1 # Install the Node.js dependencies npm install # Run the JavaScript and Python scripts and save their outputs node_output=$(node qs.js) python_output=$(python3 qs.py) # Compare the outputs if [ "$node_output" == "$python_output" ]; then echo "The outputs are identical." else echo "The outputs are different." exit 1 fi popd || exit 1 ``` -------------------------------- ### RFC 3986 vs RFC 1738 Space Encoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Compares the space encoding behavior between RFC 3986 (space to %20) and RFC 1738 (space to +). ```python import qs_codec as qs assert qs.encode({'a': 'b c'}) == 'a=b%20c' assert qs.encode( {'a': 'b c'}, qs.EncodeOptions(format=qs.Format.RFC3986) ) == 'a=b%20c' assert qs.encode( {'a': 'b c'}, qs.EncodeOptions(format=qs.Format.RFC1738) ) == 'a=b+c' ``` -------------------------------- ### Decoding Lists with Array Notation Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how `qs.decode` handles lists using the `[]` notation for array elements. ```python import qs_codec as qs assert qs.decode('a[]=b&a[]=c') == {'a': ['b', 'c']} ``` -------------------------------- ### Encode with Empty Lists Allowed Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to allow empty list values in the query string by setting `allow_empty_lists` to True. This ensures that keys with empty lists are still represented in the encoded output. ```python import qs_codec as qs assert qs.encode( {'foo': [], 'bar': 'baz', }, qs.EncodeOptions( encode=False, allow_empty_lists=True, ), ) == 'foo[]&bar=baz' ``` -------------------------------- ### Merge Mixed Notations Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how the `decode` function merges different notations (e.g., list indices and dictionary keys) for the same parameter into a single dictionary. ```python import qs_codec as qs assert qs.decode('a[0]=b&a[b]=c') == {'a': {'0': 'b', 'b': 'c'}} ``` -------------------------------- ### Customizing Nesting Depth Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to override the default nesting depth limit for dictionary decoding using the `depth` option in `DecodeOptions`. Demonstrates the effect of a custom depth. ```python import qs_codec as qs assert qs.decode( 'a[b][c][d][e][f][g][h][i]=j', qs.DecodeOptions(depth=1), ) == {'a': {'b': {'[c][d][e][f][g][h][i]': 'j'}}} ``` -------------------------------- ### Overriding Delimiter Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how the delimiter used to separate key-value pairs in the query string can be overridden. ```python import qs_codec as qs # Example of overriding the delimiter (specific delimiter not shown in input, placeholder used) # assert qs.encode({'a': 'b', 'c': 'd'}, qs.EncodeOptions(delimiter=';')) == 'a=b;c=d' ``` -------------------------------- ### Deeply Nested Dictionary Decoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates decoding of deeply nested dictionaries and the default depth limit. ```python import qs_codec as qs assert qs.decode('foo[bar][baz]=foobarbaz') == {'foo': {'bar': {'baz': 'foobarbaz'}}} ``` -------------------------------- ### Default None Value Handling Source: https://github.com/techouse/qs_codec/blob/main/README.rst Explains the default behavior of qs_codec where `None` values are treated as empty strings during encoding. This is the standard behavior for many query string implementations. ```python import qs_codec as qs assert qs.encode({'a': None, 'b': ''}) == 'a=&b=' ``` -------------------------------- ### Decode Lists of Dictionaries Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates decoding a query string that results in a list of dictionaries. ```python import qs_codec as qs assert qs.decode('a[][b]=c') == {'a': [{'b': 'c'}]} ``` -------------------------------- ### Custom Character Set Encoding (Shift JIS) Source: https://github.com/techouse/qs_codec/blob/main/README.rst Shows how to define and use a custom encoder function to handle character sets like Shift JIS for encoding query strings. ```python import qs_codec as qs import codecs import typing as t def custom_encoder( string: str, charset: t.Optional[qs.Charset], format: t.Optional[qs.Format], ) -> str: if string: buf: bytes = codecs.encode(string, 'shift_jis') result: t.List[str] = ['{:02x}'.format(b) for b in buf] return '%' + '%'.join(result) return '' assert qs.encode( {'a': 'こんにちは!'}, qs.EncodeOptions(encoder=custom_encoder) ) == '%61=%82%b1%82%f1%82%c9%82%bf%82%cd%81%49' ``` -------------------------------- ### Ignoring Query Prefix Source: https://github.com/techouse/qs_codec/blob/main/README.rst Shows how to bypass a leading question mark in the query string using DecodeOptions. ```python import qs_codec as qs assert qs.decode( '?a=b&c=d', qs.DecodeOptions(ignore_query_prefix=True), ) == {'a': 'b', 'c': 'd'} ``` -------------------------------- ### Encoding Datetime to ISO 8601 String Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to serialize datetime objects to ISO 8601 formatted strings during query string encoding. ```python import qs_codec as qs import datetime import sys # First case: encoding a datetime object to an ISO 8601 string assert ( qs.encode( { "a": ( datetime.datetime.fromtimestamp(7, datetime.UTC) if sys.version_info.major == 3 and sys.version_info.minor >= 11 else datetime.datetime.utcfromtimestamp(7) ) }, qs.EncodeOptions(encode=False), ) == "a=1970-01-01T00:00:07+00:00" if sys.version_info.major == 3 and sys.version_info.minor >= 11 else "a=1970-01-01T00:00:07" ) ``` -------------------------------- ### Decode Lists with Empty String Values Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates decoding lists where empty strings are preserved as values. ```python import qs_codec as qs assert qs.decode('a[]=&a[]=b') == {'a': ['', 'b']} ``` ```python import qs_codec as qs assert qs.decode('a[0]=b&a[1]=&a[2]=c') == {'a': ['b', '', 'c']} ``` -------------------------------- ### Allowing Empty List Values Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Explains how to include empty lists in the encoded output by setting 'allow_empty_lists' to True, which appends '[]' to the key. ```python import qs_codec as qs assert qs.encode( {'foo': [], 'bar': 'baz'}, qs.EncodeOptions( encode=False, allow_empty_lists=True, ), ) == 'foo[]&bar=baz' ``` -------------------------------- ### URI Encoded String Decoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Illustrates that qs-codec correctly decodes URI-encoded query strings. ```python import qs_codec as qs assert qs.decode('a%5Bb%5D=c') == {'a': {'b': 'c'}} ``` -------------------------------- ### Custom Delimiter Usage Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates using a custom delimiter for separating key-value pairs in a query string. ```python import qs_codec as qs assert qs.decode( 'a=b;c=d', qs.DecodeOptions(delimiter=';'), ) == {'a': 'b', 'c': 'd'} ``` -------------------------------- ### Ignoring Query Prefix Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to use the `ignore_query_prefix` option to automatically strip a leading question mark ('?') from the query string before decoding. ```python import qs_codec as qs assert qs.decode( '?a=b&c=d', qs.DecodeOptions(ignore_query_prefix=True), ) == {'a': 'b', 'c': 'd'} ``` -------------------------------- ### List Encoding Format (Default) Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates the default behavior of encoding lists using the `INDICES` format, where each list element is accessed by its numerical index. ```python import qs_codec as qs assert qs.encode( ``` -------------------------------- ### qs_codec.encode Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.rst Houses functions for encoding data within the qs_codec package. It includes members, undocumented members, and inheritance information. ```python from qs_codec import encode # Example usage of encode functions (specific functions depend on module content) # encoded_data = encode.some_encode_function(data_to_encode) # print(encoded_data) ``` -------------------------------- ### Dot Notation for Nested Keys Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates enabling dot notation for nested keys using the `allow_dots` option. Also shows `decode_dot_in_keys` for decoding dots within keys, which implies `allow_dots`. ```python import qs_codec as qs assert qs.decode( 'a.b=c', qs.DecodeOptions(allow_dots=True), ) == {'a': {'b': 'c'}} ``` ```python import qs_codec as qs assert qs.decode( 'name%252Eobj.first=John&name%252Eobj.last=Doe', qs.DecodeOptions(decode_dot_in_keys=True), ) == {'name.obj': {'first': 'John', 'last': 'Doe'}} ``` -------------------------------- ### qs_codec.decode Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.rst Contains functions for decoding data within the qs_codec package. It exposes members, undocumented members, and inheritance details. ```python from qs_codec import decode # Example usage of decode functions (specific functions depend on module content) # decoded_data = decode.some_decode_function(encoded_bytes) # print(decoded_data) ``` -------------------------------- ### Sorting Query String Keys Alphabetically Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Demonstrates how to sort the keys of a query string alphabetically using a custom sorting function. ```python import qs_codec as qs assert qs.encode( {'a': 'c', 'z': 'y', 'b': 'f'}, qs.EncodeOptions( encode=False, sort=lambda a, b: (a > b) - (a < b) ) ) == 'a=c&b=f&z=y' ``` -------------------------------- ### Custom Delimiter Decoding Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to decode a query string using a custom delimiter pattern. This is useful when query strings use separators other than the standard '&'. ```python import qs_codec as qs import re assert qs.decode( 'a=b;c=d', qs.DecodeOptions(delimiter=re.compile(r'[;,]')), ) == {'a': 'b', 'c': 'd'} ``` -------------------------------- ### Encode with Charset Sentinel Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Shows how to use the `charset_sentinel` option to include a 'utf8=✓' parameter, indicating the character encoding used. This is a common practice in web frameworks like Ruby on Rails. ```python import qs_codec as qs assert qs.encode( {'a': '☺'}, qs.EncodeOptions(charset_sentinel=True) ) == 'utf8=%E2%9C%93&a=%E2%98%BA' ``` ```python import qs_codec as qs assert qs.encode( {'a': 'æ'}, qs.EncodeOptions(charset=qs.Charset.LATIN1, charset_sentinel=True) ) == 'utf8=%26%2310003%3B&a=%E6' ``` -------------------------------- ### Encoding with LATIN1 Charset Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates how to specify the `LATIN1` charset using the `charset` option in `EncodeOptions` for compatibility with systems that require this encoding. Characters not present in LATIN1 are converted to numeric entities. ```python import qs_codec as qs assert qs.encode( {'æ': 'æ'}, qs.EncodeOptions(charset=qs.Charset.LATIN1) ) == '%E6=%E6' ``` -------------------------------- ### qs_codec.enums.charset Module Source: https://github.com/techouse/qs_codec/blob/main/docs/qs_codec.enums.rst Provides enumeration for character set definitions used in qs_codec. ```python import qs_codec.enums.charset # Example usage (assuming Charset.UTF8 is defined): # print(qs_codec.enums.charset.Charset.UTF8) ``` -------------------------------- ### Space Encoding Formats (RFC3986 vs RFC1738) Source: https://github.com/techouse/qs_codec/blob/main/docs/README.rst Compares the two space encoding formats supported by the library: RFC3986, which encodes spaces as '%20', and RFC1738, which encodes spaces as '+'. ```python import qs_codec as qs assert qs.encode( {'a': 'b c'}, qs.EncodeOptions(format=qs.Format.RFC3986) ) == 'a=b%20c' ``` ```python import qs_codec as qs assert qs.encode( {'a': 'b c'}, qs.EncodeOptions(format=qs.Format.RFC1738) ) == 'a=b+c' ``` -------------------------------- ### Filter Keys with List Source: https://github.com/techouse/qs_codec/blob/main/README.rst Demonstrates using a list of keys with the `filter` option in EncodeOptions to include only specific top-level keys in the encoded output. This is a simpler way to select a subset of data. ```python import qs_codec as qs assert qs.encode( {'a': 'b', 'c': 'd', 'e': 'f'}, qs.EncodeOptions( encode=False, filter=['a', 'e'] ) ) == 'a=b&e=f' ```