nficano commited on
Commit
cf2a402
·
unverified ·
2 Parent(s): 0457529 3409e8b

Merge branch 'master' into playlist_exception

Browse files
Files changed (14) hide show
  1. .gitignore +2 -1
  2. LICENSE +1 -1
  3. Makefile +1 -0
  4. Pipfile +3 -0
  5. Pipfile.lock +226 -25
  6. README.md +2 -1
  7. docs/conf.py +1 -1
  8. pytube/__init__.py +2 -2
  9. pytube/captions.py +1 -1
  10. pytube/contrib/playlist.py +35 -0
  11. pytube/query.py +5 -3
  12. pytube/streams.py +1 -1
  13. setup.cfg +1 -1
  14. setup.py +50 -11
.gitignore CHANGED
@@ -39,8 +39,9 @@ _build
39
  _static
40
  _templates
41
  _autosummary
42
-
43
  .pytest_cache*
44
 
45
  # IDE Files
46
  .idea/
 
 
 
39
  _static
40
  _templates
41
  _autosummary
 
42
  .pytest_cache*
43
 
44
  # IDE Files
45
  .idea/
46
+ #Pycharm stuff
47
+ .idea/*
LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2017 Nick Ficano
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
  this software and associated documentation files (the "Software"), to deal in
 
1
+ Copyright (c) 2018 Nick Ficano
2
 
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of
4
  this software and associated documentation files (the "Software"), to deal in
Makefile CHANGED
@@ -25,6 +25,7 @@ clean-pyc:
25
  find . -name '*.pyo' -exec rm -f {} +
26
  find . -name '*~' -exec rm -f {} +
27
  find . -name '__pycache__' -exec rm -fr {} +
 
28
 
29
  install: clean
30
  python setup.py install
 
25
  find . -name '*.pyo' -exec rm -f {} +
26
  find . -name '*~' -exec rm -f {} +
27
  find . -name '__pycache__' -exec rm -fr {} +
28
+ find . -name '.pytest_cache' -exec rm -fr {} +
29
 
30
  install: clean
31
  python setup.py install
Pipfile CHANGED
@@ -15,6 +15,9 @@ pre-commit = "*"
15
  pytest-cov = "*"
16
  "pathlib2" = "*"
17
  "scandir" = "*"
 
 
 
18
 
19
  [requires]
20
  python_version = "3.6"
 
15
  pytest-cov = "*"
16
  "pathlib2" = "*"
17
  "scandir" = "*"
18
+ bumpversion = "*"
19
+ coveralls = "*"
20
+ twine = "*"
21
 
22
  [requires]
23
  python_version = "3.6"
Pipfile.lock CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "_meta": {
3
  "hash": {
4
- "sha256": "dd358c9af1cbfcb78426520303170fc47ec55723b59a730a5234ddf2395b8910"
5
  },
6
  "pipfile-spec": 6,
7
  "requires": {
@@ -29,7 +29,6 @@
29
  "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0",
30
  "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"
31
  ],
32
- "markers": "python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.2.*' and python_version != '3.3.*'",
33
  "version": "==1.2.1"
34
  },
35
  "attrs": {
@@ -39,6 +38,21 @@
39
  ],
40
  "version": "==18.2.0"
41
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  "cached-property": {
43
  "hashes": [
44
  "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f",
@@ -46,6 +60,50 @@
46
  ],
47
  "version": "==1.5.1"
48
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  "cfgv": {
50
  "hashes": [
51
  "sha256:73f48a752bd7aab103c4b882d6596c6360b7aa63b34073dd2c35c7b4b8f93010",
@@ -53,6 +111,46 @@
53
  ],
54
  "version": "==1.1.0"
55
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  "coverage": {
57
  "hashes": [
58
  "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba",
@@ -89,6 +187,28 @@
89
  ],
90
  "version": "==4.5.1"
91
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  "enum34": {
93
  "hashes": [
94
  "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
@@ -107,12 +227,25 @@
107
  "index": "pypi",
108
  "version": "==3.5.0"
109
  },
 
 
 
 
 
 
110
  "identify": {
111
  "hashes": [
112
- "sha256:6aa415d0ce7cb358dfa38844338057067533ffe4973b1c9bc33c5e8e4e54ec92",
113
- "sha256:ac6ae37088cb87da931fc681d1e13da46bf2e06c344dc1d49b18b2f6cd5aa140"
114
  ],
115
- "version": "==1.1.5"
 
 
 
 
 
 
 
116
  },
117
  "mccabe": {
118
  "hashes": [
@@ -153,34 +286,39 @@
153
  },
154
  "pbr": {
155
  "hashes": [
156
- "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45",
157
- "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa"
158
  ],
159
- "version": "==4.2.0"
 
 
 
 
 
 
 
160
  },
161
  "pluggy": {
162
  "hashes": [
163
- "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1",
164
- "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1"
165
  ],
166
- "markers": "python_version >= '2.7' and python_version != '3.3.*' and python_version != '3.0.*' and python_version != '3.2.*' and python_version != '3.1.*'",
167
- "version": "==0.7.1"
168
  },
169
  "pre-commit": {
170
  "hashes": [
171
- "sha256:18ef2892ff6b6518945bc7dcf423e3c969033a4ca132b6a1ae0d52eb2e51ea27",
172
- "sha256:88d59872610a7069d937b6868632ba534187bda58c4665de12b25c8c549ddd0e"
173
  ],
174
  "index": "pypi",
175
- "version": "==1.11.0"
176
  },
177
  "py": {
178
  "hashes": [
179
- "sha256:06a30435d058473046be836d3fc4f27167fd84c45b99704f2fb5509ef61f9af1",
180
- "sha256:50402e9d1c9005d759426988a492e0edaadb7f4e68bcddfea586bc7432d009c6"
181
  ],
182
- "markers": "python_version != '3.3.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.1.*' and python_version != '3.2.*'",
183
- "version": "==1.6.0"
184
  },
185
  "pycodestyle": {
186
  "hashes": [
@@ -189,6 +327,12 @@
189
  ],
190
  "version": "==2.3.1"
191
  },
 
 
 
 
 
 
192
  "pyflakes": {
193
  "hashes": [
194
  "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f",
@@ -196,13 +340,20 @@
196
  ],
197
  "version": "==1.6.0"
198
  },
 
 
 
 
 
 
 
199
  "pytest": {
200
  "hashes": [
201
- "sha256:453cbbbe5ce6db38717d282b758b917de84802af4288910c12442984bde7b823",
202
- "sha256:a8a07f84e680482eb51e244370aaf2caa6301ef265f37c2bdefb3dd3b663f99d"
203
  ],
204
  "index": "pypi",
205
- "version": "==3.8.0"
206
  },
207
  "pytest-cov": {
208
  "hashes": [
@@ -236,6 +387,27 @@
236
  ],
237
  "version": "==3.13"
238
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
239
  "scandir": {
240
  "hashes": [
241
  "sha256:04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6",
@@ -262,10 +434,32 @@
262
  },
263
  "toml": {
264
  "hashes": [
265
- "sha256:380178cde50a6a79f9d2cf6f42a62a5174febe5eea4126fe4038785f1d888d42",
266
- "sha256:a7901919d3e4f92ffba7ff40a9d697e35bbbc8a8049fe8da742f34c83606d957"
267
  ],
268
- "version": "==0.9.6"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  },
270
  "virtualenv": {
271
  "hashes": [
@@ -273,6 +467,13 @@
273
  "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752"
274
  ],
275
  "version": "==16.0.0"
 
 
 
 
 
 
 
276
  }
277
  }
278
  }
 
1
  {
2
  "_meta": {
3
  "hash": {
4
+ "sha256": "7b66cc55f724f5fad32bf12e902f3505f261760bf5a32fa26b7961002594b3dc"
5
  },
6
  "pipfile-spec": 6,
7
  "requires": {
 
29
  "sha256:0312ad34fcad8fac3704d441f7b317e50af620823353ec657a53e981f92920c0",
30
  "sha256:ec9ae8adaae229e4f8446952d204a3e4b5fdd2d099f9be3aaf556120135fb3ee"
31
  ],
 
32
  "version": "==1.2.1"
33
  },
34
  "attrs": {
 
38
  ],
39
  "version": "==18.2.0"
40
  },
41
+ "bleach": {
42
+ "hashes": [
43
+ "sha256:48d39675b80a75f6d1c3bdbffec791cf0bbbab665cf01e20da701c77de278718",
44
+ "sha256:73d26f018af5d5adcdabf5c1c974add4361a9c76af215fe32fdec8a6fc5fb9b9"
45
+ ],
46
+ "version": "==3.0.2"
47
+ },
48
+ "bumpversion": {
49
+ "hashes": [
50
+ "sha256:6744c873dd7aafc24453d8b6a1a0d6d109faf63cd0cd19cb78fd46e74932c77e",
51
+ "sha256:6753d9ff3552013e2130f7bc03c1007e24473b4835952679653fb132367bdd57"
52
+ ],
53
+ "index": "pypi",
54
+ "version": "==0.5.3"
55
+ },
56
  "cached-property": {
57
  "hashes": [
58
  "sha256:3a026f1a54135677e7da5ce819b0c690f156f37976f3e30c5430740725203d7f",
 
60
  ],
61
  "version": "==1.5.1"
62
  },
63
+ "certifi": {
64
+ "hashes": [
65
+ "sha256:339dc09518b07e2fa7eda5450740925974815557727d6bd35d319c1524a04a4c",
66
+ "sha256:6d58c986d22b038c8c0df30d639f23a3e6d172a05c3583e766f4c0b785c0986a"
67
+ ],
68
+ "version": "==2018.10.15"
69
+ },
70
+ "cffi": {
71
+ "hashes": [
72
+ "sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743",
73
+ "sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef",
74
+ "sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50",
75
+ "sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f",
76
+ "sha256:3bb6bd7266598f318063e584378b8e27c67de998a43362e8fce664c54ee52d30",
77
+ "sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93",
78
+ "sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257",
79
+ "sha256:495c5c2d43bf6cebe0178eb3e88f9c4aa48d8934aa6e3cddb865c058da76756b",
80
+ "sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3",
81
+ "sha256:57b2533356cb2d8fac1555815929f7f5f14d68ac77b085d2326b571310f34f6e",
82
+ "sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc",
83
+ "sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04",
84
+ "sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6",
85
+ "sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359",
86
+ "sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596",
87
+ "sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b",
88
+ "sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd",
89
+ "sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95",
90
+ "sha256:a6a5cb8809091ec9ac03edde9304b3ad82ad4466333432b16d78ef40e0cce0d5",
91
+ "sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e",
92
+ "sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6",
93
+ "sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca",
94
+ "sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31",
95
+ "sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1",
96
+ "sha256:ca1bd81f40adc59011f58159e4aa6445fc585a32bb8ac9badf7a2c1aa23822f2",
97
+ "sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085",
98
+ "sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801",
99
+ "sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4",
100
+ "sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184",
101
+ "sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917",
102
+ "sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f",
103
+ "sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb"
104
+ ],
105
+ "version": "==1.11.5"
106
+ },
107
  "cfgv": {
108
  "hashes": [
109
  "sha256:73f48a752bd7aab103c4b882d6596c6360b7aa63b34073dd2c35c7b4b8f93010",
 
111
  ],
112
  "version": "==1.1.0"
113
  },
114
+ "chardet": {
115
+ "hashes": [
116
+ "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
117
+ "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
118
+ ],
119
+ "version": "==3.0.4"
120
+ },
121
+ "cmarkgfm": {
122
+ "hashes": [
123
+ "sha256:0186dccca79483e3405217993b83b914ba4559fe9a8396efc4eea56561b74061",
124
+ "sha256:1a625afc6f62da428df96ec325dc30866cc5781520cbd904ff4ec44cf018171c",
125
+ "sha256:207b7673ff4e177374c572feeae0e4ef33be620ec9171c08fd22e2b796e03e3d",
126
+ "sha256:275905bb371a99285c74931700db3f0c078e7603bed383e8cf1a09f3ee05a3de",
127
+ "sha256:50098f1c4950722521f0671e54139e0edc1837d63c990cf0f3d2c49607bb51a2",
128
+ "sha256:50ed116d0b60a07df0dc7b180c28569064b9d37d1578d4c9021cff04d725cb63",
129
+ "sha256:61a72def110eed903cd1848245897bcb80d295cd9d13944d4f9f30cba5b76655",
130
+ "sha256:64186fb75d973a06df0e6ea12879533b71f6e7ba1ab01ffee7fc3e7534758889",
131
+ "sha256:665303d34d7f14f10d7b0651082f25ebf7107f29ef3d699490cac16cdc0fc8ce",
132
+ "sha256:70b18f843aec58e4e64aadce48a897fe7c50426718b7753aaee399e72df64190",
133
+ "sha256:761ee7b04d1caee2931344ac6bfebf37102ffb203b136b676b0a71a3f0ea3c87",
134
+ "sha256:811527e9b7280b136734ed6cb6845e5fbccaeaa132ddf45f0246cbe544016957",
135
+ "sha256:987b0e157f70c72a84f3c2f9ef2d7ab0f26c08f2bf326c12c087ff9eebcb3ff5",
136
+ "sha256:9fc6a2183d0a9b0974ec7cdcdad42bd78a3be674cc3e65f87dd694419b3b0ab7",
137
+ "sha256:a3d17ee4ae739fe16f7501a52255c2e287ac817cfd88565b9859f70520afffea",
138
+ "sha256:ba5b5488719c0f2ced0aa1986376f7baff1a1653a8eb5fdfcf3f84c7ce46ef8d",
139
+ "sha256:c573ea89dd95d41b6d8cf36799c34b6d5b1eac4aed0212dee0f0a11fb7b01e8f",
140
+ "sha256:c5f1b9e8592d2c448c44e6bc0d91224b16ea5f8293908b1561de1f6d2d0658b1",
141
+ "sha256:cbe581456357d8f0674d6a590b1aaf46c11d01dd0a23af147a51a798c3818034",
142
+ "sha256:cf219bec69e601fe27e3974b7307d2f06082ab385d42752738ad2eb630a47d65",
143
+ "sha256:cf5014eb214d814a83a7a47407272d5db10b719dbeaf4d3cfe5969309d0fcf4b",
144
+ "sha256:d08bad67fa18f7e8ff738c090628ee0cbf0505d74a991c848d6d04abfe67b697",
145
+ "sha256:d6f716d7b1182bf35862b5065112f933f43dd1aa4f8097c9bcfb246f71528a34",
146
+ "sha256:e08e479102627641c7cb4ece421c6ed4124820b1758765db32201136762282d9",
147
+ "sha256:e20ac21418af0298437d29599f7851915497ce9f2866bc8e86b084d8911ee061",
148
+ "sha256:e25f53c37e319241b9a412382140dffac98ca756ba8f360ac7ab5e30cad9670a",
149
+ "sha256:e8932bddf159064f04e946fbb64693753488de21586f20e840b3be51745c8c09",
150
+ "sha256:f20900f16377f2109783ae9348d34bc80530808439591c3d3df73d5c7ef1a00c"
151
+ ],
152
+ "version": "==0.4.2"
153
+ },
154
  "coverage": {
155
  "hashes": [
156
  "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba",
 
187
  ],
188
  "version": "==4.5.1"
189
  },
190
+ "coveralls": {
191
+ "hashes": [
192
+ "sha256:ab638e88d38916a6cedbf80a9cd8992d5fa55c77ab755e262e00b36792b7cd6d",
193
+ "sha256:b2388747e2529fa4c669fb1e3e2756e4e07b6ee56c7d9fce05f35ccccc913aa0"
194
+ ],
195
+ "index": "pypi",
196
+ "version": "==1.5.1"
197
+ },
198
+ "docopt": {
199
+ "hashes": [
200
+ "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491"
201
+ ],
202
+ "version": "==0.6.2"
203
+ },
204
+ "docutils": {
205
+ "hashes": [
206
+ "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
207
+ "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
208
+ "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
209
+ ],
210
+ "version": "==0.14"
211
+ },
212
  "enum34": {
213
  "hashes": [
214
  "sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850",
 
227
  "index": "pypi",
228
  "version": "==3.5.0"
229
  },
230
+ "future": {
231
+ "hashes": [
232
+ "sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb"
233
+ ],
234
+ "version": "==0.16.0"
235
+ },
236
  "identify": {
237
  "hashes": [
238
+ "sha256:5e956558a9a1e3b3891d7c6609fc9709657a11878af288ace484d1a46a93922b",
239
+ "sha256:623086059219cc7b86c77a3891f3700cb175d4ce02b8fb8802b047301d71e783"
240
  ],
241
+ "version": "==1.1.7"
242
+ },
243
+ "idna": {
244
+ "hashes": [
245
+ "sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
246
+ "sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
247
+ ],
248
+ "version": "==2.7"
249
  },
250
  "mccabe": {
251
  "hashes": [
 
286
  },
287
  "pbr": {
288
  "hashes": [
289
+ "sha256:ab94783019179bf48f5784edc63f5bc8328ec5ff93f33591567f266d21ac7323",
290
+ "sha256:bfcff1a3878eebf559392c2130a17f612a03f96a0d44c3559d9c1e62a4235a2d"
291
  ],
292
+ "version": "==5.0.0"
293
+ },
294
+ "pkginfo": {
295
+ "hashes": [
296
+ "sha256:5878d542a4b3f237e359926384f1dde4e099c9f5525d236b1840cf704fa8d474",
297
+ "sha256:a39076cb3eb34c333a0dd390b568e9e1e881c7bf2cc0aee12120636816f55aee"
298
+ ],
299
+ "version": "==1.4.2"
300
  },
301
  "pluggy": {
302
  "hashes": [
303
+ "sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095",
304
+ "sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f"
305
  ],
306
+ "version": "==0.8.0"
 
307
  },
308
  "pre-commit": {
309
  "hashes": [
310
+ "sha256:98ec318db1f255e3d5089ae416959ef3c775215a3509620027d446eeabbba740",
311
+ "sha256:b68f9219c56b50ebafb57f378c5325f9876d06fb29e9cd05daf5cbd6676ce8f2"
312
  ],
313
  "index": "pypi",
314
+ "version": "==1.11.2"
315
  },
316
  "py": {
317
  "hashes": [
318
+ "sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694",
319
+ "sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6"
320
  ],
321
+ "version": "==1.7.0"
 
322
  },
323
  "pycodestyle": {
324
  "hashes": [
 
327
  ],
328
  "version": "==2.3.1"
329
  },
330
+ "pycparser": {
331
+ "hashes": [
332
+ "sha256:a988718abfad80b6b157acce7bf130a30876d27603738ac39f140993246b25b3"
333
+ ],
334
+ "version": "==2.19"
335
+ },
336
  "pyflakes": {
337
  "hashes": [
338
  "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f",
 
340
  ],
341
  "version": "==1.6.0"
342
  },
343
+ "pygments": {
344
+ "hashes": [
345
+ "sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
346
+ "sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
347
+ ],
348
+ "version": "==2.2.0"
349
+ },
350
  "pytest": {
351
  "hashes": [
352
+ "sha256:10e59f84267370ab20cec9305bafe7505ba4d6b93ecbf66a1cce86193ed511d5",
353
+ "sha256:8c827e7d4816dfe13e9329c8226aef8e6e75d65b939bc74fda894143b6d1df59"
354
  ],
355
  "index": "pypi",
356
+ "version": "==3.9.1"
357
  },
358
  "pytest-cov": {
359
  "hashes": [
 
387
  ],
388
  "version": "==3.13"
389
  },
390
+ "readme-renderer": {
391
+ "hashes": [
392
+ "sha256:237ca8705ffea849870de41101dba41543561da05c0ae45b2f1c547efa9843d2",
393
+ "sha256:f75049a3a7afa57165551e030dd8f9882ebf688b9600535a3f7e23596651875d"
394
+ ],
395
+ "version": "==22.0"
396
+ },
397
+ "requests": {
398
+ "hashes": [
399
+ "sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c",
400
+ "sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279"
401
+ ],
402
+ "version": "==2.20.0"
403
+ },
404
+ "requests-toolbelt": {
405
+ "hashes": [
406
+ "sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237",
407
+ "sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5"
408
+ ],
409
+ "version": "==0.8.0"
410
+ },
411
  "scandir": {
412
  "hashes": [
413
  "sha256:04b8adb105f2ed313a7c2ef0f1cf7aff4871aa7a1883fa4d8c44b5551ab052d6",
 
434
  },
435
  "toml": {
436
  "hashes": [
437
+ "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c",
438
+ "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e"
439
  ],
440
+ "version": "==0.10.0"
441
+ },
442
+ "tqdm": {
443
+ "hashes": [
444
+ "sha256:a0be569511161220ff709a5b60d0890d47921f746f1c737a11d965e1b29e7b2e",
445
+ "sha256:e293e6d7a7f41a529a27f8d6624ab11544ccbfe82a205af6fad102545099fc21"
446
+ ],
447
+ "version": "==4.27.0"
448
+ },
449
+ "twine": {
450
+ "hashes": [
451
+ "sha256:7d89bc6acafb31d124e6e5b295ef26ac77030bf098960c2a4c4e058335827c5c",
452
+ "sha256:fad6f1251195f7ddd1460cb76d6ea106c93adb4e56c41e0da79658e56e547d2c"
453
+ ],
454
+ "index": "pypi",
455
+ "version": "==1.12.1"
456
+ },
457
+ "urllib3": {
458
+ "hashes": [
459
+ "sha256:41c3db2fc01e5b907288010dec72f9d0a74e37d6994e6eb56849f59fea2265ae",
460
+ "sha256:8819bba37a02d143296a4d032373c4dd4aca11f6d4c9973335ca75f9c8475f59"
461
+ ],
462
+ "version": "==1.24"
463
  },
464
  "virtualenv": {
465
  "hashes": [
 
467
  "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752"
468
  ],
469
  "version": "==16.0.0"
470
+ },
471
+ "webencodings": {
472
+ "hashes": [
473
+ "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78",
474
+ "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"
475
+ ],
476
+ "version": "==0.5.1"
477
  }
478
  }
479
  }
README.md CHANGED
@@ -1,13 +1,14 @@
1
 
2
  <div align="center">
3
  <p>
4
- <img src="./images/pytube.png" width="350" height="328" alt="pytube logo" />
5
  </p>
6
  <p align="center">
7
  <img src="https://img.shields.io/pypi/v/pytube.svg" alt="pypi">
8
  <a href="https://travis-ci.org/nficano/pytube"><img src="https://travis-ci.org/nficano/pytube.svg?branch=master" /></a>
9
  <a href="http://python-pytube.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/python-pytube/badge/?version=latest" /></a>
10
  <a href="https://coveralls.io/github/nficano/pytube?branch=master"><img src="https://coveralls.io/repos/github/nficano/pytube/badge.svg?branch=master#23e6f7ac56dd3bde" /></a>
 
11
  <a href="https://pypi.python.org/pypi/pytube/"><img src="https://img.shields.io/pypi/pyversions/pytube.svg" /></a>
12
  </p>
13
  </div>
 
1
 
2
  <div align="center">
3
  <p>
4
+ <img src="https://github.com/nficano/pytube/blob/master/images/pytube.png?raw=true" width="350" height="328" alt="pytube logo" />
5
  </p>
6
  <p align="center">
7
  <img src="https://img.shields.io/pypi/v/pytube.svg" alt="pypi">
8
  <a href="https://travis-ci.org/nficano/pytube"><img src="https://travis-ci.org/nficano/pytube.svg?branch=master" /></a>
9
  <a href="http://python-pytube.readthedocs.io/en/latest/?badge=latest"><img src="https://readthedocs.org/projects/python-pytube/badge/?version=latest" /></a>
10
  <a href="https://coveralls.io/github/nficano/pytube?branch=master"><img src="https://coveralls.io/repos/github/nficano/pytube/badge.svg?branch=master#23e6f7ac56dd3bde" /></a>
11
+ <a href="https://pypi.org/project/pytube/"><img src="https://img.shields.io/pypi/dm/pytube.svg" alt="pypi"></a>
12
  <a href="https://pypi.python.org/pypi/pytube/"><img src="https://img.shields.io/pypi/pyversions/pytube.svg" /></a>
13
  </p>
14
  </div>
docs/conf.py CHANGED
@@ -35,7 +35,7 @@ master_doc = 'index'
35
 
36
  # General information about the project.
37
  project = 'pytube'
38
- copyright = '2017, Nick Ficano'
39
  author = 'Nick Ficano'
40
 
41
  # The version info for the project you're documenting, acts as replacement for
 
35
 
36
  # General information about the project.
37
  project = 'pytube'
38
+ copyright = '2018, Nick Ficano'
39
  author = 'Nick Ficano'
40
 
41
  # The version info for the project you're documenting, acts as replacement for
pytube/__init__.py CHANGED
@@ -5,10 +5,10 @@
5
  Pytube: a very serious Python library for downloading YouTube Videos.
6
  """
7
  __title__ = 'pytube'
8
- __version__ = '9.2.3'
9
  __author__ = 'Nick Ficano'
10
  __license__ = 'MIT License'
11
- __copyright__ = 'Copyright 2017 Nick Ficano'
12
 
13
  from pytube.logging import create_logger
14
  from pytube.query import CaptionQuery
 
5
  Pytube: a very serious Python library for downloading YouTube Videos.
6
  """
7
  __title__ = 'pytube'
8
+ __version__ = '9.3.4'
9
  __author__ = 'Nick Ficano'
10
  __license__ = 'MIT License'
11
+ __copyright__ = 'Copyright 2018 Nick Ficano'
12
 
13
  from pytube.logging import create_logger
14
  from pytube.query import CaptionQuery
pytube/captions.py CHANGED
@@ -45,7 +45,7 @@ class Caption:
45
  '00:00:03,890'
46
  """
47
  frac, whole = math.modf(d)
48
- time_fmt = time.strftime('0%H:0%M:%S,', time.gmtime(whole))
49
  ms = '{:.3f}'.format(frac).replace('0.', '')
50
  return time_fmt + ms
51
 
 
45
  '00:00:03,890'
46
  """
47
  frac, whole = math.modf(d)
48
+ time_fmt = time.strftime('%H:%M:%S,', time.gmtime(whole))
49
  ms = '{:.3f}'.format(frac).replace('0.', '')
50
  return time_fmt + ms
51
 
pytube/contrib/playlist.py CHANGED
@@ -2,7 +2,10 @@
2
  """
3
  Module to download a complete playlist from a youtube channel
4
  """
 
5
  import logging
 
 
6
 
7
  from pytube import request
8
  from pytube.__main__ import YouTube
@@ -36,6 +39,21 @@ class Playlist(object):
36
  # url is already in the desired format, so just return it
37
  return self.playlist_url
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def parse_links(self):
40
  """Parse the video links from the page source, extracts and
41
  returns the /watch?v= part from video link href
@@ -51,6 +69,23 @@ class Playlist(object):
51
  content = [x for x in req.split('\n') if 'pl-video-title-link' in x]
52
  link_list = [x.split('href="', 1)[1].split('&', 1)[0] for x in content]
53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  return link_list
55
 
56
  def populate_video_urls(self):
 
2
  """
3
  Module to download a complete playlist from a youtube channel
4
  """
5
+ import json
6
  import logging
7
+ import re
8
+ from collections import OrderedDict
9
 
10
  from pytube import request
11
  from pytube.__main__ import YouTube
 
39
  # url is already in the desired format, so just return it
40
  return self.playlist_url
41
 
42
+ def _load_more_url(self, req):
43
+ """Given an html page or a fragment thereof, looks for
44
+ and returns the "load more" url if found.
45
+
46
+ :return: string
47
+ """
48
+ try:
49
+ load_more_url = 'https://www.youtube.com' + re.search(
50
+ r'data-uix-load-more-href=\"(/browse_ajax\?'
51
+ 'action_continuation=.*?)\"', req,
52
+ ).group(1)
53
+ except AttributeError:
54
+ load_more_url = ''
55
+ return load_more_url
56
+
57
  def parse_links(self):
58
  """Parse the video links from the page source, extracts and
59
  returns the /watch?v= part from video link href
 
69
  content = [x for x in req.split('\n') if 'pl-video-title-link' in x]
70
  link_list = [x.split('href="', 1)[1].split('&', 1)[0] for x in content]
71
 
72
+ # The above only returns 100 or fewer links
73
+ # Simulating a browser request for the load more link
74
+ load_more_url = self._load_more_url(req)
75
+ while len(load_more_url): # there is an url found
76
+ logger.debug('load more url: %s' % load_more_url)
77
+ req = request.get(load_more_url)
78
+ load_more = json.loads(req)
79
+ videos = re.findall(
80
+ r'href=\"(/watch\?v=[\w-]*)',
81
+ load_more['content_html'],
82
+ )
83
+ # remove duplicates
84
+ link_list.extend(list(OrderedDict.fromkeys(videos)))
85
+ load_more_url = self._load_more_url(
86
+ load_more['load_more_widget_html'],
87
+ )
88
+
89
  return link_list
90
 
91
  def populate_video_urls(self):
pytube/query.py CHANGED
@@ -167,14 +167,16 @@ class StreamQuery:
167
  attr = getattr(stream, attribute_name)
168
  if attr is None:
169
  break
170
- num = [char for char in attr if char.isdigit()]
171
  integer_attr_repr[attr] = int(''.join(num)) if num else None
172
 
173
  # if every attribute has an integer representation
174
  if integer_attr_repr and all(integer_attr_repr.values()):
175
- def key(s): return integer_attr_repr[getattr(s, attribute_name)]
 
176
  else:
177
- def key(s): return getattr(s, attribute_name)
 
178
 
179
  fmt_streams = sorted(
180
  self.fmt_streams,
 
167
  attr = getattr(stream, attribute_name)
168
  if attr is None:
169
  break
170
+ num = ''.join(x for x in attr if x.isdigit())
171
  integer_attr_repr[attr] = int(''.join(num)) if num else None
172
 
173
  # if every attribute has an integer representation
174
  if integer_attr_repr and all(integer_attr_repr.values()):
175
+ def key(s):
176
+ return integer_attr_repr[getattr(s, attribute_name)]
177
  else:
178
+ def key(s):
179
+ return getattr(s, attribute_name)
180
 
181
  fmt_streams = sorted(
182
  self.fmt_streams,
pytube/streams.py CHANGED
@@ -226,7 +226,7 @@ class Stream(object):
226
  bytes_remaining -= len(chunk)
227
  # send to the on_progress callback.
228
  self.on_progress(chunk, fh, bytes_remaining)
229
- self.on_complete(fh)
230
  return fp
231
 
232
  def stream_to_buffer(self):
 
226
  bytes_remaining -= len(chunk)
227
  # send to the on_progress callback.
228
  self.on_progress(chunk, fh, bytes_remaining)
229
+ self.on_complete(fh)
230
  return fp
231
 
232
  def stream_to_buffer(self):
setup.cfg CHANGED
@@ -1,7 +1,7 @@
1
  [bumpversion]
2
  commit = True
3
  tag = True
4
- current_version = 9.2.3
5
  parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
6
  serialize =
7
  {major}.{minor}.{patch}
 
1
  [bumpversion]
2
  commit = True
3
  tag = True
4
+ current_version = 9.3.4
5
  parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
6
  serialize =
7
  {major}.{minor}.{patch}
setup.py CHANGED
@@ -1,25 +1,61 @@
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
  """This module contains setup instructions for pytube."""
4
- try:
5
- from setuptools import setup
6
- except ImportError:
7
- from distutils.core import setup
8
 
9
- with open('README.md') as readme_file:
10
- readme = readme_file.read()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- with open('LICENSE') as readme_file:
13
- license = readme_file.read()
14
 
15
  setup(
16
  name='pytube',
17
- version='9.2.3',
18
  author='Nick Ficano',
19
  author_email='nficano@gmail.com',
20
  packages=['pytube', 'pytube.contrib'],
 
 
 
21
  url='https://github.com/nficano/pytube',
22
- license=license,
23
  entry_points={
24
  'console_scripts': [
25
  'pytube = pytube.cli:main',
@@ -48,6 +84,9 @@ setup(
48
  'Topic :: Utilities',
49
  ],
50
  description=('A pythonic library for downloading YouTube Videos.'),
51
- long_description=readme,
 
 
52
  zip_safe=True,
 
53
  )
 
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
  """This module contains setup instructions for pytube."""
4
+ import codecs
5
+ import os
6
+ import sys
7
+ from shutil import rmtree
8
 
9
+ from setuptools import Command
10
+ from setuptools import setup
11
+
12
+ here = os.path.abspath(os.path.dirname(__file__))
13
+
14
+ with codecs.open(os.path.join(here, 'README.md'), encoding='utf-8') as fh:
15
+ long_description = '\n' + fh.read()
16
+
17
+
18
+ class UploadCommand(Command):
19
+ """Support setup.py publish."""
20
+
21
+ description = 'Build and publish the package.'
22
+ user_options = []
23
+
24
+ @staticmethod
25
+ def status(s):
26
+ """Prints things in bold."""
27
+ print('\033[1m{0}\033[0m'.format(s))
28
+
29
+ def initialize_options(self):
30
+ pass
31
+
32
+ def finalize_options(self):
33
+ pass
34
+
35
+ def run(self):
36
+ try:
37
+ self.status('Removing previous builds ...')
38
+ rmtree(os.path.join(here, 'dist'))
39
+ except Exception:
40
+ pass
41
+ self.status('Building Source distribution ...')
42
+ os.system('{0} setup.py sdist bdist_wheel'.format(sys.executable))
43
+ self.status('Uploading the package to PyPI via Twine ...')
44
+ os.system('twine upload dist/*')
45
+ sys.exit()
46
 
 
 
47
 
48
  setup(
49
  name='pytube',
50
+ version='9.3.4',
51
  author='Nick Ficano',
52
  author_email='nficano@gmail.com',
53
  packages=['pytube', 'pytube.contrib'],
54
+ package_data={
55
+ '': ['LICENSE'],
56
+ },
57
  url='https://github.com/nficano/pytube',
58
+ license='MIT',
59
  entry_points={
60
  'console_scripts': [
61
  'pytube = pytube.cli:main',
 
84
  'Topic :: Utilities',
85
  ],
86
  description=('A pythonic library for downloading YouTube Videos.'),
87
+ include_package_data=True,
88
+ long_description_content_type='text/markdown',
89
+ long_description=long_description,
90
  zip_safe=True,
91
+ cmdclass={'upload': UploadCommand},
92
  )