Skip to content

Commit 4d80569

Browse files
captainyugi00claude
andcommitted
Implement YouTube Python SDK with full API coverage
Async-first SDK wrapping YouTube Data API v3 and Analytics API v2, following the TikTok Python SDK architecture. Includes 14 API namespaces (videos, channels, playlists, comments, search, captions, analytics, etc.), Pydantic v2 models for all requests/responses, resumable video uploads, auto-pagination iterators, and comprehensive error handling. Also adds CI/CD pipeline (GitHub Actions), Docker support, and 35 tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 71af2d5 commit 4d80569

52 files changed

Lines changed: 5477 additions & 1 deletion

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copy this file to .env and fill in your values.
2+
# Never commit your real .env file to version control.
3+
4+
# OAuth 2.0 access token for full read/write access to a YouTube channel.
5+
# Obtain this through your OAuth 2.0 flow.
6+
YOUTUBE_ACCESS_TOKEN=ya29.your_access_token_here
7+
8+
# Google API key for read-only access to public data.
9+
# Get one from https://console.cloud.google.com/apis/credentials
10+
# YOUTUBE_API_KEY=AIzaSyYourApiKeyHere
11+
12+
# Optional: override the default HTTP request timeout (seconds).
13+
# YOUTUBE_TIMEOUT=30

.github/workflows/ci.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: ["main", "develop"]
6+
pull_request:
7+
branches: ["main", "develop"]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
name: Lint & format check
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: "3.12"
24+
25+
- name: Install ruff
26+
run: pip install ruff
27+
28+
- name: Check formatting
29+
run: ruff format --check .
30+
31+
- name: Lint
32+
run: ruff check .
33+
34+
type-check:
35+
name: Type check (mypy)
36+
runs-on: ubuntu-latest
37+
steps:
38+
- uses: actions/checkout@v4
39+
40+
- name: Set up Python
41+
uses: actions/setup-python@v5
42+
with:
43+
python-version: "3.12"
44+
45+
- name: Install dependencies
46+
run: |
47+
pip install -e ".[dev]"
48+
49+
- name: Run mypy
50+
run: mypy youtube/
51+
52+
test:
53+
name: Tests (Python ${{ matrix.python-version }})
54+
runs-on: ubuntu-latest
55+
strategy:
56+
fail-fast: false
57+
matrix:
58+
python-version: ["3.11", "3.12", "3.13"]
59+
60+
steps:
61+
- uses: actions/checkout@v4
62+
63+
- name: Set up Python ${{ matrix.python-version }}
64+
uses: actions/setup-python@v5
65+
with:
66+
python-version: ${{ matrix.python-version }}
67+
68+
- name: Cache pip
69+
uses: actions/cache@v4
70+
with:
71+
path: ~/.cache/pip
72+
key: ${{ runner.os }}-pip-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}
73+
restore-keys: |
74+
${{ runner.os }}-pip-${{ matrix.python-version }}-
75+
76+
- name: Install dependencies
77+
run: pip install -e ".[dev]"
78+
79+
- name: Run tests with coverage
80+
run: |
81+
pip install pytest-cov
82+
pytest --cov=youtube --cov-report=xml --cov-report=term-missing
83+
84+
- name: Upload coverage to Codecov
85+
if: matrix.python-version == '3.12'
86+
uses: codecov/codecov-action@v4
87+
with:
88+
files: coverage.xml
89+
fail_ci_if_error: false
90+
91+
docker-build:
92+
name: Docker build check
93+
runs-on: ubuntu-latest
94+
steps:
95+
- uses: actions/checkout@v4
96+
97+
- name: Build Docker image
98+
run: docker build --target dev -t youtube-python-sdk:dev .

.github/workflows/release.yml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*.*.*"
7+
8+
permissions:
9+
contents: write
10+
id-token: write
11+
12+
jobs:
13+
validate:
14+
name: Validate tag matches package version
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Set up Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: "3.12"
23+
24+
- name: Install package
25+
run: pip install -e .
26+
27+
- name: Check version match
28+
run: |
29+
TAG_VERSION="${GITHUB_REF_NAME#v}"
30+
PKG_VERSION=$(python -c "import youtube; print(youtube.__version__)")
31+
if [ "$TAG_VERSION" != "$PKG_VERSION" ]; then
32+
echo "Tag version ($TAG_VERSION) does not match package version ($PKG_VERSION)."
33+
exit 1
34+
fi
35+
echo "Version check passed: $PKG_VERSION"
36+
37+
test:
38+
name: Full test suite before release
39+
needs: validate
40+
runs-on: ubuntu-latest
41+
strategy:
42+
matrix:
43+
python-version: ["3.11", "3.12", "3.13"]
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Set up Python ${{ matrix.python-version }}
48+
uses: actions/setup-python@v5
49+
with:
50+
python-version: ${{ matrix.python-version }}
51+
52+
- name: Install dependencies
53+
run: pip install -e ".[dev]"
54+
55+
- name: Run tests
56+
run: pytest
57+
58+
build-and-publish:
59+
name: Build distribution and publish to PyPI
60+
needs: test
61+
runs-on: ubuntu-latest
62+
environment:
63+
name: pypi
64+
url: https://pypi.org/project/youtube-python-sdk/
65+
steps:
66+
- uses: actions/checkout@v4
67+
68+
- name: Set up Python
69+
uses: actions/setup-python@v5
70+
with:
71+
python-version: "3.12"
72+
73+
- name: Install build tools
74+
run: pip install hatch
75+
76+
- name: Build distributions
77+
run: hatch build
78+
79+
- name: Publish to PyPI
80+
uses: pypa/gh-action-pypi-publish@release/v1
81+
82+
github-release:
83+
name: Create GitHub release
84+
needs: build-and-publish
85+
runs-on: ubuntu-latest
86+
steps:
87+
- uses: actions/checkout@v4
88+
with:
89+
fetch-depth: 0
90+
91+
- name: Create GitHub Release
92+
uses: softprops/action-gh-release@v2
93+
with:
94+
generate_release_notes: true
95+
draft: false
96+
prerelease: ${{ contains(github.ref_name, '-') }}

Dockerfile

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# =============================================================================
2+
# YouTube Python SDK — Multi-stage Dockerfile
3+
# =============================================================================
4+
#
5+
# Stages:
6+
# base — shared Python + system dependencies
7+
# dev — development environment with all extras (tests, linting)
8+
# prod — minimal runtime image for library consumers
9+
#
10+
# Build examples:
11+
# docker build --target dev -t youtube-sdk:dev .
12+
# docker build --target prod -t youtube-sdk:prod .
13+
14+
ARG PYTHON_VERSION=3.12
15+
ARG DEBIAN_RELEASE=slim-bookworm
16+
17+
# -----------------------------------------------------------------------------
18+
# Stage: base
19+
# -----------------------------------------------------------------------------
20+
FROM python:${PYTHON_VERSION}-${DEBIAN_RELEASE} AS base
21+
22+
ENV PYTHONDONTWRITEBYTECODE=1 \
23+
PYTHONUNBUFFERED=1 \
24+
PIP_NO_CACHE_DIR=1 \
25+
PIP_DISABLE_PIP_VERSION_CHECK=1
26+
27+
WORKDIR /app
28+
29+
# Copy only the packaging metadata first to leverage Docker layer caching.
30+
COPY pyproject.toml README.md LICENSE ./
31+
COPY youtube/ ./youtube/
32+
33+
# -----------------------------------------------------------------------------
34+
# Stage: dev
35+
# -----------------------------------------------------------------------------
36+
FROM base AS dev
37+
38+
# Install the package with development extras.
39+
RUN pip install -e ".[dev]"
40+
41+
COPY tests/ ./tests/
42+
43+
# Default command runs the full test suite.
44+
CMD ["pytest", "--tb=short", "-v"]
45+
46+
# -----------------------------------------------------------------------------
47+
# Stage: prod
48+
# -----------------------------------------------------------------------------
49+
FROM base AS prod
50+
51+
# Install only the runtime dependencies.
52+
RUN pip install .
53+
54+
# The SDK is a library — nothing to run by default.
55+
# Override CMD in your own Dockerfile to use it.
56+
CMD ["python", "-c", "import youtube; print(f'YouTube Python SDK v{youtube.__version__} ready.')"]

0 commit comments

Comments
 (0)