Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#
2# Copyright (C) 2019-2020 Leo P. Singer <leo.singer@ligo.org>
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program. If not, see <https://www.gnu.org/licenses/>.
16#
17from __future__ import absolute_import
18from os.path import basename
19from mimetypes import guess_type
20from sys import stdin
22from requests.utils import guess_filename, to_key_val_list
25def _guess_content_type(filename):
26 return guess_type(filename)[0] or 'application/octet-stream'
29def _guess_mime_type(key, val):
30 if not isinstance(val, (tuple, list)):
31 filename = guess_filename(val) or key
32 filetype = _guess_content_type(filename)
33 val = (filename, val, filetype)
34 elif len(val) < 3 or val[2] is None:
35 filename = val[0]
36 filetype = _guess_content_type(filename)
37 # val = (*val[:2], filetype, *val[3:])
38 # FIXME: Python 2
39 val = tuple(val[:2]) + (filetype,) + tuple(val[3:])
40 return key, val
43def _read_files(key, val):
44 if isinstance(val, (tuple, list)) and (len(val) < 2 or val[1] is None):
45 filename = val[0]
46 with (stdin.buffer if filename == '-' else open(filename, 'rb')) as f:
47 data = f.read()
48 filename = basename(filename)
49 # val = (filename, data, *val[2:])
50 # FIXME: Python 2
51 val = (filename, data) + tuple(val[2:])
52 return key, val
55def _prepare_file(key, val):
56 key, val = _read_files(key, val)
57 key, val = _guess_mime_type(key, val)
58 return key, val
61def _prepare_files(files):
62 if files is not None:
63 files = [_prepare_file(k, v) for k, v in to_key_val_list(files)]
64 return files
67class SessionFileMixin(object):
68 """A mixin for :class:`requests.Session` to add features for file uploads.
70 The :meth:`requests.Session.request` method takes a `files` argument which
71 is a dictionary of `{fieldname: fileobject}`, where `fileobject` may be a
72 file-like object or a tuple of 2-4 elements consisting of the filename,
73 file content, MIME type, and any custom headers.
75 This mixin adds the following features:
77 * The MIME type is automatically guessed from the filename.
78 * If the file content is None, then the filename is treated as a path, and
79 the file is opened and read. If the filename is `-`, then the file
80 content is read from stdin.
81 """
83 def request(
84 self, method, url, params=None, data=None, headers=None,
85 cookies=None, files=None, auth=None, timeout=None,
86 allow_redirects=True, proxies=None, hooks=None, stream=None,
87 verify=None, cert=None, json=None):
88 return super(SessionFileMixin, self).request(
89 method, url, params=params, data=data, headers=headers,
90 cookies=cookies, files=_prepare_files(files), auth=auth,
91 timeout=timeout, allow_redirects=True, proxies=proxies,
92 hooks=hooks, stream=stream, verify=verify, cert=cert, json=json)