-
-
Notifications
You must be signed in to change notification settings - Fork 64
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
Use SettingsErrors when file can't be used as source #432
base: main
Are you sure you want to change the base?
Conversation
Thanks @l00ptr for this PR. I think this will introduce a breaking change because some people's code might depend on the old error. This change can be made in the next major release |
ok, i think i can try to help on that topic. I can start writing a simple test case for invalid yaml file and handle json decoding error. |
It seems to me that the change would not break users code because
so anybody doing: try:
s = Settings()
except ValueError:
# handle exception here
... would still have their code working. This could be checked in tests added here. Or did you have something else in mind @hramezani ? |
pydantic_settings/sources.py
Outdated
try: | ||
vars.update(self._read_file(file_path)) | ||
except ValueError as e: | ||
raise SettingsError(f'Parsing error encountered for {file_path}: {e}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we could improve the user experience by explicitly checking that the result of file read is a dict because otherwise, (e.g. in added tests), the ValueError
, which is about dict.update()
, is not very informative:
>>> d
{}
>>> d.update("abc")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Also, I realize that calling dict.update()
with an iterable is also valid and so loading a YAML like:
- - x
- y
- - a
- b
would work; not sure if it's expected? But maybe it's another issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can probably check if the object returned by self._read_file
is a dict or not and handle that specific case.
There are also a lot of cases where reading from (toml, yaml,...) file will raise ValueError. Eg:
import tomli
tomli.loads("demo =\ndemo2 =")
Will throw a tomli.TOMLDecodeError :/ finally i think we should simply keep the ValueError
.
Thanks @dlax for the explanation. However, it is still a breaking change because some people's code might depend on the error type
|
@l00ptr Thanks for your update and for adding tests. As I mentioned above, we can't merge this PR because of breaking changes. but you've added some good tests.
|
e49dbbd
to
4a9f0c3
Compare
try: | ||
settings = self._read_file(file_path) | ||
except ValueError as e: | ||
raise SettingsError(f'Failed to parse settings from {file_path}, {e}') | ||
if not isinstance(settings, dict): | ||
raise SettingsError( | ||
f'Failed to parse settings from {file_path}, expecting an object (valid dictionnary)' | ||
) | ||
vars.update(settings) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@l00ptr Thanks for updating this.
As I mentioned before we can't merge this PR because it will introduce a breaking change. So, we have 2 options here:
1- Keep only the tests that test the current behavior(ValueError) and revert to raising SettingsError
; then, we can merge the tests only.
2- Keep the PR open until V3
and merge it before V3
.
I would prefer option 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hramezani i splitted those changes on 3 commits, let me know if i should create a specific MR for the 2 last commits (about SettingsError) and only keep the first one here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@l00ptr no need for a new PR.
Then we have to wait to merge it on V3
. I will add a v3
label to the PR to not merge it until v3
Some file formats (at least yaml) allow to represent non dictionnary values. In such situation we can't add the values read from those files. Instead of raising a ValueError, we now raise a SettingsError and indicate we can't parse the related config file.
4a9f0c3
to
55ff1e5
Compare
We verify the loaded settings from files is dict, otherwise we raise a SettingsError. With that change, we make Pydantic fails a bit faster.
55ff1e5
to
c6e6fb9
Compare
Some file formats (at least yaml) allow to represent non dictionnary values. In such situation we can't add the values read from those files. Instead of raising a ValueError, we now raise a SettingsError and indicate we can't parse the related config file.