Multidict is dict-like collection of key-value pairs where key might be occurred more than once in the container.

Overview

multidict

GitHub status for master branch Coverage metrics PyPI Documentationb Python versions Chat on Gitter

Multidict is dict-like collection of key-value pairs where key might be occurred more than once in the container.

Introduction

HTTP Headers and URL query string require specific data structure: multidict. It behaves mostly like a regular dict but it may have several values for the same key and preserves insertion ordering.

The key is str (or istr for case-insensitive dictionaries).

multidict has four multidict classes: MultiDict, MultiDictProxy, CIMultiDict and CIMultiDictProxy.

Immutable proxies (MultiDictProxy and CIMultiDictProxy) provide a dynamic view for the proxied multidict, the view reflects underlying collection changes. They implement the collections.abc.Mapping interface.

Regular mutable (MultiDict and CIMultiDict) classes implement collections.abc.MutableMapping and allows to change their own content.

Case insensitive (CIMultiDict and CIMultiDictProxy) ones assume the keys are case insensitive, e.g.:

>>> dct = CIMultiDict(key='val')
>>> 'Key' in dct
True
>>> dct['Key']
'val'

Keys should be str or istr instances.

The library has optional C Extensions for sake of speed.

License

Apache 2

Library Installation

$ pip install multidict

The library is Python 3 only!

PyPI contains binary wheels for Linux, Windows and MacOS. If you want to install multidict on another operation system (or Alpine Linux inside a Docker) the Tarball will be used to compile the library from sources. It requires C compiler and Python headers installed.

To skip the compilation please use MULTIDICT_NO_EXTENSIONS environment variable, e.g.:

$ MULTIDICT_NO_EXTENSIONS=1 pip install multidict

Please note, Pure Python (uncompiled) version is about 20-50 times slower depending on the usage scenario!!!

Changelog

See RTD page.

