-
-
Notifications
You must be signed in to change notification settings - Fork 91
cli_parse_args issue #391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
@kschwab Could you please take a look? |
Hi @Sanchoyzer, the above is expected. When What is likely misleading is the output, specifically the "pytest" references:
In reality, both parsers will run and parse the same CLI args, in this case
Which of course, when More broadly speaking, the issue you're hitting is running multiple parsers in a single app. Parser A will fail because it doesn't have Parser B args, and Parser B will fail because it doesn't have Parser A args. To share the same CLI args, you'll need to merge the two parsers together. This is covered in the docs under Integrating with Existing Parsers. For your case, I believe the below should work: import pytest
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(cli_parse_args=True)
MY_VAR: str = ""
cli_settings = CliSettingsSource(
Settings,
root_parser=pytest.Parser(_ispytest=True),
parse_args_method=pytest.Parser.parse,
add_argument_method=pytest.Parser.addoption,
add_argument_group_method=pytest.Parser.getgroup,
add_parser_method=None,
add_subparsers_method=None,
formatter_class=None,
)
conf = Settings(_cli_settings_source=cli_settings(args=True)) You should then see |
Hey, @kschwab. Thanks for your answer, it looks really cool. By the way, it might be useful additional information for the documentation I've tried the solution, and it works for
It seems that the pytest parser replaced its own arguments instead of adding new (or something like that) |
Hey @Sanchoyzer, I think you have to use the hooks with pytest to get it to work properly. Try the following in your import pytest
from settings import Settings
from pydantic_settings import CliSettingsSource
_cli_settings: CliSettingsSource
def pytest_addoption(parser):
global _cli_settings
_cli_settings = CliSettingsSource(
Settings,
root_parser=parser,
parse_args_method=pytest.Parser.parse,
add_argument_method=pytest.Parser.addoption,
add_argument_group_method=pytest.Parser.getgroup,
add_parser_method=None,
add_subparsers_method=None,
formatter_class=None,
)
conf: Settings
def pytest_configure(config):
global conf
conf = Settings(_cli_settings_source=_cli_settings(args=config.args)) And then in your from pydantic import Field
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
MY_STR: str = Field("it's me", description='This is my str var')
MY_INT: int = Field(23, description='This is my int var') Locally, I get:
and |
Hey, @kschwab . Thanks for your message. Your code works as expected, but I'm afraid that it isn't so optimal to create the The thing is that we usually have the settings file, like from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(cli_parse_args=True)
MY_VAR: str = ""
conf = Settings() and we use it in many files for business logic, like from settings import conf
def handler(request):
if request.params.get('my_var') != conf.MY_VAR:
... or in tests, like from settings import conf
@pytest.fixture(scope='session', autouse=True)
def settings():
conf.MY_VAR = 'qwerty' that's why the |
I see. This is really more of an app specific issue. i.e., in the business logic case, In import sys
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(cli_parse_args=True)
MY_VAR: str = ""
conf = Settings() if 'pytest' not in sys.argv[0] else None In import pytest
import settings
from pydantic_settings import CliSettingsSource
_cli_settings: CliSettingsSource
def pytest_addoption(parser):
global _cli_settings
_cli_settings = CliSettingsSource(
settings.Settings,
root_parser=parser,
parse_args_method=pytest.Parser.parse,
add_argument_method=pytest.Parser.addoption,
add_argument_group_method=pytest.Parser.getgroup,
add_parser_method=None,
add_subparsers_method=None,
formatter_class=None,
)
def pytest_configure(config):
settings.conf = settings.Settings(_cli_settings_source=_cli_settings(args=config.args)) Of course, if the intent is to not to integrate with the pytest CLI (i.e. import sys
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(cli_parse_args='pytest' not in sys.argv[0])
MY_VAR: str = ""
conf = Settings() |
Hey, @kschwab , thanks a lot, this awesome solution is what I need: SettingsConfigDict(cli_parse_args='pytest' not in sys.argv[0]) |
Libs
Code
project/settings.py
project/tests/conftest.py
Run pytest
Let's add
cli_parse_args
Run pytest again
Summary
It seems that using
cli_parse_args
overrides all other options, and it doesn't look goodThe text was updated successfully, but these errors were encountered: