polytool 0.2.6__tar.gz → 0.2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {polytool-0.2.6 → polytool-0.2.7}/PKG-INFO +3 -1
  2. {polytool-0.2.6 → polytool-0.2.7}/pyproject.toml +2 -2
  3. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/__init__.py +1 -1
  4. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/dl.py +24 -2
  5. {polytool-0.2.6 → polytool-0.2.7}/.gitignore +0 -0
  6. {polytool-0.2.6 → polytool-0.2.7}/LICENSE +0 -0
  7. {polytool-0.2.6 → polytool-0.2.7}/README.md +0 -0
  8. {polytool-0.2.6 → polytool-0.2.7}/docs/README.md +0 -0
  9. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/__main__.py +0 -0
  10. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/__init__.py +0 -0
  11. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/clip.py +0 -0
  12. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/color.py +0 -0
  13. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/convert.py +0 -0
  14. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/cron.py +0 -0
  15. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/data.py +0 -0
  16. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/enc.py +0 -0
  17. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/file.py +0 -0
  18. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/gen.py +0 -0
  19. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/img.py +0 -0
  20. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/net.py +0 -0
  21. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/pdf.py +0 -0
  22. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/qr.py +0 -0
  23. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/shot.py +0 -0
  24. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/text.py +0 -0
  25. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/cli/vid.py +0 -0
  26. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/__init__.py +0 -0
  27. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/browsers.py +0 -0
  28. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/config.py +0 -0
  29. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/console.py +0 -0
  30. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/errors.py +0 -0
  31. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/ffmpeg.py +0 -0
  32. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/io.py +0 -0
  33. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/lazy.py +0 -0
  34. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/progress.py +0 -0
  35. {polytool-0.2.6 → polytool-0.2.7}/src/polytool/core/runtime.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polytool
3
- Version: 0.2.6
3
+ Version: 0.2.7
4
4
  Summary: One-binary CLI bundling 26 everyday utilities — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more
5
5
  Project-URL: Homepage, https://github.com/k6w/polytool
6
6
  Project-URL: Repository, https://github.com/k6w/polytool
@@ -48,6 +48,7 @@ Requires-Dist: pytest-cov>=5; extra == 'dev'
48
48
  Requires-Dist: pytest>=8; extra == 'dev'
49
49
  Requires-Dist: ruff>=0.5; extra == 'dev'
50
50
  Provides-Extra: dl
51
+ Requires-Dist: yt-dlp-ejs>=0.8; extra == 'dl'
51
52
  Requires-Dist: yt-dlp>=2024.5; extra == 'dl'
52
53
  Provides-Extra: full
53
54
  Requires-Dist: ascii-magic>=2; extra == 'full'
@@ -70,6 +71,7 @@ Requires-Dist: pytesseract>=0.3; extra == 'full'
70
71
  Requires-Dist: pyzbar>=0.1; extra == 'full'
71
72
  Requires-Dist: rembg[cpu]>=2.0; extra == 'full'
72
73
  Requires-Dist: resvg-py>=0.1; extra == 'full'
74
+ Requires-Dist: yt-dlp-ejs>=0.8; extra == 'full'
73
75
  Requires-Dist: yt-dlp>=2024.5; extra == 'full'
74
76
  Provides-Extra: img
75
77
  Requires-Dist: ascii-magic>=2; extra == 'img'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "polytool"
7
- version = "0.2.6"
7
+ version = "0.2.7"
8
8
  description = "One-binary CLI bundling 26 everyday utilities — image/video/PDF conversion, background removal, OCR, QR codes, hashing, downloads, and more"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -58,7 +58,7 @@ img = [
58
58
  ]
59
59
  vid = ["ffmpeg-python>=0.2", "imageio-ffmpeg>=0.5"]
60
60
  pdf = ["pypdf>=4", "pikepdf>=8", "pdfplumber>=0.11", "pymupdf>=1.24"]
61
- dl = ["yt-dlp>=2024.5"]
61
+ dl = ["yt-dlp>=2024.5", "yt-dlp-ejs>=0.8"]
62
62
  ocr = ["pytesseract>=0.3", "easyocr>=1.7"]
63
63
  ai = ["rembg[cpu]>=2.0"]
64
64
  qr-decode = ["pyzbar>=0.1"]
@@ -1,4 +1,4 @@
1
1
  """polytool — one-binary CLI bundling 26 everyday utilities."""
2
2
 
3
- __version__ = "0.2.6"
3
+ __version__ = "0.2.7"
4
4
  __all__ = ["__version__"]
@@ -56,6 +56,13 @@ N_CHALLENGE_PATTERNS = (
56
56
  "requested format is not available",
57
57
  )
58
58
 
59
+ # Patterns that indicate per-session DRM lock — not something we can solve.
60
+ DRM_PATTERNS = (
61
+ "drm protected",
62
+ "drm-protected",
63
+ "experiment that applies drm",
64
+ )
65
+
59
66
 
60
67
  _ANSI_RE = re.compile(r"\x1b\[[0-9;]*[A-Za-z]")
61
68
  _NOISE_RE = re.compile(
@@ -151,10 +158,25 @@ def _n_challenge_hint(messages: list[str]) -> str | None:
151
158
  )
152
159
 
153
160
 
161
+ def _drm_hint(messages: list[str]) -> str | None:
162
+ text = " ".join(messages).lower()
163
+ if not any(p in text for p in DRM_PATTERNS):
164
+ return None
165
+ return (
166
+ "YouTube has flagged this video as DRM-protected for your current session.\n"
167
+ "This is a per-account / per-session A/B experiment yt-dlp can't bypass.\n\n"
168
+ "Workarounds (any one usually works):\n"
169
+ " • Try without cookies: [cyan]pt dl get URL --cookies-from-browser ''[/cyan]\n"
170
+ " • Use a different browser profile: [cyan]pt dl setup --browser chrome[/cyan]\n"
171
+ " • Try a different YouTube account.\n"
172
+ " • Pick a different video — only some are DRM-flagged in your session."
173
+ )
174
+
175
+
154
176
  def _hint_for_error(message: str, logger: _DlLogger) -> str | None:
155
- """Pick the best hint for a failure: bot-check first, then n-challenge."""
177
+ """Pick the best hint for a failure: DRM > bot-check > n-challenge."""
156
178
  pool = [message, *logger.warnings, *logger.errors]
157
- return _bot_check_hint(message) or _n_challenge_hint(pool)
179
+ return _drm_hint(pool) or _bot_check_hint(message) or _n_challenge_hint(pool)
158
180
 
159
181
 
160
182
  # --------------------------------------------------------------------------- #
File without changes
File without changes
File without changes
File without changes