Comments
  • Mypy 0.620 and generic type aliases

    Mypy 0.620 and generic type aliases

    • Fixes new check appeared in mypy 0.620
    • Also fixes usage of generic type aliases in some places (see below)

    Things I've noticed:

    • MultiDictProxy.copy and CIMultiDictProxy.copy had wrong return type (fixed)
    • MultiDictProxy is inherited from a different class in .pyx and .py implementation
    • Coundn't enable disallow_any_generics = True in mypy config because there are a lot of errors like No library stub file for module 'pytest' (see travis). Not sure what to do with them.
    • Update: Using _S as a type name in MultiDict[_S, _T] confuses _S with a generic argument (TypeVar), while it's just an alias for Union. Probably better name it _Str or alike.
    opened by tailhook 30
  • fix pickling of multidicts

    fix pickling of multidicts

    fixes: https://github.com/aio-libs/multidict/issues/78 fixes when sending multidicts across processes

    testcase:

    import asyncio
    from concurrent.futures import ProcessPoolExecutor
    from aiohttp.web import Response
    from multidict import CIMultiDict
    
    
    class JSONResponseException(Exception):
        def __init__(self, http_status_code:int, payload_object=None, response_headers: CIMultiDict = None):
            self.__http_status_code = http_status_code
            self.__payload_object = payload_object if payload_object is not None else {}
            self.__response_headers = response_headers if response_headers is not None else CIMultiDict()
    
        @property
        def http_status_code(self):
            return self.__http_status_code
    
        @property
        def payload_object(self):
            return self.__payload_object
    
        @property
        def response_headers(self):
            return self.__response_headers
    
    
    def foo():
        err = JSONResponseException(404)
        raise err
    
    async def main(loop):
        with ProcessPoolExecutor() as executor:
            try:
                await loop.run_in_executor(executor, foo)
            except JSONResponseException as e:
                return Response(body=b'',
                                headers=e.response_headers,
                                status=e.http_status_code,
                                content_type='application/json')
    
    if __name__ == '__main__':
        _loop = asyncio.get_event_loop()
        _loop.run_until_complete(main(_loop))
    
    opened by thehesiod 23
  • Wheel support for linux aarch64

    Wheel support for linux aarch64

    Summary Installing multidict on aarch64 via pip using command "pip3 install multidict" tries to build wheel from source code

    Problem description multidict don't have wheel for aarch64 on PyPI repository. So, while installing multidict via pip on aarch64, pip builds wheel for same resulting in it takes more time to install multidict. Making wheel available for aarch64 will benefit aarch64 users by minimizing multidict installation time.

    Expected Output Pip should be able to download multidict wheel from PyPI repository rather than building it from source code.

    @multidict-taem, please let me know if I can help you building wheel/uploading to PyPI repository. I am curious to make multidict wheel available for aarch64. It will be a great opportunity for me to work with you.

    enhancement 
    opened by odidev 18
  • multidict 4.5 memory leak

    multidict 4.5 memory leak

    It seems like the recent version of multidict brakes aiohttp somehow.

    Server:

    from aiohttp import web
    
    async def hello(request):
        return web.json_response(await request.json())
    
    app = web.Application()
    app.add_routes([web.post('/', hello)])
    web.run_app(app)
    

    Client:

    import asyncio
    import aiohttp
    
    async def foo(times):
        data = {'foo': 1}
        async with aiohttp.ClientSession() as session:
            for x in range(times):
                resp = await session.post('http://localhost:8080', json=data)
                if not x % 100:
                    print(await resp.json())
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(foo(100000))
    loop.close()
    

    Just after 100000 cycles this simple server takes 171M of ram and doesn't release it. 4.4.2 works like a charm.

    python 3.6.4 aiohttp 3.4.4 but should affect other versions multidict>=4.0,<5.0

    bug 
    opened by byashimov 15
  • Consider moving package to `src` subfolder

    Consider moving package to `src` subfolder

    As per https://hynek.me/articles/testing-packaging/ when testing --editable (develop) install you are not testing the package installed same way as it will be installed in by users.

    @asvetlov what do you think about such approach? Sounds reasonable to me.

    opened by webknjaz 14
  • Rebuild multidict using cython 0.29.0

    Rebuild multidict using cython 0.29.0

    Describe the bug

    This will resolve #79 and #101

    To Reproduce

    script

    rm -rf venv
    virtualenv venv -ppython3.6
    venv/bin/pip install multidict
    venv/bin/python -Werror -c 'import multidict'
    

    output

    ...
    Successfully installed multidict-4.4.2
    $ venv/bin/python -Werror -c 'import multidict'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/t/venv/lib/python3.6/site-packages/multidict/__init__.py", line 23, in <module>
        from ._multidict import (MultiDictProxy,
      File "multidict/_multidict.pyx", line 9, in init multidict._multidict
    ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
    

    Expected behavior

    (silence)

    Logs/tracebacks

    see above

    Your version of the Python

    $ ./venv/bin/python --version --version
    Python 3.6.6 (default, Sep 12 2018, 18:26:19) 
    [GCC 8.0.1 20180414 (experimental) [trunk revision 259383]]
    

    Your version of the multidict distribution

    see above

    Additional context

    The current wheel is built against 0.28.5:

    $ grep Generated !$
    grep Generated venv/lib/python3.6/site-packages/multidict/_multidict.c
    /* Generated by Cython 0.28.5 */
    

    Building from source against 0.28.5 produces the error:

    rm -rf venv
    virtualenv venv -ppython3.6
    venv/bin/pip install cython==0.28.5
    git -C multidict clean -fxfd
    venv/bin/pip install ./multidict
    venv/bin/python -Werror -c 'import multidict'
    
    ...
    $ venv/bin/python -Werror -c 'import multidict'
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/t/venv/lib/python3.6/site-packages/multidict/__init__.py", line 23, in <module>
        from ._multidict import (MultiDictProxy,
      File "multidict/_multidict.pyx", line 9, in init multidict._multidict
    ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
    

    Building from source against 0.29.0:

    rm -rf venv
    virtualenv venv -ppython3.6
    venv/bin/pip install cython==0.29.0
    git -C multidict clean -fxfd
    venv/bin/pip install ./multidict
    venv/bin/python -Werror -c 'import multidict'
    
    ...
    $ venv/bin/python -Werror -c 'import multidict'
    $ 
    

    proper silence!

    bug 
    opened by asottile 13
  • Refactor unit tests

    Refactor unit tests

    Changes:

    • merged test_instantiate__from_arg0 and test_instantiate__from_arg0_dict
    • tests from _BaseMutableMultiDictTests are at TestMutableMultiDict
    • TestNonProxyCIMultiDict#test_extend_with_istr was moved to TestMutableMultiDict
    • _TestProxy/_TestCIProxy#test_copy was moved to test_proxy_copy

    Questions:

    • test_instantiate__with_kwargs: should we rely on order and drop sorted?
    • test_instantiate__empty: is duplication done by purpose?
    • test_items__contains: is duplication done by purpose?
    • test_get duplicates test_getone
    • _CIMultiDictTests was inherited from _Root and not _BaseTest
    • test__iter__types was done only for non-ci dicts. Should I add CI classes?
    opened by akhomchenko 13
  • Pre-compiled shared libraries

    Pre-compiled shared libraries

    I'm attempting to build a distribution package from the source on PyPi. However, the source contains the compiled shared library _istr.cpython-34m.so.

    This causes problems if the arch and Python version don't match up with the library. Manually removing the file from the source solves the problem but it doesn't seem like this should exist in the source package?

    I also noticed the source on PyPi does not match up with the source on Github. Github does not contain the _multidict.c file. Is this also a build artifact that was compiled from the pyx file?

    The url I'm pulling source from is: https://files.pythonhosted.org/packages/source/m/multidict/multidict-%{version}.tar.gz

    opened by smarlowucf 12
  • Importing multidict raises ImportWarning on 3.6

    Importing multidict raises ImportWarning on 3.6

    $ python -We -c "import multidict as x; print(x.__version__)"
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/home/antoine/miniconda3/envs/dask36/lib/python3.6/site-packages/multidict/__init__.py", line 24, in <module>
        from ._multidict import (MultiDictProxy,
      File "multidict/_multidict.pyx", line 1, in init multidict._multidict (multidict/_multidict.c:14817)
    ImportWarning: can't resolve package from __spec__ or __package__, falling back on __name__ and __path__
    
    opened by pitrou 12
  • multidict 4.7.1 causes segfault when bundled with PyInstaller

    multidict 4.7.1 causes segfault when bundled with PyInstaller

    Describe the bug

    After upgrading to multidict 4.7.1 we have found that the applications we bundle using PyInstaller crash. Actually, I discovered this problem because we use aiohttp which depends on multidict. Version 4.6.1 does not have this problem.

    To Reproduce

    1. Create a new virtual environment
    2. pip install multidict==4.7.1 pyinstaller
    3. Create a simple test.py script with:
    print("Hello!")
    import multidict
    
    1. Bundle it pyinstaller test.py
    2. Run it:
    ./dist/test/test
    Hello!
    [1]    22548 segmentation fault (core dumped)  ./dist/test/test
    

    Expected behavior

    Application prints "Hello!" and quits nicely.

    Logs/tracebacks

    Provided above.

    Your version of the Python

    Observed with 3.6.9 and 3.7.5

    Your version of the multidict distribution

    4.7.1

    Additional context

    N/A

    opened by gmarull 11
  • Tox based tests

    Tox based tests

    This attempts to make tox a single source of truth for all the test envs (mainly CI, but it wires it into GNU make as well.

    I didn't test deployment flow yet, but current results look promising in terms of clearly separating different envs/tasks + there's a nice ~10% speedup in Travis.

    opened by webknjaz 10
  • Bump sphinx from 5.3.0 to 6.1.1

    Bump sphinx from 5.3.0 to 6.1.1

    Bumps sphinx from 5.3.0 to 6.1.1.

    Release notes

    Sourced from sphinx's releases.

    v6.1.1

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    v6.1.0

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    v6.0.1

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    v6.0.0

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    v6.0.0b2

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    v6.0.0b1

    Changelog: https://www.sphinx-doc.org/en/master/changes.html

    Changelog

    Sourced from sphinx's changelog.

    Release 6.1.1 (released Jan 05, 2023)

    Bugs fixed

    • #11091: Fix util.nodes.apply_source_workaround for literal_block nodes with no source information in the node or the node's parents.

    Release 6.1.0 (released Jan 05, 2023)

    Dependencies

    Incompatible changes

    • #10979: gettext: Removed support for pluralisation in get_translation. This was unused and complicated other changes to sphinx.locale.

    Deprecated

    • sphinx.util functions:

      • Renamed sphinx.util.typing.stringify() to sphinx.util.typing.stringify_annotation()
      • Moved sphinx.util.xmlname_checker() to sphinx.builders.epub3._XML_NAME_PATTERN

      Moved to sphinx.util.display:

      • sphinx.util.status_iterator
      • sphinx.util.display_chunk
      • sphinx.util.SkipProgressMessage
      • sphinx.util.progress_message

      Moved to sphinx.util.http_date:

      • sphinx.util.epoch_to_rfc1123
      • sphinx.util.rfc1123_to_epoch

      Moved to sphinx.util.exceptions:

      • sphinx.util.save_traceback

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies autosquash 
    opened by dependabot[bot] 1
  • Specify the build system in pyproject.toml

    Specify the build system in pyproject.toml

    What do these changes do?

    Adds build-backend to pyproject.toml so that there's no warnings from pip when building from source (+ so that modern setuptools backend is used).

    Are there changes in behavior for the user?

    pip will no longer show warning:

      WARNING: Missing build requirements in pyproject.toml for multidict==6.0.4 from https://files.pythonhosted.org/packages/4a/15/bd620f7a6eb9aa5112c4ef93e7031bcd071e0611763d8e17706ef8ba65e0/multidict-6.0.4.tar.gz.
      WARNING: The project does not specify a build backend, and pip cannot fall back to setuptools without 'wheel'.
    

    Related issue number

    None

    Checklist

    • [x] I think the code is well written
    • [ ] Unit tests for the changes exist
    • [ ] Documentation reflects the changes
    • [ ] Add a new news fragment into the CHANGES folder
      • name it <issue_id>.<type> (e.g. 588.bugfix)
      • if you don't have an issue_id change it to the pr id after creating the PR
      • ensure type is one of the following:
        • .feature: Signifying a new feature.
        • .bugfix: Signifying a bug fix.
        • .doc: Signifying a documentation improvement.
        • .removal: Signifying a deprecation or removal of public API.
        • .misc: A ticket has been closed, but it is not of interest to users.
      • Make sure to use full sentences with correct case and punctuation, for example: Fix issue with non-ascii contents in doctest text files.
    bot:chronographer:provided 
    opened by Jackenmen 3
  • Enhancement: `to_dict` method

    Enhancement: `to_dict` method

    Hi there,

    Thanks for this library. I'd like to ask for a convenience method that output a dict of a multidict - with lists for multi-values. Currently I have this:

        def dict(self) -> Dict[str, List[Any]]:
            """
    
            Returns:
                A dict of lists
            """
            return {k: self.getall(k) for k in set(self.keys)}
    

    While this works, its not very performant.

    opened by Goldziher 1
  • Add a sketch for static keys cache

    Add a sketch for static keys cache

    The idea is: statically cache the most common HTTP headers.

    For example, aiohttp.hdrs can do the following:

    CONTENT_LENGTH = istr("Content-Length")
    multidict.add_static_cache(str(CONTENT_LENGTH), CONTENT_LENGTH)
    multidict.add_static_cache(str(CONTENT_LENGTH).lower(), CONTENT_LENGTH)
    multidict.add_static_cache(str(CONTENT_LENGTH).upper(), CONTENT_LENGTH)
    
    opened by asvetlov 0
  • Make keys view reversible

    Make keys view reversible

    Since Python 3.8 keys view is reversible (but Mapping/MutableMapping ABCs are not for the sake of backward compatibility).

    It would be nice to support reversibility in multidict keys views as well.

    opened by asvetlov 0
  • Don't track multidict if it contains untrackable objects only

    Don't track multidict if it contains untrackable objects only

    Multidict is used mostly for storing primitive types as keys and values: str, int, float, None.

    PyObject_GC_Track should be called only if a key or value doesn't belong to a primitive type.

    BTW, now PyObject_GC_Track is not called for multidicts and proxies which is an error.

    opened by asvetlov 1
Releases(v6.0.4)
Owner
aio-libs
The set of asyncio-based libraries built with high quality
aio-libs
dict subclass with keylist/keypath support, normalized I/O operations (base64, csv, ini, json, pickle, plist, query-string, toml, xml, yaml) and many utilities.

python-benedict python-benedict is a dict subclass with keylist/keypath support, I/O shortcuts (base64, csv, ini, json, pickle, plist, query-string, t

Fabio Caccamo 799 Jan 09, 2023
Programming of a spanning tree algorithm with Python : In depth first with a root node.

ST Algorithm Programming of a spanning tree algorithm with Python : In depth first with a root node. Description This programm reads informations abou

Mathieu Lamon 1 Dec 16, 2021
A collection of data structures and algorithms I'm writing while learning

Data Structures and Algorithms: This is a collection of data structures and algorithms that I write while learning the subject Stack: stack.py A stack

Dhravya Shah 1 Jan 09, 2022
Solutions for leetcode problems.

Leetcode-solution This is an repository for storring new algorithms that I am learning form the LeetCode for future use. Implemetations Two Sum (pytho

Shrutika Borkute 1 Jan 09, 2022
🔬 Fixed struct serialization system, using Python 3.9 annotated type hints

py-struct Fixed-size struct serialization, using Python 3.9 annotated type hints This was originally uploaded as a Gist because it's not intended as a

Alba Mendez 4 Jan 14, 2022
pyprobables is a pure-python library for probabilistic data structures

pyprobables is a pure-python library for probabilistic data structures. The goal is to provide the developer with a pure-python implementation of common probabilistic data-structures to use in their

Tyler Barrus 86 Dec 25, 2022
A mutable set that remembers the order of its entries. One of Python's missing data types.

An OrderedSet is a mutable data structure that is a hybrid of a list and a set. It remembers the order of its entries, and every entry has an index nu

Elia Robyn Lake (Robyn Speer) 173 Nov 28, 2022
A HDF5-based python pickle replacement

Hickle Hickle is an HDF5 based clone of pickle, with a twist: instead of serializing to a pickle file, Hickle dumps to an HDF5 file (Hierarchical Data

Danny Price 450 Dec 21, 2022
A Munch is a Python dictionary that provides attribute-style access (a la JavaScript objects).

munch munch is a fork of David Schoonover's Bunch package, providing similar functionality. 99% of the work was done by him, and the fork was made mai

Infinidat Ltd. 643 Jan 07, 2023
Google, Facebook, Amazon, Microsoft, Netflix tech interview questions

Algorithm and Data Structures Interview Questions HackerRank | Practice, Tutorials & Interview Preparation Solutions This repository consists of solut

Quan Le 8 Oct 04, 2022
An command-line utility that schedules your exams preparation routines

studyplan A tiny utility that schedules your exams preparation routines. You only need to specify the tasks and the deadline. App will output a iCal f

Ilya Breitburg 3 May 18, 2022
A Python implementation of red-black trees

Python red-black trees A Python implementation of red-black trees. This code was originally copied from programiz.com, but I have made a few tweaks to

Emily Dolson 7 Oct 20, 2022
A high-performance immutable mapping type for Python.

immutables An immutable mapping type for Python. The underlying datastructure is a Hash Array Mapped Trie (HAMT) used in Clojure, Scala, Haskell, and

magicstack 996 Jan 02, 2023
A mutable set that remembers the order of its entries. One of Python's missing data types.

An OrderedSet is a mutable data structure that is a hybrid of a list and a set. It remembers the order of its entries, and every entry has an index number that can be looked up.

Elia Robyn Lake (Robyn Speer) 173 Nov 28, 2022
This Repository consists of my solutions in Python 3 to various problems in Data Structures and Algorithms

Problems and it's solutions. Problem solving, a great Speed comes with a good Accuracy. The more Accurate you can write code, the more Speed you will

SAMIR PAUL 1.3k Jan 01, 2023
This repository is for adding codes of data structures and algorithms, leetCode, hackerrank etc solutions in different languages

DSA-Code-Snippet This repository is for adding codes of data structures and algorithms, leetCode, hackerrank etc solutions in different languages Cont

DSCSRMNCR 3 Oct 22, 2021
Webtesting for course Data Structures & Algorithms

Selenium job to automate queries to check last posts of Module Data Structures & Algorithms Web-testing for course Data Structures & Algorithms Struct

1 Dec 15, 2021
A JSON-friendly data structure which allows both object attributes and dictionary keys and values to be used simultaneously and interchangeably.

A JSON-friendly data structure which allows both object attributes and dictionary keys and values to be used simultaneously and interchangeably.

Peter F 93 Dec 01, 2022
Data Structure With Python

Data-Structure-With-Python- Python programs also include in this repo Stack A stack is a linear data structure that stores items in a Last-In/First-Ou

Sumit Nautiyal 2 Jan 09, 2022
Svector (pronounced Swag-tor) provides extension methods to pyrsistent data structures

Svector Svector (pronounced Swag-tor) provides extension methods to pyrsistent data structures. Easily chain your methods confidently with tons of add

James Chua 5 Dec 09, 2022