Merge pull request #56 from hbmartin/logging
Browse files- pytube/__init__.py +0 -4
- pytube/cipher.py +3 -3
- pytube/cli.py +5 -5
- pytube/extract.py +4 -1
- pytube/helpers.py +1 -2
- tests/test_cli.py +15 -0
- tests/test_helpers.py +13 -1
pytube/__init__.py
CHANGED
@@ -10,13 +10,9 @@ __license__ = "MIT License"
|
|
10 |
__copyright__ = "Copyright 2019 Nick Ficano"
|
11 |
|
12 |
from pytube.version import __version__
|
13 |
-
from pytube.helpers import create_logger
|
14 |
from pytube.streams import Stream
|
15 |
from pytube.captions import Caption
|
16 |
from pytube.query import CaptionQuery
|
17 |
from pytube.query import StreamQuery
|
18 |
from pytube.__main__ import YouTube
|
19 |
from pytube.contrib.playlist import Playlist
|
20 |
-
|
21 |
-
logger = create_logger()
|
22 |
-
logger.info("%s v%s", __title__, __version__)
|
|
|
10 |
__copyright__ = "Copyright 2019 Nick Ficano"
|
11 |
|
12 |
from pytube.version import __version__
|
|
|
13 |
from pytube.streams import Stream
|
14 |
from pytube.captions import Caption
|
15 |
from pytube.query import CaptionQuery
|
16 |
from pytube.query import StreamQuery
|
17 |
from pytube.__main__ import YouTube
|
18 |
from pytube.contrib.playlist import Playlist
|
|
|
|
|
|
pytube/cipher.py
CHANGED
@@ -14,15 +14,15 @@ functions" (2) maps them to Python equivalents and (3) taking the ciphered
|
|
14 |
signature and decoding it.
|
15 |
|
16 |
"""
|
17 |
-
|
18 |
import re
|
19 |
from itertools import chain
|
20 |
from typing import List, Tuple, Dict, Callable, Any, Optional
|
21 |
|
22 |
from pytube.exceptions import RegexMatchError
|
23 |
-
from pytube.helpers import regex_search,
|
24 |
|
25 |
-
logger =
|
26 |
|
27 |
|
28 |
class Cipher:
|
|
|
14 |
signature and decoding it.
|
15 |
|
16 |
"""
|
17 |
+
import logging
|
18 |
import re
|
19 |
from itertools import chain
|
20 |
from typing import List, Tuple, Dict, Callable, Any, Optional
|
21 |
|
22 |
from pytube.exceptions import RegexMatchError
|
23 |
+
from pytube.helpers import regex_search, cache
|
24 |
|
25 |
+
logger = logging.getLogger(__name__)
|
26 |
|
27 |
|
28 |
class Cipher:
|
pytube/cli.py
CHANGED
@@ -17,9 +17,7 @@ from typing import Any, Optional, List
|
|
17 |
from pytube import __version__, CaptionQuery, Stream, Playlist
|
18 |
from pytube import YouTube
|
19 |
from pytube.exceptions import PytubeError
|
20 |
-
from pytube.helpers import safe_filename
|
21 |
-
|
22 |
-
logger = logging.getLogger(__name__)
|
23 |
|
24 |
|
25 |
def main():
|
@@ -27,7 +25,9 @@ def main():
|
|
27 |
# noinspection PyTypeChecker
|
28 |
parser = argparse.ArgumentParser(description=main.__doc__)
|
29 |
args = _parse_args(parser)
|
30 |
-
|
|
|
|
|
31 |
|
32 |
if not args.url or "youtu" not in args.url:
|
33 |
parser.print_help()
|
@@ -99,7 +99,7 @@ def _parse_args(
|
|
99 |
action="count",
|
100 |
default=0,
|
101 |
dest="verbosity",
|
102 |
-
help="Verbosity level",
|
103 |
)
|
104 |
parser.add_argument(
|
105 |
"--build-playback-report",
|
|
|
17 |
from pytube import __version__, CaptionQuery, Stream, Playlist
|
18 |
from pytube import YouTube
|
19 |
from pytube.exceptions import PytubeError
|
20 |
+
from pytube.helpers import safe_filename, setup_logger
|
|
|
|
|
21 |
|
22 |
|
23 |
def main():
|
|
|
25 |
# noinspection PyTypeChecker
|
26 |
parser = argparse.ArgumentParser(description=main.__doc__)
|
27 |
args = _parse_args(parser)
|
28 |
+
if args.verbosity:
|
29 |
+
log_level = min(args.verbosity, 4) * 10
|
30 |
+
setup_logger(logging.FATAL - log_level)
|
31 |
|
32 |
if not args.url or "youtu" not in args.url:
|
33 |
parser.print_help()
|
|
|
99 |
action="count",
|
100 |
default=0,
|
101 |
dest="verbosity",
|
102 |
+
help="Verbosity level, use up to 4 to increase logging -vvvv",
|
103 |
)
|
104 |
parser.add_argument(
|
105 |
"--build-playback-report",
|
pytube/extract.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module contains all non-cipher related data extraction logic."""
|
3 |
import json
|
|
|
4 |
import re
|
5 |
from collections import OrderedDict
|
6 |
from html.parser import HTMLParser
|
@@ -10,7 +11,9 @@ from urllib.parse import urlencode
|
|
10 |
|
11 |
from pytube.cipher import Cipher
|
12 |
from pytube.exceptions import RegexMatchError, HTMLParseError, LiveStreamError
|
13 |
-
from pytube.helpers import regex_search
|
|
|
|
|
14 |
|
15 |
|
16 |
class PytubeHTMLParser(HTMLParser):
|
|
|
1 |
# -*- coding: utf-8 -*-
|
2 |
"""This module contains all non-cipher related data extraction logic."""
|
3 |
import json
|
4 |
+
import logging
|
5 |
import re
|
6 |
from collections import OrderedDict
|
7 |
from html.parser import HTMLParser
|
|
|
11 |
|
12 |
from pytube.cipher import Cipher
|
13 |
from pytube.exceptions import RegexMatchError, HTMLParseError, LiveStreamError
|
14 |
+
from pytube.helpers import regex_search
|
15 |
+
|
16 |
+
logger = logging.getLogger(__name__)
|
17 |
|
18 |
|
19 |
class PytubeHTMLParser(HTMLParser):
|
pytube/helpers.py
CHANGED
@@ -86,7 +86,7 @@ def safe_filename(s: str, max_length: int = 255) -> str:
|
|
86 |
return filename[:max_length].rsplit(" ", 0)[0]
|
87 |
|
88 |
|
89 |
-
def
|
90 |
"""Create a configured instance of logger.
|
91 |
|
92 |
:param int level:
|
@@ -103,7 +103,6 @@ def create_logger(level: int = logging.ERROR) -> logging.Logger:
|
|
103 |
logger = logging.getLogger("pytube")
|
104 |
logger.addHandler(handler)
|
105 |
logger.setLevel(level)
|
106 |
-
return logger
|
107 |
|
108 |
|
109 |
GenericType = TypeVar("GenericType")
|
|
|
86 |
return filename[:max_length].rsplit(" ", 0)[0]
|
87 |
|
88 |
|
89 |
+
def setup_logger(level: int = logging.ERROR):
|
90 |
"""Create a configured instance of logger.
|
91 |
|
92 |
:param int level:
|
|
|
103 |
logger = logging.getLogger("pytube")
|
104 |
logger.addHandler(handler)
|
105 |
logger.setLevel(level)
|
|
|
106 |
|
107 |
|
108 |
GenericType = TypeVar("GenericType")
|
tests/test_cli.py
CHANGED
@@ -154,12 +154,27 @@ def test_parse_args_truthy():
|
|
154 |
"en",
|
155 |
"-l",
|
156 |
"--itag=10",
|
|
|
157 |
],
|
158 |
)
|
159 |
assert args.url == "http://youtube.com/watch?v=9bZkp7q19f0"
|
160 |
assert args.build_playback_report is True
|
161 |
assert args.itag == 10
|
162 |
assert args.list is True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
|
165 |
@mock.patch("pytube.cli.YouTube", return_value=None)
|
|
|
154 |
"en",
|
155 |
"-l",
|
156 |
"--itag=10",
|
157 |
+
"-vvv",
|
158 |
],
|
159 |
)
|
160 |
assert args.url == "http://youtube.com/watch?v=9bZkp7q19f0"
|
161 |
assert args.build_playback_report is True
|
162 |
assert args.itag == 10
|
163 |
assert args.list is True
|
164 |
+
assert args.verbosity == 3
|
165 |
+
|
166 |
+
|
167 |
+
@mock.patch("pytube.cli.setup_logger", return_value=None)
|
168 |
+
def test_main_logging_setup(setup_logger):
|
169 |
+
# Given
|
170 |
+
parser = argparse.ArgumentParser()
|
171 |
+
args = parse_args(parser, ["http://fakeurl", "-v"])
|
172 |
+
cli._parse_args = MagicMock(return_value=args)
|
173 |
+
# When
|
174 |
+
with pytest.raises(SystemExit):
|
175 |
+
cli.main()
|
176 |
+
# Then
|
177 |
+
setup_logger.assert_called_with(40)
|
178 |
|
179 |
|
180 |
@mock.patch("pytube.cli.YouTube", return_value=None)
|
tests/test_helpers.py
CHANGED
@@ -5,7 +5,7 @@ import pytest
|
|
5 |
|
6 |
from pytube import helpers
|
7 |
from pytube.exceptions import RegexMatchError
|
8 |
-
from pytube.helpers import deprecated, cache, target_directory
|
9 |
|
10 |
|
11 |
def test_regex_search_no_match():
|
@@ -74,3 +74,15 @@ def test_target_directory_with_absolute_path(_, makedirs):
|
|
74 |
def test_target_directory_with_no_path(_, makedirs):
|
75 |
assert target_directory() == "/cwd"
|
76 |
makedirs.assert_called()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
from pytube import helpers
|
7 |
from pytube.exceptions import RegexMatchError
|
8 |
+
from pytube.helpers import deprecated, cache, target_directory, setup_logger
|
9 |
|
10 |
|
11 |
def test_regex_search_no_match():
|
|
|
74 |
def test_target_directory_with_no_path(_, makedirs):
|
75 |
assert target_directory() == "/cwd"
|
76 |
makedirs.assert_called()
|
77 |
+
|
78 |
+
|
79 |
+
@mock.patch("pytube.helpers.logging")
|
80 |
+
def test_setup_logger(logging):
|
81 |
+
# Given
|
82 |
+
logger = logging.getLogger.return_value
|
83 |
+
# When
|
84 |
+
setup_logger(20)
|
85 |
+
# Then
|
86 |
+
logging.getLogger.assert_called_with("pytube")
|
87 |
+
logger.addHandler.assert_called()
|
88 |
+
logger.setLevel.assert_called_with(20)
|