-
Notifications
You must be signed in to change notification settings - Fork 3
Enable safe fallback when loading single values #147
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
base: main
Are you sure you want to change the base?
Changes from all commits
cb471dd
f9c2dc4
b9476bc
6570747
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| import json | ||
| import typing | ||
| from abc import ABC, abstractmethod | ||
| from collections.abc import Sequence | ||
| from collections.abc import Callable, Sequence | ||
| from dataclasses import dataclass, replace | ||
| from os import PathLike | ||
| from pathlib import Path | ||
|
|
@@ -26,6 +26,7 @@ class Format(ABC): | |
|
|
||
| suffix: str = '' #: the default file path suffix for a configuration file of this Format | ||
| encoding: str = 'utf-8' #: the default text encoding for reading from binary I/O | ||
| value_fallback: Callable[[str], typing.Any] = str #: the fallback 'factory' for unparseable single values | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternatively, we could so something like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Realistically, what do we expect this callable to be/do? Are there many more sane options than I'm thinking this might be too much flexibility for our needs.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, In hindsight, |
||
|
|
||
| def load(self, fp: typing.TextIO) -> typing.Any: | ||
| return self.loads(fp.read()) | ||
|
|
@@ -38,6 +39,14 @@ def loadf(self, fpath: str | PathLike, encoding: str | None = None) -> typing.An | |
| with Path(fpath).open('rt', encoding=encoding or self.encoding) as fp: | ||
| return self.load(fp) | ||
|
|
||
| def loadv(self, string: str) -> typing.Any: | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure this implementation is entirely kosher, thoughts welcome 🤔 This combined with calling it where singular values are expected does actually fairly transparently solve the issue.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This relies on the formats doing the proper translating of all possible relevant parsing errors back to I hate to bring this up, but could this be a good place for a custom exception type?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The only ones not supporting the fallback themselves are JSON and TOML, both using a fairly sane exception hierachy where a parsing failure will raise something that quacks
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I was led astray by the complex Exception hierarchy of PyYAML (see for example yaml/pyyaml#750). If the parsers that need it raise It feels a bit ad-hoc though. If exception types are a part of the
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah yes, documentation of the assumptions here makes sense, let's at least make that clear.
|
||
| try: | ||
| # hope the format implementation will be able to read string as a value formatted value | ||
| return self.loads(string) | ||
| except ValueError: | ||
| # use the fallback otherwise | ||
| return self.value_fallback(string) | ||
|
|
||
| def dump(self, value: typing.Any, fp: typing.TextIO) -> None: | ||
| fp.write(self.dumps(value)) | ||
|
|
||
|
|
||
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.
Changing this needs a test