Skip to content
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

Add CLI Settings Source #214

Merged
merged 65 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
0aedfa2
Initial commit.
kschwab Jan 18, 2024
9d22a39
Draft complete. Needs testing.
kschwab Jan 19, 2024
2ef8473
Subcommand union discrimination not strong enough.
kschwab Jan 20, 2024
0ce72ac
Updated subcommands.
kschwab Jan 21, 2024
ce2c425
Initial tests.
kschwab Jan 21, 2024
5795c7c
Remove use_attribute_docstrings.
kschwab Jan 22, 2024
3215797
Various updates.
kschwab Jan 23, 2024
6085008
Merge branch 'main' into support_cli_source
kschwab Jan 27, 2024
dd5bf6e
Docs with various fixes and updates.
kschwab Jan 28, 2024
abc1095
Use Union.
kschwab Jan 28, 2024
fcc4d2d
Test and doc updates.
kschwab Jan 29, 2024
783d1c9
Python 3.8 and 3.9 argparse help text fixes.
kschwab Jan 29, 2024
ff5b7ed
More Python 3.8 and 3.9 test fixes.
kschwab Jan 29, 2024
7ea4c97
More Python 3.8 and 3.9 fixes.
kschwab Jan 29, 2024
d55d699
Python 3.8 dict union fix.
kschwab Jan 29, 2024
cb3b250
Mypy lint fix?
kschwab Jan 29, 2024
d1692a3
Add test case for nested dictionaries.
kschwab Jan 30, 2024
b107d91
Additional test cases.
kschwab Jan 30, 2024
7e7713e
Python 3.8 and 3.9 format fixes.
kschwab Jan 30, 2024
ca39690
Fix for typing vs typing_extensions Literal.
kschwab Jan 30, 2024
09bdce2
Add test case for typing vs typing_extensions Literal.
kschwab Jan 30, 2024
20a83f1
Mypy fix for _metavar_format function update.
kschwab Jan 31, 2024
f4bf3ee
Update pydantic_settings/sources.py
hramezani Jan 31, 2024
3a4949c
Handle Representation from pydantic._internal and pydantic.v1.
kschwab Jan 31, 2024
0483380
Fix for _cli_parse_args to cli_parse_args.
kschwab Jan 31, 2024
ff018ce
Complex test cases and fixes for env parse none str.
kschwab Jan 31, 2024
a8d15b1
Remove empty groups from parsing and help text.
kschwab Feb 6, 2024
90403ee
Lint fix.
kschwab Feb 6, 2024
61a4745
Lint and formatting.
kschwab Feb 6, 2024
c38ed6a
Lint again.
kschwab Feb 6, 2024
cb9c1c3
Enum support and strip annotations.
kschwab Feb 7, 2024
a984f32
Update pydantic_settings/main.py
kschwab Feb 17, 2024
8470930
Initial updates for external parser support.
kschwab Mar 4, 2024
0eaba11
Doc updates.
kschwab Mar 4, 2024
336108f
Add tuple type.
kschwab Mar 4, 2024
ae6fa73
Doc and test prep for literals and enums.
kschwab Mar 5, 2024
128f94e
Merge branch 'main' into support_cli_source
kschwab Mar 12, 2024
9679c10
Enable CLI enum support.
kschwab Mar 12, 2024
197114d
Exception validation and skip doc tests using --help.
kschwab Mar 12, 2024
431bcb1
Python 3.8 fix.
kschwab Mar 12, 2024
0eeee79
Lint fixes.
kschwab Mar 12, 2024
e04fa93
Lint fixes.
kschwab Mar 12, 2024
7d735ab
Mypy fix.
kschwab Mar 12, 2024
1ce348a
Move integration doc section down.
kschwab Mar 12, 2024
16feca7
Fix unioned dicts and hide_none_type metavar formatting.
kschwab Mar 24, 2024
309f1c6
Test case updates.
kschwab Mar 24, 2024
04c51ca
Add string inference.
kschwab Mar 24, 2024
0263f0d
Merge branch 'main' into support_cli_source
hramezani Mar 28, 2024
385b770
Remove v1 import.
kschwab Mar 29, 2024
4ee2bbd
Docs fix.
kschwab Mar 29, 2024
58a3d8f
Add support for alias fields.
kschwab May 19, 2024
1b41f17
Add support for pydantic dataclasses.
kschwab May 23, 2024
8606f78
Add support for CLISettingsSource prioritization.
kschwab May 23, 2024
488489e
Merge branch 'main' into support_cli_source
kschwab May 23, 2024
155ffe3
Fixes.
kschwab May 23, 2024
5f430b0
Fixes.
kschwab May 23, 2024
53163a8
Lint.
kschwab May 23, 2024
1f62254
Lint.
kschwab May 23, 2024
0016a5e
Lint.
kschwab May 23, 2024
b555ad1
Add support for case-insensitive matching.
kschwab May 24, 2024
3c27f27
Lint.
kschwab May 24, 2024
a3fe71c
Lint.
kschwab May 24, 2024
a1688c7
Add CliSettingsSource prioritization doc.
kschwab May 24, 2024
56146e9
Update help text and formalize cli_parse_none_str.
kschwab Jun 2, 2024
d3f2de2
Add help text for default factory.
kschwab Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions pydantic_settings/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from .main import BaseSettings, SettingsConfigDict
from .sources import (
CliPositionalArg,
CliSettingsSource,
CliSubCommand,
DotEnvSettingsSource,
EnvSettingsSource,
InitSettingsSource,
Expand All @@ -12,6 +15,9 @@
'BaseSettings',
'DotEnvSettingsSource',
'EnvSettingsSource',
'CliSettingsSource',
'CliSubCommand',
'CliPositionalArg',
'InitSettingsSource',
'PydanticBaseSettingsSource',
'SecretsSettingsSource',
Expand Down
57 changes: 57 additions & 0 deletions pydantic_settings/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from .sources import (
ENV_FILE_SENTINEL,
CliSettingsSource,
DotEnvSettingsSource,
DotenvType,
EnvSettingsSource,
Expand All @@ -27,6 +28,11 @@ class SettingsConfigDict(ConfigDict, total=False):
env_ignore_empty: bool
env_nested_delimiter: str | None
env_parse_none_str: str | None
cli_prog_name: str | None
cli_parse_args: bool | list[str] | None
cli_hide_none_type: bool
cli_avoid_json: bool
cli_enforce_required: bool
secrets_dir: str | Path | None


Expand Down Expand Up @@ -59,6 +65,13 @@ class BaseSettings(BaseModel):
_env_nested_delimiter: The nested env values delimiter. Defaults to `None`.
_env_parse_none_str: The env string value that should be parsed (e.g. "null", "void", "None", etc.)
into `None` type(None). Defaults to `None` type(None), which means no parsing should occur.
_cli_prog_name: The CLI program name to display in help text. Defaults to `None` if _cli_parse_args is `None`.
Otherwse, defaults to sys.argv[0].
_cli_parse_args: The list of CLI arguments to parse. Defaults to None.
If set to `True`, defaults to sys.argv[1:].
_cli_hide_none_type: Hide NoneType values in CLI help text. Defaults to `False`.
kschwab marked this conversation as resolved.
Show resolved Hide resolved
_cli_avoid_json: Avoid complex JSON objects in CLI help text. Defaults to `False`.
_cli_enforce_required: Enforce required fields at the CLI. Defaults to `False`.
_secrets_dir: The secret files directory. Defaults to `None`.
"""

Expand All @@ -71,6 +84,11 @@ def __init__(
_env_ignore_empty: bool | None = None,
_env_nested_delimiter: str | None = None,
_env_parse_none_str: str | None = None,
_cli_prog_name: str | None = None,
_cli_parse_args: bool | list[str] | None = None,
_cli_hide_none_type: bool | None = None,
_cli_avoid_json: bool | None = None,
_cli_enforce_required: bool | None = None,
_secrets_dir: str | Path | None = None,
**values: Any,
) -> None:
Expand All @@ -85,6 +103,11 @@ def __init__(
_env_ignore_empty=_env_ignore_empty,
_env_nested_delimiter=_env_nested_delimiter,
_env_parse_none_str=_env_parse_none_str,
_cli_prog_name=_cli_prog_name,
_cli_parse_args=_cli_parse_args,
_cli_hide_none_type=_cli_hide_none_type,
_cli_avoid_json=_cli_avoid_json,
_cli_enforce_required=_cli_enforce_required,
_secrets_dir=_secrets_dir,
)
)
Expand Down Expand Up @@ -123,6 +146,11 @@ def _settings_build_values(
_env_ignore_empty: bool | None = None,
_env_nested_delimiter: str | None = None,
_env_parse_none_str: str | None = None,
_cli_prog_name: str | None = None,
_cli_parse_args: bool | list[str] | None = None,
_cli_hide_none_type: bool | None = None,
_cli_avoid_json: bool | None = None,
_cli_enforce_required: bool | None = None,
_secrets_dir: str | Path | None = None,
) -> dict[str, Any]:
# Determine settings config values
Expand All @@ -143,10 +171,32 @@ def _settings_build_values(
env_parse_none_str = (
_env_parse_none_str if _env_parse_none_str is not None else self.model_config.get('env_parse_none_str')
)

cli_prog_name = _cli_prog_name if _cli_prog_name is not None else self.model_config.get('cli_prog_name')
cli_parse_args = _cli_parse_args if _cli_parse_args is not None else self.model_config.get('cli_parse_args')
cli_hide_none_type = (
_cli_hide_none_type if _cli_hide_none_type is not None else self.model_config.get('cli_hide_none_type')
)
cli_avoid_json = _cli_avoid_json if _cli_avoid_json is not None else self.model_config.get('cli_avoid_json')
cli_enforce_required = (
_cli_enforce_required
if _cli_enforce_required is not None
else self.model_config.get('cli_enforce_required')
)

secrets_dir = _secrets_dir if _secrets_dir is not None else self.model_config.get('secrets_dir')

# Configure built-in sources
init_settings = InitSettingsSource(self.__class__, init_kwargs=init_kwargs)
cli_settings = CliSettingsSource(
self.__class__,
cli_prog_name=cli_prog_name,
cli_parse_args=cli_parse_args,
cli_parse_none_str=env_parse_none_str,
cli_hide_none_type=cli_hide_none_type,
cli_avoid_json=cli_avoid_json,
cli_enforce_required=cli_enforce_required,
)
env_settings = EnvSettingsSource(
self.__class__,
case_sensitive=case_sensitive,
Expand Down Expand Up @@ -177,6 +227,8 @@ def _settings_build_values(
dotenv_settings=dotenv_settings,
file_secret_settings=file_secret_settings,
)
if _cli_parse_args:
sources = (cli_settings,) + sources
kschwab marked this conversation as resolved.
Show resolved Hide resolved
if sources:
return deep_update(*reversed([source() for source in sources]))
else:
Expand All @@ -195,6 +247,11 @@ def _settings_build_values(
env_ignore_empty=False,
env_nested_delimiter=None,
env_parse_none_str=None,
cli_prog_name=None,
cli_parse_args=None,
cli_hide_none_type=False,
cli_avoid_json=False,
cli_enforce_required=False,
secrets_dir=None,
protected_namespaces=('model_', 'settings_'),
)