Skip to content

A brief usage example of how click and pydantic interact would be helpful #1

@ricosaurus

Description

@ricosaurus

I am interested in configuring command-line parsing from pydantic models -- this could be very useful as I switched from standard dataclasses to pydantic, and would love to integrate these models with command line parsing. However I am having a bit of trouble trying to figure out intended use from your tests.

For example, if I attempt to replicate your test_basic_field function:

import sys
from typing import Dict, List, Tuple, Type, Any
from pydantic import BaseModel, BaseSettings

from cyto.settings import autofill

# from cyto/tests/conftest.py
class Argv:
    def __init__(self, monkeypatch: Any) -> None:
        self._monkeypatch = monkeypatch
        self._sys_argv_first = sys.argv[0]
        self.clear()

    def assign(self, *args: Any) -> None:
        """Clear existing arguments first and append the given ones."""
        self.clear()
        self.append(*args)

    def clear(self) -> None:
        self._argv = [self._sys_argv_first]
        self._update()

    def append(self, *args: Any) -> None:
        self._argv += args
        self._update()

    def _update(self) -> None:
        self._monkeypatch.setattr(sys, "argv", self._argv)

# from cyto/tests/settings/conftest.py
class MyTunesSettings(BaseSettings):
    theme: str
    volume: int = 80
    shuffle: bool = True
    translations: Dict[str, str] = {
        "repeat": "repetir",
        "shuffle": "barajar",
    }

# from cyto/tests/settings/sources/test_source_cli.py
def test_basic_field(
    mytunes_settings: Type[MyTunesSettings],
    argv: Argv,
) -> None:
    
    # Set the required field
    argv.append("--theme", "dark")
    settings = mytunes_settings()
    assert settings.theme == "dark"
    # Non-required fields get their default value
    assert settings.volume == 80
    assert settings.shuffle is True
    assert settings.translations == {
        "repeat": "repetir",
        "shuffle": "barajar",
    }
....

presumably I could create a mytunes_settings arg with

mytunes_settings = autofill(name="mytunes")(MyTunesSettings)

but I haven't figured out what the 'monkeypatch' arg for Argv should be, eg how to construct argv. Taking a stab at it, since it requires setattr that can manipulate sys.argv:

class Patch:
    def setattr(self, obj, k, v):
        setattr(obj, k, v)
    
monkeypatch = Patch()

mytunes_settings = autofill(name="mytunes")(MyTunesSettings)
argv = Argv(monkeypatch)
argv.append("--theme", "dark")
settings = mytunes_settings()
assert settings.theme == 'dark'

print(settings)

theme='dark' volume=80 shuffle=True translations={'repeat': 'repetir', 'shuffle': 'barajar'}

gets me started, but just a toy example would be immensely helpful! I'll look forward to integrating cyto.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions