hbmartin commited on
Commit
3fe716b
·
1 Parent(s): a9b1e3b

clean up request

Browse files
pytube/request.py CHANGED
@@ -1,39 +1,49 @@
1
  # -*- coding: utf-8 -*-
2
  """Implements a simple wrapper around urlopen."""
 
3
  from urllib.request import Request
4
  from urllib.request import urlopen
5
 
6
 
7
- def get(url, headers=False, streaming=False, chunk_size=8192):
 
 
 
 
8
  """Send an http GET request.
9
 
10
  :param str url:
11
  The URL to perform the GET request for.
12
- :param bool headers:
13
- Only return the http headers.
14
- :param bool streaming:
15
- Returns the response body in chunks via a generator.
16
- :param int chunk_size:
17
- The size in bytes of each chunk. Defaults to 8*1024
18
  """
 
19
 
20
- req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
21
- response = urlopen(req)
22
-
23
- if streaming:
24
- return stream_response(response, chunk_size)
25
 
26
- if headers:
27
- # https://github.com/nficano/pytube/issues/160
28
- return {k.lower(): v for k, v in response.info().items()}
29
-
30
- return response.read().decode("utf-8")
31
-
32
-
33
- def stream_response(response, chunk_size=8 * 1024):
34
- """Read the response in chunks."""
35
  while True:
36
  buf = response.read(chunk_size)
37
  if not buf:
38
  break
39
  yield buf
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # -*- coding: utf-8 -*-
2
  """Implements a simple wrapper around urlopen."""
3
+ from typing import Any, Iterable, Dict
4
  from urllib.request import Request
5
  from urllib.request import urlopen
6
 
7
 
8
+ def _execute_request(url:str) -> Any:
9
+ return urlopen(Request(url, headers={"User-Agent": "Mozilla/5.0"}))
10
+
11
+
12
+ def get(url) -> str:
13
  """Send an http GET request.
14
 
15
  :param str url:
16
  The URL to perform the GET request for.
17
+ :rtype: str
18
+ :returns:
19
+ UTF-8 encoded string of response
 
 
 
20
  """
21
+ return _execute_request(url).read().decode("utf-8")
22
 
 
 
 
 
 
23
 
24
+ def stream(url: str, chunk_size:int = 8192) -> Iterable[bytes]:
25
+ """Read the response in chunks.
26
+ :param str url:
27
+ The URL to perform the GET request for.
28
+ :param int chunk_size:
29
+ The size in bytes of each chunk. Defaults to 8*1024
30
+ :rtype: Iterable[bytes]
31
+ """
32
+ response = _execute_request(url)
33
  while True:
34
  buf = response.read(chunk_size)
35
  if not buf:
36
  break
37
  yield buf
38
+
39
+
40
+ def headers(url: str) -> Dict:
41
+ """Fetch headers returned http GET request.
42
+
43
+ :param str url:
44
+ The URL to perform the GET request for.
45
+ :rtype: dict
46
+ :returns:
47
+ dictionary of lowercase headers
48
+ """
49
+ return {k.lower(): v for k, v in _execute_request(url).info().items()}
pytube/streams.py CHANGED
@@ -160,7 +160,7 @@ class Stream:
160
  Filesize (in bytes) of the stream.
161
  """
162
  if self._filesize is None:
163
- headers = request.get(self.url, headers=True)
164
  self._filesize = int(headers["content-length"])
165
  return self._filesize
166
 
@@ -239,7 +239,7 @@ class Stream:
239
  )
240
 
241
  with open(file_path, "wb") as fh:
242
- for chunk in request.get(self.url, streaming=True):
243
  # reduce the (bytes) remainder by the length of the chunk.
244
  bytes_remaining -= len(chunk)
245
  # send to the on_progress callback.
@@ -258,7 +258,7 @@ class Stream:
258
  "downloading (%s total bytes) file to BytesIO buffer", self.filesize,
259
  )
260
 
261
- for chunk in request.get(self.url, streaming=True):
262
  # reduce the (bytes) remainder by the length of the chunk.
263
  bytes_remaining -= len(chunk)
264
  # send to the on_progress callback.
 
160
  Filesize (in bytes) of the stream.
161
  """
162
  if self._filesize is None:
163
+ headers = request.headers(self.url)
164
  self._filesize = int(headers["content-length"])
165
  return self._filesize
166
 
 
239
  )
240
 
241
  with open(file_path, "wb") as fh:
242
+ for chunk in request.stream(self.url):
243
  # reduce the (bytes) remainder by the length of the chunk.
244
  bytes_remaining -= len(chunk)
245
  # send to the on_progress callback.
 
258
  "downloading (%s total bytes) file to BytesIO buffer", self.filesize,
259
  )
260
 
261
+ for chunk in request.stream(self.url):
262
  # reduce the (bytes) remainder by the length of the chunk.
263
  bytes_remaining -= len(chunk)
264
  # send to the on_progress callback.
tests/test_request.py CHANGED
@@ -7,7 +7,7 @@ from pytube import request
7
 
8
 
9
  @mock.patch("pytube.request.urlopen")
10
- def test_get_streaming(mock_urlopen):
11
  fake_stream_binary = [
12
  iter(os.urandom(8 * 1024)),
13
  iter(os.urandom(8 * 1024)),
@@ -17,18 +17,18 @@ def test_get_streaming(mock_urlopen):
17
  response = mock.Mock()
18
  response.read.side_effect = fake_stream_binary
19
  mock_urlopen.return_value = response
20
- response = request.get("http://fakeassurl.gov", streaming=True)
21
  call_count = len(list(response))
22
 
23
  assert call_count == 3
24
 
25
 
26
  @mock.patch("pytube.request.urlopen")
27
- def test_get_headers(mock_urlopen):
28
  response = mock.Mock()
29
  response.info.return_value = {"content-length": "16384"}
30
  mock_urlopen.return_value = response
31
- response = request.get("http://fakeassurl.gov", headers=True)
32
  assert response == {"content-length": "16384"}
33
 
34
 
 
7
 
8
 
9
  @mock.patch("pytube.request.urlopen")
10
+ def test_streaming(mock_urlopen):
11
  fake_stream_binary = [
12
  iter(os.urandom(8 * 1024)),
13
  iter(os.urandom(8 * 1024)),
 
17
  response = mock.Mock()
18
  response.read.side_effect = fake_stream_binary
19
  mock_urlopen.return_value = response
20
+ response = request.stream("http://fakeassurl.gov")
21
  call_count = len(list(response))
22
 
23
  assert call_count == 3
24
 
25
 
26
  @mock.patch("pytube.request.urlopen")
27
+ def test_headers(mock_urlopen):
28
  response = mock.Mock()
29
  response.info.return_value = {"content-length": "16384"}
30
  mock_urlopen.return_value = response
31
+ response = request.headers("http://fakeassurl.gov")
32
  assert response == {"content-length": "16384"}
33
 
34
 
tests/test_streams.py CHANGED
@@ -8,8 +8,8 @@ from pytube import Stream
8
 
9
 
10
  def test_filesize(cipher_signature, mocker):
11
- mocker.patch.object(request, "get")
12
- request.get.return_value = {"content-length": "6796391"}
13
  assert cipher_signature.streams.first().filesize == 6796391
14
 
15
 
@@ -36,12 +36,10 @@ def test_title(cipher_signature):
36
 
37
 
38
  def test_download(cipher_signature, mocker):
39
- mocker.patch.object(request, "get")
40
- request.get.side_effect = [
41
- {"content-length": "16384"},
42
- {"content-length": "16384"},
43
- iter([str(random.getrandbits(8 * 1024))]),
44
- ]
45
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
46
  stream = cipher_signature.streams.first()
47
  stream.download()
@@ -61,12 +59,11 @@ def test_on_progress_hook(cipher_signature, mocker):
61
  callback_fn = mock.MagicMock()
62
  cipher_signature.register_on_progress_callback(callback_fn)
63
 
64
- mocker.patch.object(request, "get")
65
- request.get.side_effect = [
66
- {"content-length": "16384"},
67
- {"content-length": "16384"},
68
- iter([str(random.getrandbits(8 * 1024))]),
69
- ]
70
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
71
  stream = cipher_signature.streams.first()
72
  stream.download()
@@ -81,12 +78,11 @@ def test_on_complete_hook(cipher_signature, mocker):
81
  callback_fn = mock.MagicMock()
82
  cipher_signature.register_on_complete_callback(callback_fn)
83
 
84
- mocker.patch.object(request, "get")
85
- request.get.side_effect = [
86
- {"content-length": "16384"},
87
- {"content-length": "16384"},
88
- iter([str(random.getrandbits(8 * 1024))]),
89
- ]
90
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
91
  stream = cipher_signature.streams.first()
92
  stream.download()
 
8
 
9
 
10
  def test_filesize(cipher_signature, mocker):
11
+ mocker.patch.object(request, "headers")
12
+ request.headers.return_value = {"content-length": "6796391"}
13
  assert cipher_signature.streams.first().filesize == 6796391
14
 
15
 
 
36
 
37
 
38
  def test_download(cipher_signature, mocker):
39
+ mocker.patch.object(request, "headers")
40
+ request.headers.return_value = {"content-length": "16384"}
41
+ mocker.patch.object(request, "stream")
42
+ request.stream.return_value = iter([str(random.getrandbits(8 * 1024))])
 
 
43
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
44
  stream = cipher_signature.streams.first()
45
  stream.download()
 
59
  callback_fn = mock.MagicMock()
60
  cipher_signature.register_on_progress_callback(callback_fn)
61
 
62
+ mocker.patch.object(request, "headers")
63
+ request.headers.return_value = {"content-length": "16384"}
64
+ mocker.patch.object(request, "stream")
65
+ request.stream.return_value = iter([str(random.getrandbits(8 * 1024))])
66
+
 
67
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
68
  stream = cipher_signature.streams.first()
69
  stream.download()
 
78
  callback_fn = mock.MagicMock()
79
  cipher_signature.register_on_complete_callback(callback_fn)
80
 
81
+ mocker.patch.object(request, "headers")
82
+ request.headers.return_value = {"content-length": "16384"}
83
+ mocker.patch.object(request, "stream")
84
+ request.stream.return_value = iter([str(random.getrandbits(8 * 1024))])
85
+
 
86
  with mock.patch("pytube.streams.open", mock.mock_open(), create=True):
87
  stream = cipher_signature.streams.first()
88
  stream.download()