refactoring of exceptions
Browse files- pytube/__main__.py +2 -1
- pytube/cipher.py +4 -10
- pytube/exceptions.py +28 -16
- pytube/extract.py +1 -3
- pytube/helpers.py +1 -3
- pytube/request.py +2 -6
- tests/test_exceptions.py +3 -3
pytube/__main__.py
CHANGED
@@ -182,7 +182,8 @@ class YouTube(object):
|
|
182 |
or '<img class="icon meh" src="/yts/img' # noqa: W503
|
183 |
not in self.watch_html # noqa: W503
|
184 |
):
|
185 |
-
raise VideoUnavailable(
|
|
|
186 |
self.embed_html = request.get(url=self.embed_url)
|
187 |
self.age_restricted = extract.is_age_restricted(self.watch_html)
|
188 |
self.vid_info_url = extract.video_info_url(
|
|
|
182 |
or '<img class="icon meh" src="/yts/img' # noqa: W503
|
183 |
not in self.watch_html # noqa: W503
|
184 |
):
|
185 |
+
raise VideoUnavailable(video_id=self.video_id)
|
186 |
+
|
187 |
self.embed_html = request.get(url=self.embed_url)
|
188 |
self.age_restricted = extract.is_age_restricted(self.watch_html)
|
189 |
self.vid_info_url = extract.video_info_url(
|
pytube/cipher.py
CHANGED
@@ -56,7 +56,7 @@ def get_initial_function_name(js: str) -> str:
|
|
56 |
logger.debug("finished regex search, matched: {pattern}".format(pattern=p))
|
57 |
return results.group(1)
|
58 |
|
59 |
-
raise RegexMatchError("get_initial_function_name
|
60 |
|
61 |
|
62 |
def get_transform_plan(js: str) -> List[str]:
|
@@ -113,9 +113,7 @@ def get_transform_object(js: str, var: str) -> List[str]:
|
|
113 |
regex = re.compile(pattern, flags=re.DOTALL)
|
114 |
results = regex.search(js)
|
115 |
if not results:
|
116 |
-
raise RegexMatchError(
|
117 |
-
"regex pattern ({pattern}) had zero matches".format(pattern=pattern),
|
118 |
-
)
|
119 |
|
120 |
return results.group(1).replace("\n", " ").split(", ")
|
121 |
|
@@ -222,9 +220,7 @@ def map_functions(js_func: str) -> Callable:
|
|
222 |
for pattern, fn in mapper:
|
223 |
if re.search(pattern, js_func):
|
224 |
return fn
|
225 |
-
raise RegexMatchError(
|
226 |
-
"could not find python equivalent function for: ", js_func,
|
227 |
-
)
|
228 |
|
229 |
|
230 |
def parse_function(js_func: str) -> Tuple[str, int]:
|
@@ -250,9 +246,7 @@ def parse_function(js_func: str) -> Tuple[str, int]:
|
|
250 |
regex = re.compile(pattern)
|
251 |
results = regex.search(js_func)
|
252 |
if not results:
|
253 |
-
raise RegexMatchError(
|
254 |
-
"regex pattern ({pattern}) had zero matches".format(pattern=pattern),
|
255 |
-
)
|
256 |
fn_name, fn_arg = results.groups()
|
257 |
return fn_name, int(fn_arg)
|
258 |
|
|
|
56 |
logger.debug("finished regex search, matched: {pattern}".format(pattern=p))
|
57 |
return results.group(1)
|
58 |
|
59 |
+
raise RegexMatchError(caller="get_initial_function_name", pattern="multiple")
|
60 |
|
61 |
|
62 |
def get_transform_plan(js: str) -> List[str]:
|
|
|
113 |
regex = re.compile(pattern, flags=re.DOTALL)
|
114 |
results = regex.search(js)
|
115 |
if not results:
|
116 |
+
raise RegexMatchError(caller="get_transform_object", pattern=pattern)
|
|
|
|
|
117 |
|
118 |
return results.group(1).replace("\n", " ").split(", ")
|
119 |
|
|
|
220 |
for pattern, fn in mapper:
|
221 |
if re.search(pattern, js_func):
|
222 |
return fn
|
223 |
+
raise RegexMatchError(caller="map_functions", pattern="multiple")
|
|
|
|
|
224 |
|
225 |
|
226 |
def parse_function(js_func: str) -> Tuple[str, int]:
|
|
|
246 |
regex = re.compile(pattern)
|
247 |
results = regex.search(js_func)
|
248 |
if not results:
|
249 |
+
raise RegexMatchError(caller="parse_function", pattern=pattern)
|
|
|
|
|
250 |
fn_name, fn_arg = results.groups()
|
251 |
return fn_name, int(fn_arg)
|
252 |
|
pytube/exceptions.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""Library specific exception definitions."""
|
3 |
import sys
|
|
|
4 |
|
5 |
|
6 |
class PytubeError(Exception):
|
@@ -15,26 +16,25 @@ class PytubeError(Exception):
|
|
15 |
class ExtractError(PytubeError):
|
16 |
"""Data extraction based exception."""
|
17 |
|
18 |
-
def __init__(self, msg: str, video_id: str = "unknown id"):
|
19 |
-
"""Construct an instance of a :class:`ExtractError <ExtractError>`.
|
20 |
-
|
21 |
-
:param str msg:
|
22 |
-
User defined error message.
|
23 |
-
:param str video_id:
|
24 |
-
A YouTube video identifier.
|
25 |
-
"""
|
26 |
-
if video_id is not None:
|
27 |
-
msg = "{video_id}: {msg}".format(video_id=video_id, msg=msg)
|
28 |
-
|
29 |
-
super(ExtractError, self).__init__(msg)
|
30 |
-
|
31 |
-
self.exc_info = sys.exc_info()
|
32 |
-
self.video_id = video_id
|
33 |
-
|
34 |
|
35 |
class RegexMatchError(ExtractError):
|
36 |
"""Regex pattern did not return any matches."""
|
37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
|
39 |
class LiveStreamError(ExtractError):
|
40 |
"""Video is a live stream."""
|
@@ -43,6 +43,18 @@ class LiveStreamError(ExtractError):
|
|
43 |
class VideoUnavailable(PytubeError):
|
44 |
"""Video is unavailable."""
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
class HTMLParseError(PytubeError):
|
48 |
"""HTML could not be parsed"""
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""Library specific exception definitions."""
|
3 |
import sys
|
4 |
+
from typing import Union, Pattern
|
5 |
|
6 |
|
7 |
class PytubeError(Exception):
|
|
|
16 |
class ExtractError(PytubeError):
|
17 |
"""Data extraction based exception."""
|
18 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
class RegexMatchError(ExtractError):
|
21 |
"""Regex pattern did not return any matches."""
|
22 |
|
23 |
+
def __init__(self, caller: str, pattern: Union[str, Pattern]):
|
24 |
+
"""
|
25 |
+
:param str caller:
|
26 |
+
Calling function
|
27 |
+
:param str pattern:
|
28 |
+
Pattern that failed to match
|
29 |
+
"""
|
30 |
+
super(ExtractError, self).__init__(
|
31 |
+
"{caller}: could not find match for {pattern}".format(
|
32 |
+
caller=caller, pattern=pattern
|
33 |
+
)
|
34 |
+
)
|
35 |
+
self.caller = caller
|
36 |
+
self.pattern = pattern
|
37 |
+
|
38 |
|
39 |
class LiveStreamError(ExtractError):
|
40 |
"""Video is a live stream."""
|
|
|
43 |
class VideoUnavailable(PytubeError):
|
44 |
"""Video is unavailable."""
|
45 |
|
46 |
+
def __init__(self, video_id: str):
|
47 |
+
"""
|
48 |
+
:param str video_id:
|
49 |
+
A YouTube video identifier.
|
50 |
+
"""
|
51 |
+
super(PytubeError, self).__init__(
|
52 |
+
"{video_id} is unavailable".format(video_id=video_id)
|
53 |
+
)
|
54 |
+
|
55 |
+
self.exc_info = sys.exc_info()
|
56 |
+
self.video_id = video_id
|
57 |
+
|
58 |
|
59 |
class HTMLParseError(PytubeError):
|
60 |
"""HTML could not be parsed"""
|
pytube/extract.py
CHANGED
@@ -174,9 +174,7 @@ def mime_type_codec(mime_type_codec: str) -> Tuple[str, List[str]]:
|
|
174 |
regex = re.compile(pattern)
|
175 |
results = regex.search(mime_type_codec)
|
176 |
if not results:
|
177 |
-
raise RegexMatchError(
|
178 |
-
"regex pattern ({pattern}) had zero matches".format(pattern=pattern),
|
179 |
-
)
|
180 |
mime_type, codecs = results.groups()
|
181 |
return mime_type, [c.strip() for c in codecs.split(",")]
|
182 |
|
|
|
174 |
regex = re.compile(pattern)
|
175 |
results = regex.search(mime_type_codec)
|
176 |
if not results:
|
177 |
+
raise RegexMatchError(caller="mime_type_codec", pattern=pattern)
|
|
|
|
|
178 |
mime_type, codecs = results.groups()
|
179 |
return mime_type, [c.strip() for c in codecs.split(",")]
|
180 |
|
pytube/helpers.py
CHANGED
@@ -27,9 +27,7 @@ def regex_search(pattern: str, string: str, group: int) -> str:
|
|
27 |
regex = re.compile(pattern)
|
28 |
results = regex.search(string)
|
29 |
if not results:
|
30 |
-
raise RegexMatchError(
|
31 |
-
"regex pattern ({pattern}) had zero matches".format(pattern=pattern),
|
32 |
-
)
|
33 |
|
34 |
logger.debug(
|
35 |
"finished regex search: %s",
|
|
|
27 |
regex = re.compile(pattern)
|
28 |
results = regex.search(string)
|
29 |
if not results:
|
30 |
+
raise RegexMatchError(caller="regex_search", pattern=pattern)
|
|
|
|
|
31 |
|
32 |
logger.debug(
|
33 |
"finished regex search: %s",
|
pytube/request.py
CHANGED
@@ -3,12 +3,8 @@
|
|
3 |
from urllib.request import Request
|
4 |
from urllib.request import urlopen
|
5 |
|
6 |
-
# 403 forbidden fix
|
7 |
|
8 |
-
|
9 |
-
def get(
|
10 |
-
url=None, headers=False, streaming=False, chunk_size=8 * 1024,
|
11 |
-
):
|
12 |
"""Send an http GET request.
|
13 |
|
14 |
:param str url:
|
@@ -18,7 +14,7 @@ def get(
|
|
18 |
:param bool streaming:
|
19 |
Returns the response body in chunks via a generator.
|
20 |
:param int chunk_size:
|
21 |
-
The size in bytes of each chunk.
|
22 |
"""
|
23 |
|
24 |
# https://github.com/nficano/pytube/pull/465
|
|
|
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:
|
|
|
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 |
# https://github.com/nficano/pytube/pull/465
|
tests/test_exceptions.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
-
from pytube.exceptions import
|
3 |
|
4 |
|
5 |
def test_is_expected():
|
6 |
try:
|
7 |
-
raise
|
8 |
-
except
|
9 |
assert e.video_id == "YLnZklYFe7E"
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
+
from pytube.exceptions import VideoUnavailable
|
3 |
|
4 |
|
5 |
def test_is_expected():
|
6 |
try:
|
7 |
+
raise VideoUnavailable("ppfff", video_id="YLnZklYFe7E")
|
8 |
+
except VideoUnavailable as e:
|
9 |
assert e.video_id == "YLnZklYFe7E"
|