В файле requests/api.py нет новой функциональности; она существует для того, чтобы предоставить пользователю простой API. Плюс размещение строковых методов HTTP непосредственно в API в качестве имен функций означает, что любая опечатка в имени метода будет найдена на ранних этапах, например:
>>> requests.foo('http://www.python.org')
Traceback (most recent call last):
····File "
AttributeError: 'module' object has no attribute 'foo'
>>>
>>> requests.request('foo', 'http://www.python.org')
Файл __init__.py предоставляет классы Request, PreparedRequest и Response из файла models.py как часть основного API. Зачем вообще нужен файл models.Request? В стандартной библиотеке уже существует urllib.requests.Request, и в файле cookies.py находится объект MockRequest, который оборачивает models.Request, чтобы он работал как urllib.requests.Request для http.cookiejar[66]. Это означает, что любые методы, необходимые для взаимодействия объекта типа Request с библиотекой cookies, намеренно исключены из requests.Request. Для чего эти лишние усилия?
Дополнительные методы в MockRequest (нужен для эмуляции urllib.request.Request для библиотеки cookies) используются библиотекой cookies для управления cookies. За исключением функции get_type() (которая обычно возвращает http или https при использовании) и непроверяемого свойства (в нашем случае True), они связаны с URL или заголовками запросов.
• add_unredirected_header() — добавить в заголовок новую пару ключ-значение;
• get_header() — получить определенное имя из словаря заголовков;
• get_new_headers() — получить словарь, содержащий новые заголовки (которые добавлены с помощью cookielib);
• has_header() — проверяем, существует ли имя в словаре заголовков.
• get_full_url() — соответствует своему имени;
• host и origin_req_host — свойства, чьи значения устанавливаются путем вызова методов get_host() и get_origin_req_host() соответственно;
• get_host() — извлекает хост из URL (например, www.python.org из https://www.python.org/dev/peps/pep-0008/);
• get_origin_req_host() — вызывает get_host()[67].
Все они являются функциями доступа, за исключением MockRequest.add_unredirected_header().
В строке документации к объекту MockRequest указывается, что «оригинальный объект запроса доступен только для чтения».
В requests.Request вместо этого непосредственно доступны атрибуты данных. Это делает все функции доступа ненужными: для получения или установки заголовков требуется лишь получить доступ к словарю request-instance.headers. Аналогично пользователь может получить или изменить строку URL: request-instance.url.
Объект PreparedRequest инициализируется пустым и заполняется при вызове метода prepared-request-instance.prepare(), что наполняет его релевантными данными (обычно получаемыми путем вызова объекта Request). В этот момент применяются исправления регистра символов, кодировки и пр. Содержимое объекта после подготовки можно будет отправить на сервер, но к каждому атрибуту все еще можно получить доступ непосредственно. Доступен даже PreparedRequest._cookies, однако нижнее подчеркивание, с которого начинается это имя, намекает на то, что атрибут не предназначен для использования за пределами класса, не запрещая при этом доступ (мы все — ответственные пользователи).
Этот выбор позволяет пользователю изменять объекты, но они становятся гораздо читабельнее, а дополнительная работа, выполняемая внутри PreparedRequest, позволяет исправить проблемы с регистром и использовать словарь вместо CookieJar (ищите оператор if isinstance()/else):
#
#… из файла models.py…
#
class PreparedRequest():
····#
····#…пропускаем все остальное…
····#
····def prepare_cookies(self, cookies):
········"""Подготавливает данные заданного HTTP cookie.
········Эта функция в итоге генерирует заголовок ''Cookie'' на основе
········предоставленных cookies с использованием cookielib. Из-за особенностей
········дизайна cookielib заголовок не будет сгенерирован повторно,
········если он уже существует. Это значит, что эта функция может быть
········вызвана всего один раз во время жизни объекта