ytpaw 0.1.0__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.
ytpaw-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: ytpaw
3
+ Version: 0.1.0
4
+ Summary: YouTube search and public statistics client
5
+ License-Expression: MIT
6
+ Requires-Python: >=3.9
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: curl-cffi>=0.13.0
9
+ Provides-Extra: test
10
+ Requires-Dist: pytest>=7; extra == "test"
11
+ Provides-Extra: docs
12
+ Requires-Dist: sphinx<10,>=9; python_version >= "3.11" and extra == "docs"
13
+ Requires-Dist: sphinx<9,>=6; python_version < "3.11" and extra == "docs"
14
+ Requires-Dist: myst-parser<6,>=5; python_version >= "3.11" and extra == "docs"
15
+ Requires-Dist: myst-parser<5,>=2; python_version < "3.11" and extra == "docs"
16
+ Requires-Dist: shibuya<2027,>=2026.1; python_version >= "3.11" and extra == "docs"
17
+ Requires-Dist: shibuya<2026,>=2024; python_version < "3.11" and extra == "docs"
18
+ Requires-Dist: sphinx-autodoc-typehints<4,>=3; python_version >= "3.10" and extra == "docs"
19
+ Requires-Dist: sphinx-autodoc-typehints<3,>=1; python_version < "3.10" and extra == "docs"
20
+ Requires-Dist: sphinx-copybutton<0.6,>=0.5; extra == "docs"
21
+ Requires-Dist: sphinx-design<0.8,>=0.7; python_version >= "3.11" and extra == "docs"
22
+ Requires-Dist: sphinx-design<0.7,>=0.5; python_version < "3.11" and extra == "docs"
23
+ Requires-Dist: sphinxcontrib-mermaid<3,>=2; python_version >= "3.10" and extra == "docs"
24
+ Requires-Dist: sphinxcontrib-mermaid<2,>=1; python_version < "3.10" and extra == "docs"
25
+
26
+ # ytpaw
27
+
28
+ `ytpaw` is a small Python library for YouTube search and public metadata
29
+ collection. It intentionally does not download media, implement SABR or
30
+ signature deciphering, or merge audio and video streams.
31
+
32
+ Shared model field names follow [NAMING_STANDARD.md](NAMING_STANDARD.md), while
33
+ YouTube-specific extensions retain their provider-specific meaning.
34
+
35
+ All Innertube, HTML, and OAuth requests use `curl_cffi` with browser-compatible
36
+ TLS handling. Proxy, timeout, retry, OAuth, and PO-token options remain
37
+ available through `YouTubeClient`.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install ytpaw
43
+ ```
44
+
45
+ For development and tests:
46
+
47
+ ```bash
48
+ pip install -e ".[test]"
49
+ python -m pytest
50
+ ```
51
+
52
+ The default suite is network-free. Run the real-YouTube integration suite
53
+ explicitly when network access and rate-limit budget are available:
54
+
55
+ ```powershell
56
+ $env:YTPAW_RUN_INTEGRATION = "1"
57
+ python -m pytest tests/integration -m integration -s
58
+ ```
59
+
60
+ For the documentation site:
61
+
62
+ ```bash
63
+ uv sync --extra docs
64
+ uv run sphinx-build -b html docs docs/_build/html
65
+ ```
66
+
67
+ The Russian README is available in [README.ru.md](README.ru.md).
68
+
69
+ ## Quick Start
70
+
71
+ ```python
72
+ from ytpaw import YouTubeClient
73
+
74
+ client = YouTubeClient(min_interval=1.0, retries=3)
75
+ video = client.video_stats("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
76
+
77
+ print(video.title, video.view_count, video.like_count, video.comment_count)
78
+ print(client.channel_stats("UC_x5XG1OV2P6uZZ5xm2JYQ"))
79
+
80
+ for result in client.search("python http client"):
81
+ print(result.result_type, result.id, result.title)
82
+ ```
83
+
84
+ ## API
85
+
86
+ - `YouTubeClient.video_stats(url)` returns `VideoStats` for a YouTube video.
87
+ - `YouTubeClient.channel_stats(profile_id_or_url)` returns `ChannelStats`.
88
+ - `YouTubeClient.channel_videos(profile_id_or_url, limit)` yields available
89
+ video statistics from newest to oldest and follows continuation pages.
90
+ - `YouTubeClient.related_videos(url, depth=0)` traverses side-panel
91
+ recommendations breadth-first and yields `RelatedVideo` objects.
92
+ - `YouTubeClient.search(query, filters=None)` returns video, channel, and
93
+ playlist `SearchResult` objects.
94
+ - `is_video_url(value)`, `is_channel_url(value)`, and `youtube_url_type(value)`
95
+ classify ambiguous input safely before selecting a client method.
96
+ - `extract_video_stats()` and `extract_channel_stats()` parse saved responses
97
+ without making network requests.
98
+
99
+ `channel_videos()` accepts channel IDs, `@handles`, URLs with or without a
100
+ scheme, `/channel/ID`, `/@handle`, `/c/name`, `/user/name`, and `/videos`
101
+ suffixes. `related_videos(depth=0)` returns direct recommendations only; the
102
+ input video itself is never yielded.
103
+
104
+ Every model keeps the original response in `raw`. The field is hidden from
105
+ `repr()` because responses can be large and may contain service metadata.
106
+
107
+ ## Network Context
108
+
109
+ The client supports `proxy`, `timeout`, `retries`, and `min_interval` for
110
+ corporate or rate-limited environments. `visitor_data`, `oauth_token`, and
111
+ optional PO-token integration are supported where YouTube requires a specific
112
+ request context. These options do not bypass CAPTCHA, authentication,
113
+ authorization, access controls, or YouTube policies.
114
+
115
+ ```python
116
+ client = YouTubeClient(
117
+ proxy="http://127.0.0.1:8080",
118
+ timeout=20,
119
+ retries=4,
120
+ min_interval=0.5,
121
+ visitor_data="VISITOR_DATA",
122
+ oauth_token="OAUTH_ACCESS_TOKEN",
123
+ language="en",
124
+ region="US",
125
+ )
126
+ ```
127
+
128
+ The default locale is `en-US` so numeric labels are stable for parsing. Set
129
+ `language` and `region` when needed; localized units such as `тыс.`, `Mio.`,
130
+ `million`, and `mil` are supported.
131
+
132
+ ## OAuth
133
+
134
+ ```python
135
+ client = YouTubeClient(use_oauth=True, allow_oauth_cache=True)
136
+ ```
137
+
138
+ The first run starts Google's Device Flow and displays a verification URL and
139
+ one-time code. Tokens are refreshed automatically and stored in
140
+ `~/.cache/ytpaw/tokens.json` by default. Do not publish or commit this file.
141
+ Set `allow_oauth_cache=False` to disable persistence, or pass `oauth_verifier`
142
+ for a GUI or custom CLI.
143
+
144
+ ## PO Tokens
145
+
146
+ ```python
147
+ from ytpaw import YouTubeClient, generate_po_token
148
+
149
+ po_token = generate_po_token("dQw4w9WgXcQ")
150
+ client = YouTubeClient(
151
+ visitor_data="VISITOR_DATA_FROM_THE_SAME_CONTEXT",
152
+ po_token=po_token,
153
+ )
154
+ ```
155
+
156
+ Install the optional generator dependencies with `pytubefix` and
157
+ `nodejs-wheel-binaries`, or pass a `po_token_verifier` returning
158
+ `(visitor_data, po_token)`. Tokens are never fabricated. Missing BotGuard
159
+ assets or Node.js results in `RequestError`.
160
+
161
+ ## Windows Encoding
162
+
163
+ Use UTF-8 output when running the smoke script on Windows:
164
+
165
+ ```powershell
166
+ python -X utf8 .\da.py
167
+ ```
168
+
169
+ ## Limitations and Safety
170
+
171
+ YouTube changes internal response schemas and applies rate limits. Public
172
+ statistics may be incomplete for private, removed, age-restricted, or blocked
173
+ content. Live requests are not deterministic.
174
+
175
+ Do not log or commit access tokens, refresh tokens, bearer headers, visitor
176
+ data, PO tokens, or OAuth cache files. Use proxies only when you are authorized
177
+ to do so. The project is MIT licensed.
ytpaw-0.1.0/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # ytpaw
2
+
3
+ `ytpaw` is a small Python library for YouTube search and public metadata
4
+ collection. It intentionally does not download media, implement SABR or
5
+ signature deciphering, or merge audio and video streams.
6
+
7
+ Shared model field names follow [NAMING_STANDARD.md](NAMING_STANDARD.md), while
8
+ YouTube-specific extensions retain their provider-specific meaning.
9
+
10
+ All Innertube, HTML, and OAuth requests use `curl_cffi` with browser-compatible
11
+ TLS handling. Proxy, timeout, retry, OAuth, and PO-token options remain
12
+ available through `YouTubeClient`.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install ytpaw
18
+ ```
19
+
20
+ For development and tests:
21
+
22
+ ```bash
23
+ pip install -e ".[test]"
24
+ python -m pytest
25
+ ```
26
+
27
+ The default suite is network-free. Run the real-YouTube integration suite
28
+ explicitly when network access and rate-limit budget are available:
29
+
30
+ ```powershell
31
+ $env:YTPAW_RUN_INTEGRATION = "1"
32
+ python -m pytest tests/integration -m integration -s
33
+ ```
34
+
35
+ For the documentation site:
36
+
37
+ ```bash
38
+ uv sync --extra docs
39
+ uv run sphinx-build -b html docs docs/_build/html
40
+ ```
41
+
42
+ The Russian README is available in [README.ru.md](README.ru.md).
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ from ytpaw import YouTubeClient
48
+
49
+ client = YouTubeClient(min_interval=1.0, retries=3)
50
+ video = client.video_stats("https://www.youtube.com/watch?v=dQw4w9WgXcQ")
51
+
52
+ print(video.title, video.view_count, video.like_count, video.comment_count)
53
+ print(client.channel_stats("UC_x5XG1OV2P6uZZ5xm2JYQ"))
54
+
55
+ for result in client.search("python http client"):
56
+ print(result.result_type, result.id, result.title)
57
+ ```
58
+
59
+ ## API
60
+
61
+ - `YouTubeClient.video_stats(url)` returns `VideoStats` for a YouTube video.
62
+ - `YouTubeClient.channel_stats(profile_id_or_url)` returns `ChannelStats`.
63
+ - `YouTubeClient.channel_videos(profile_id_or_url, limit)` yields available
64
+ video statistics from newest to oldest and follows continuation pages.
65
+ - `YouTubeClient.related_videos(url, depth=0)` traverses side-panel
66
+ recommendations breadth-first and yields `RelatedVideo` objects.
67
+ - `YouTubeClient.search(query, filters=None)` returns video, channel, and
68
+ playlist `SearchResult` objects.
69
+ - `is_video_url(value)`, `is_channel_url(value)`, and `youtube_url_type(value)`
70
+ classify ambiguous input safely before selecting a client method.
71
+ - `extract_video_stats()` and `extract_channel_stats()` parse saved responses
72
+ without making network requests.
73
+
74
+ `channel_videos()` accepts channel IDs, `@handles`, URLs with or without a
75
+ scheme, `/channel/ID`, `/@handle`, `/c/name`, `/user/name`, and `/videos`
76
+ suffixes. `related_videos(depth=0)` returns direct recommendations only; the
77
+ input video itself is never yielded.
78
+
79
+ Every model keeps the original response in `raw`. The field is hidden from
80
+ `repr()` because responses can be large and may contain service metadata.
81
+
82
+ ## Network Context
83
+
84
+ The client supports `proxy`, `timeout`, `retries`, and `min_interval` for
85
+ corporate or rate-limited environments. `visitor_data`, `oauth_token`, and
86
+ optional PO-token integration are supported where YouTube requires a specific
87
+ request context. These options do not bypass CAPTCHA, authentication,
88
+ authorization, access controls, or YouTube policies.
89
+
90
+ ```python
91
+ client = YouTubeClient(
92
+ proxy="http://127.0.0.1:8080",
93
+ timeout=20,
94
+ retries=4,
95
+ min_interval=0.5,
96
+ visitor_data="VISITOR_DATA",
97
+ oauth_token="OAUTH_ACCESS_TOKEN",
98
+ language="en",
99
+ region="US",
100
+ )
101
+ ```
102
+
103
+ The default locale is `en-US` so numeric labels are stable for parsing. Set
104
+ `language` and `region` when needed; localized units such as `тыс.`, `Mio.`,
105
+ `million`, and `mil` are supported.
106
+
107
+ ## OAuth
108
+
109
+ ```python
110
+ client = YouTubeClient(use_oauth=True, allow_oauth_cache=True)
111
+ ```
112
+
113
+ The first run starts Google's Device Flow and displays a verification URL and
114
+ one-time code. Tokens are refreshed automatically and stored in
115
+ `~/.cache/ytpaw/tokens.json` by default. Do not publish or commit this file.
116
+ Set `allow_oauth_cache=False` to disable persistence, or pass `oauth_verifier`
117
+ for a GUI or custom CLI.
118
+
119
+ ## PO Tokens
120
+
121
+ ```python
122
+ from ytpaw import YouTubeClient, generate_po_token
123
+
124
+ po_token = generate_po_token("dQw4w9WgXcQ")
125
+ client = YouTubeClient(
126
+ visitor_data="VISITOR_DATA_FROM_THE_SAME_CONTEXT",
127
+ po_token=po_token,
128
+ )
129
+ ```
130
+
131
+ Install the optional generator dependencies with `pytubefix` and
132
+ `nodejs-wheel-binaries`, or pass a `po_token_verifier` returning
133
+ `(visitor_data, po_token)`. Tokens are never fabricated. Missing BotGuard
134
+ assets or Node.js results in `RequestError`.
135
+
136
+ ## Windows Encoding
137
+
138
+ Use UTF-8 output when running the smoke script on Windows:
139
+
140
+ ```powershell
141
+ python -X utf8 .\da.py
142
+ ```
143
+
144
+ ## Limitations and Safety
145
+
146
+ YouTube changes internal response schemas and applies rate limits. Public
147
+ statistics may be incomplete for private, removed, age-restricted, or blocked
148
+ content. Live requests are not deterministic.
149
+
150
+ Do not log or commit access tokens, refresh tokens, bearer headers, visitor
151
+ data, PO tokens, or OAuth cache files. Use proxies only when you are authorized
152
+ to do so. The project is MIT licensed.
@@ -0,0 +1,63 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ytpaw"
7
+ version = "0.1.0"
8
+ description = "YouTube search and public statistics client"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = "MIT"
12
+ dependencies = [
13
+ "curl-cffi>=0.13.0",
14
+ ]
15
+
16
+ [project.optional-dependencies]
17
+ test = ["pytest>=7"]
18
+ docs = [
19
+ "sphinx>=9,<10; python_version >= '3.11'",
20
+ "sphinx>=6,<9; python_version < '3.11'",
21
+ "myst-parser>=5,<6; python_version >= '3.11'",
22
+ "myst-parser>=2,<5; python_version < '3.11'",
23
+ "shibuya>=2026.1,<2027; python_version >= '3.11'",
24
+ "shibuya>=2024,<2026; python_version < '3.11'",
25
+ "sphinx-autodoc-typehints>=3,<4; python_version >= '3.10'",
26
+ "sphinx-autodoc-typehints>=1,<3; python_version < '3.10'",
27
+ "sphinx-copybutton>=0.5,<0.6",
28
+ "sphinx-design>=0.7,<0.8; python_version >= '3.11'",
29
+ "sphinx-design>=0.5,<0.7; python_version < '3.11'",
30
+ "sphinxcontrib-mermaid>=2,<3; python_version >= '3.10'",
31
+ "sphinxcontrib-mermaid>=1,<2; python_version < '3.10'",
32
+ ]
33
+
34
+ [tool.setuptools.packages.find]
35
+ where = ["."]
36
+ include = ["ytpaw*"]
37
+
38
+ [tool.pytest.ini_options]
39
+ testpaths = ["tests"]
40
+ addopts = "-q"
41
+ markers = [
42
+ "integration: tests that make live requests to YouTube",
43
+ ]
44
+
45
+ [dependency-groups]
46
+ dev = [
47
+ "pytest>=8.4.2",
48
+ ]
49
+ docs = [
50
+ "sphinx>=9,<10; python_version >= '3.11'",
51
+ "sphinx>=6,<9; python_version < '3.11'",
52
+ "myst-parser>=5,<6; python_version >= '3.11'",
53
+ "myst-parser>=2,<5; python_version < '3.11'",
54
+ "shibuya>=2026.1,<2027; python_version >= '3.11'",
55
+ "shibuya>=2024,<2026; python_version < '3.11'",
56
+ "sphinx-autodoc-typehints>=3,<4; python_version >= '3.10'",
57
+ "sphinx-autodoc-typehints>=1,<3; python_version < '3.10'",
58
+ "sphinx-copybutton>=0.5,<0.6",
59
+ "sphinx-design>=0.7,<0.8; python_version >= '3.11'",
60
+ "sphinx-design>=0.5,<0.7; python_version < '3.11'",
61
+ "sphinxcontrib-mermaid>=2,<3; python_version >= '3.10'",
62
+ "sphinxcontrib-mermaid>=1,<2; python_version < '3.10'",
63
+ ]
ytpaw-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+