updated README, added test_deprecated
Browse files- README.md +6 -6
- pytube/helpers.py +3 -7
- pytube/query.py +16 -0
README.md
CHANGED
|
@@ -138,17 +138,17 @@ Conversely, if you only want to see the DASH streams (also referred to as "adapt
|
|
| 138 |
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus">]
|
| 139 |
```
|
| 140 |
|
|
|
|
|
|
|
| 141 |
You can also download a complete Youtube playlist:
|
| 142 |
|
| 143 |
```python
|
| 144 |
>>> from pytube import Playlist
|
| 145 |
-
>>>
|
| 146 |
-
>>>
|
| 147 |
-
>>>
|
| 148 |
-
>>> pl.download_all('/path/to/directory/')
|
| 149 |
```
|
| 150 |
-
This will download the highest progressive stream available (generally 720p) from the given playlist.
|
| 151 |
-
to choose video resolution.
|
| 152 |
|
| 153 |
### Filtering
|
| 154 |
|
|
|
|
| 138 |
<Stream: itag="251" mime_type="audio/webm" abr="160kbps" acodec="opus">]
|
| 139 |
```
|
| 140 |
|
| 141 |
+
### Playlists
|
| 142 |
+
|
| 143 |
You can also download a complete Youtube playlist:
|
| 144 |
|
| 145 |
```python
|
| 146 |
>>> from pytube import Playlist
|
| 147 |
+
>>> playlist = Playlist("https://www.youtube.com/playlist?list=PLynhp4cZEpTbRs_PYISQ8v_uwO0_mDg_X")
|
| 148 |
+
>>> for video in playlist.videos:
|
| 149 |
+
>>> video.streams.get_highest_resolution().download()
|
|
|
|
| 150 |
```
|
| 151 |
+
This will download the highest progressive stream available (generally 720p) from the given playlist.
|
|
|
|
| 152 |
|
| 153 |
### Filtering
|
| 154 |
|
pytube/helpers.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
"""Various helper functions implemented by pytube."""
|
| 3 |
import functools
|
| 4 |
-
import inspect
|
| 5 |
import logging
|
| 6 |
import pprint
|
| 7 |
import re
|
|
@@ -112,7 +111,7 @@ def cache(func: Callable[..., GenericType]) -> GenericType:
|
|
| 112 |
return functools.lru_cache()(func) # type: ignore
|
| 113 |
|
| 114 |
|
| 115 |
-
def deprecated(reason):
|
| 116 |
"""
|
| 117 |
This is a decorator which can be used to mark functions
|
| 118 |
as deprecated. It will result in a warning being emitted
|
|
@@ -120,16 +119,13 @@ def deprecated(reason):
|
|
| 120 |
"""
|
| 121 |
|
| 122 |
def decorator(func1):
|
| 123 |
-
|
| 124 |
-
fmt1 = "Call to deprecated class {name} ({reason})."
|
| 125 |
-
else:
|
| 126 |
-
fmt1 = "Call to deprecated function {name} ({reason})."
|
| 127 |
|
| 128 |
@functools.wraps(func1)
|
| 129 |
def new_func1(*args, **kwargs):
|
| 130 |
warnings.simplefilter("always", DeprecationWarning)
|
| 131 |
warnings.warn(
|
| 132 |
-
|
| 133 |
category=DeprecationWarning,
|
| 134 |
stacklevel=2,
|
| 135 |
)
|
|
|
|
| 1 |
# -*- coding: utf-8 -*-
|
| 2 |
"""Various helper functions implemented by pytube."""
|
| 3 |
import functools
|
|
|
|
| 4 |
import logging
|
| 5 |
import pprint
|
| 6 |
import re
|
|
|
|
| 111 |
return functools.lru_cache()(func) # type: ignore
|
| 112 |
|
| 113 |
|
| 114 |
+
def deprecated(reason: str) -> Callable:
|
| 115 |
"""
|
| 116 |
This is a decorator which can be used to mark functions
|
| 117 |
as deprecated. It will result in a warning being emitted
|
|
|
|
| 119 |
"""
|
| 120 |
|
| 121 |
def decorator(func1):
|
| 122 |
+
message = "Call to deprecated function {name} ({reason})."
|
|
|
|
|
|
|
|
|
|
| 123 |
|
| 124 |
@functools.wraps(func1)
|
| 125 |
def new_func1(*args, **kwargs):
|
| 126 |
warnings.simplefilter("always", DeprecationWarning)
|
| 127 |
warnings.warn(
|
| 128 |
+
message.format(name=func1.__name__, reason=reason),
|
| 129 |
category=DeprecationWarning,
|
| 130 |
stacklevel=2,
|
| 131 |
)
|
pytube/query.py
CHANGED
|
@@ -273,6 +273,22 @@ class StreamQuery:
|
|
| 273 |
.last()
|
| 274 |
)
|
| 275 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 276 |
def first(self) -> Optional[Stream]:
|
| 277 |
"""Get the first :class:`Stream <Stream>` in the results.
|
| 278 |
|
|
|
|
| 273 |
.last()
|
| 274 |
)
|
| 275 |
|
| 276 |
+
def get_highest_resolution(self) -> Optional[Stream]:
|
| 277 |
+
"""Get highest resolution stream that is a progressive video.
|
| 278 |
+
|
| 279 |
+
:rtype: :class:`Stream <Stream>` or None
|
| 280 |
+
:returns:
|
| 281 |
+
The :class:`Stream <Stream>` matching the given itag or None if
|
| 282 |
+
not found.
|
| 283 |
+
|
| 284 |
+
"""
|
| 285 |
+
return (
|
| 286 |
+
self.filter(progressive=True)
|
| 287 |
+
.order_by("resolution")
|
| 288 |
+
.asc()
|
| 289 |
+
.last()
|
| 290 |
+
)
|
| 291 |
+
|
| 292 |
def first(self) -> Optional[Stream]:
|
| 293 |
"""Get the first :class:`Stream <Stream>` in the results.
|
| 294 |
|