Development Guide¶
Prerequisites¶
- Python >= 3.12
- A Google Cloud project with the YouTube Data API v3 enabled
- OAuth2 client credentials (
client_secret.json)
Setting Up a Development Environment¶
git clone https://github.com/veltzer/pytubekit.git
cd pytubekit
python -m venv .venv
source .venv/bin/activate
pip install -e .
pip install pytest mypy ruff pylint
Running Tests¶
The Makefile all target runs:
pytest tests- unit testsruff check- linterpylint- code analysismypy- type checking- A regex check for unescaped single quotes in Python files
Code Quality Tools¶
| Tool | Config File | Purpose |
|---|---|---|
| ruff | pyproject.toml ([tool.ruff]) |
Linting, line length = 130 |
| pylint | .pylintrc |
Code analysis |
| mypy | .mypy.ini / pyproject.toml |
Static type checking, Python 3.12 |
| pytest | pyproject.toml ([tool.pytest.ini_options]) |
Test runner, pythonpath = ["src"] |
Project Layout¶
Source code lives in src/pytubekit/ following the src layout convention. The pyproject.toml configures pytest to include src in the Python path.
Code Generation with pydmt¶
Several files are generated from Mako templates. The source of truth for project metadata lives in the config/ directory:
config/project.py- Project name, description, keywordsconfig/version.py- Version tupleconfig/python.py- Python dependencies and scriptsconfig/personal.py- Author detailsconfig/platform.py- Python version requirements
To regenerate files, run pydmt (if installed):
Do not manually edit generated files (pyproject.toml, README.md, static.py, LICENSE, requirements.thawed.txt). Edit the templates or config modules instead.
Adding a New CLI Command¶
- Define any new configuration classes in
src/pytubekit/configs.py:
class ConfigMyFeature(Config):
""" Parameters for my feature """
my_param = ParamCreator.create_str(
help_string="Description of the parameter",
default="default_value",
)
- Add the endpoint function in
src/pytubekit/main.py:
@register_endpoint(
description="Description of what this command does",
configs=[ConfigMyFeature],
)
def my_command() -> None:
youtube = get_youtube()
# ... implementation
- Import the new config class at the top of
main.py.
The command will automatically be available as pytubekit my_command.
YouTube API Notes¶
Deleted and Private Videos¶
When listing playlist items, the YouTube API returns deleted videos with the title "Deleted video" and private videos with the title "Private video". Fetching video details for a deleted video returns an empty items array.
Pagination¶
The YouTube API returns at most 50 items per request. The PagedRequest class in util.py handles pagination automatically by following nextPageToken values.
API Quota¶
The YouTube Data API v3 has a daily quota of 10,000 units. Different operations consume different amounts of quota. If you hit the limit, wait until the next day.
Test Video IDs¶
For manual testing:
| Type | Video ID |
|---|---|
| Regular video | xL_sMXfzzyA |
| Deleted video | 6k2nFwVqQFw |
| Private video | MZnlL8uCCU0 |
CI/CD¶
The project uses GitHub Actions (.github/workflows/build.yml) running on Ubuntu 24.04 with Python 3.12.
Building the Documentation¶
The documentation site lives in the mkdocs/ directory and uses MkDocs with the Material theme.
Install dependencies¶
Preview locally¶
Then open http://127.0.0.1:8000 in your browser. Changes to the Markdown files are picked up automatically.
Build the static site¶
The output goes to mkdocs/site/ (git-ignored).
Deploy to GitHub Pages¶
This builds the site and pushes it to the gh-pages branch. In the GitHub repository settings, set Pages source to "Deploy from a branch" with gh-pages / / (root).