Development Guide ================= Prerequisites ------------- - Python >= 3.14 - A Google Cloud project with the YouTube Data API v3 enabled - OAuth2 client credentials at ``~/.config/pytubekit/client_secret.json`` (required to build a release: the build hook copies it into the package) Setting Up a Development Environment ------------------------------------ .. code:: bash 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 ------------- .. code:: bash # Run unit tests pytest tests # Run the full CI suite (tests + linting + type checking) rsconstruct build The rsconstruct build runs: 1. ``pytest tests`` - unit tests 2. ``ruff check`` - linter 3. ``pylint`` - code analysis 4. ``mypy`` - type checking 5. ``luacheck`` on ``config/``, ``taplo`` on the TOML files and ``actionlint`` on the workflows Code Quality Tools ------------------ +--------+----------------------------------------------------+---------------------------------------+ | Tool | Config File | Purpose | +========+====================================================+=======================================+ | ruff | ``pyproject.toml`` (``[tool.ruff]``) | Linting, line length = 130 | +--------+----------------------------------------------------+---------------------------------------+ | pylint | ``.pylintrc`` | Code analysis | +--------+----------------------------------------------------+---------------------------------------+ | mypy | ``pyproject.toml`` (``[tool.mypy]``) | Static type checking | +--------+----------------------------------------------------+---------------------------------------+ | 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 rsconstruct -------------------------------- ``README.md`` and ``src/pytubekit/static.py`` are rendered from tera templates in ``tera.templates/`` by rsconstruct. The source of truth for project metadata lives in the ``config/`` directory: - ``config/project.lua`` - Project name, description, keywords - ``config/version.lua`` - Version tuple - ``config/personal.lua`` - Author details To regenerate files, run: .. code:: bash rsconstruct build Do not manually edit the generated files (``README.md``, ``static.py``). Edit the templates or config files instead. ``pyproject.toml`` is hand-edited and is the authoritative dependency list. Adding a New CLI Command ------------------------ 1. Define any new configuration classes in ``src/pytubekit/configs.py``: .. code:: python class ConfigMyFeature(Config): """ Parameters for my feature """ my_param = ParamCreator.create_str( help_string="Description of the parameter", default="default_value", ) 2. Add the endpoint function in ``src/pytubekit/main.py``: .. code:: python @register_endpoint( description="Description of what this command does", configs=[ConfigMyFeature], ) def my_command() -> None: youtube = get_youtube() # ... implementation 3. 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 26.04 with Python 3.14. Building the Documentation -------------------------- The documentation lives in the ``sphinx/`` directory as reStructuredText and is built with `Sphinx `__, like every other python repository in the fleet. The guide pages sit next to the autodoc API pages, all reachable from ``sphinx/modules.rst``. Build ~~~~~ The sphinx processor is part of the regular build, so from the repository's venv: .. code:: bash rsconstruct build The rendered site goes to ``docs/``, which is committed and served by GitHub Pages from the master branch. ``sphinx/conf.py`` refuses to build unless the sphinx toolchain matches ``uv.lock``, so activate the repository's venv first. Preview locally ~~~~~~~~~~~~~~~ .. code:: bash python -m http.server --directory docs 8000 Then open http://127.0.0.1:8000 in your browser and rebuild after editing the ``.rst`` files. Deploy to GitHub Pages ~~~~~~~~~~~~~~~~~~~~~~ There is no separate deploy step. GitHub Pages is configured to serve the ``docs/`` directory of the master branch, so pushing a commit that contains the rebuilt ``docs/`` publishes the site.