Create a pool key out of a request context dictionary. According to RFC 3986, both the scheme and host are case-insensitive. Therefore, this function normalizes both before constructing the pool key for an HTTPS request. If you wish to change this behaviour, provide alternate c
(
key_class: type[PoolKey], request_context: dict[str, typing.Any]
)
| 93 | |
| 94 | |
| 95 | def _default_key_normalizer( |
| 96 | key_class: type[PoolKey], request_context: dict[str, typing.Any] |
| 97 | ) -> PoolKey: |
| 98 | """ |
| 99 | Create a pool key out of a request context dictionary. |
| 100 | |
| 101 | According to RFC 3986, both the scheme and host are case-insensitive. |
| 102 | Therefore, this function normalizes both before constructing the pool |
| 103 | key for an HTTPS request. If you wish to change this behaviour, provide |
| 104 | alternate callables to ``key_fn_by_scheme``. |
| 105 | |
| 106 | :param key_class: |
| 107 | The class to use when constructing the key. This should be a namedtuple |
| 108 | with the ``scheme`` and ``host`` keys at a minimum. |
| 109 | :type key_class: namedtuple |
| 110 | :param request_context: |
| 111 | A dictionary-like object that contain the context for a request. |
| 112 | :type request_context: dict |
| 113 | |
| 114 | :return: A namedtuple that can be used as a connection pool key. |
| 115 | :rtype: PoolKey |
| 116 | """ |
| 117 | # Since we mutate the dictionary, make a copy first |
| 118 | context = request_context.copy() |
| 119 | context["scheme"] = context["scheme"].lower() |
| 120 | context["host"] = context["host"].lower() |
| 121 | |
| 122 | # These are both dictionaries and need to be transformed into frozensets |
| 123 | for key in ("headers", "_proxy_headers", "_socks_options"): |
| 124 | if key in context and context[key] is not None: |
| 125 | context[key] = frozenset(context[key].items()) |
| 126 | |
| 127 | # The socket_options key may be a list and needs to be transformed into a |
| 128 | # tuple. |
| 129 | socket_opts = context.get("socket_options") |
| 130 | if socket_opts is not None: |
| 131 | context["socket_options"] = tuple(socket_opts) |
| 132 | |
| 133 | # Map the kwargs to the names in the namedtuple - this is necessary since |
| 134 | # namedtuples can't have fields starting with '_'. |
| 135 | for key in list(context.keys()): |
| 136 | context["key_" + key] = context.pop(key) |
| 137 | |
| 138 | # Default to ``None`` for keys missing from the context |
| 139 | for field in key_class._fields: |
| 140 | if field not in context: |
| 141 | context[field] = None |
| 142 | |
| 143 | # Default key_blocksize to _DEFAULT_BLOCKSIZE if missing from the context |
| 144 | if context.get("key_blocksize") is None: |
| 145 | context["key_blocksize"] = _DEFAULT_BLOCKSIZE |
| 146 | |
| 147 | return key_class(**context) |
| 148 | |
| 149 | |
| 150 | #: A dictionary that maps a scheme to a callable that creates a pool key. |