Skip to content

Instantly share code, notes, and snippets.

@ambv
Last active December 16, 2015 14:09
Show Gist options
  • Save ambv/5447062 to your computer and use it in GitHub Desktop.
Save ambv/5447062 to your computer and use it in GitHub Desktop.
Adapter discovery in requests.Session

Look

Having:

>>> import requests
>>> s = requests.Session()

We cannot currently reliably do:

>>> import requests_testadapter
>>> s.mount('http://test.com', requests_testadapter.TestAdapter(b'Mock'))

Because of Session.get_adapter() this might or might not work as expected:

>>> s.get('http://test.com')

This is because there is already a default adapter for 'http://' in the form of requests.adapters.HTTPAdapter. Depending on the (seemingly random) order of keys in the s.adapters dictionary, for some combinations of keys it will work, for others it won't.

Solutions

There are a couple. As usual, a compromise between backwards compatibility, clarity and performance. What if I do :custom:`this`? What if I do this: :pep:8.

Slow but compatible

Change Session.get_adapter() so that it sorts the keys every time it fetches an adapter. The advantage is that session_obj.adapters is still a vanilla dictionary, if you consider it a public API.

A custom dictionary type

Something like Django's SortedDict which would sort the keys on insertion. The advantage is that session_obj.adapters is still a mapping and now Session.get_adapter() is faster. The disadvantage is the maintenance cost of a custom data structure. Also, mild backwards incompatibility if someone somewhere used the fact that session_obj.adapters is exactly of the type dict (unlikely, isn't it?).

A list of tuples

Having Session.mount() and Session.get_adapter() as the public API for adapters, we might just as well implement the sorting while mounting and just maintain session_obj.adapters as a list of tuples. The advantage is that it's the fastest solution with no additional maintenance burden. The disadvantage is backwards incompatibility.

We have to sort... but how exactly?

This is another design issue. It appears that sorting first from the longest key to shortest, and then alphabetically (for keys of the same length), is the way.

You decide

What should we do about it?

By the way

This test adapter in the example above is an actual thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment