Skip to content

Commit a5c1309

Browse files
committed
Provide choice of how strict to be with errors
1 parent 3dc1946 commit a5c1309

File tree

5 files changed

+38
-17
lines changed

5 files changed

+38
-17
lines changed

README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,16 @@ bundle = rustfluent.Bundle(
6767

6868
#### Parameters
6969

70-
| Name | Type | Description |
71-
|-------------|-------------|-------------------------------------------------------------------------------------------------------------------------|
72-
| `language` | `str` | [Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier) for the language. |
73-
| `ftl_files` | `list[str]` | Full paths to the FTL files containing the translations. Entries in later files overwrite earlier ones. |
70+
| Name | Type | Description |
71+
|-------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
72+
| `language` | `str` | [Unicode Language Identifier](https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier) for the language. |
73+
| `ftl_files` | `list[str]` | Full paths to the FTL files containing the translations. Entries in later files overwrite earlier ones. |
74+
| `strict` | `bool`, optional | In strict mode, a `ValueError` will be raised if there are any errors in the file. In non-strict mode, invalid Fluent messages will be excluded from the Bundle. |
7475

7576
#### Raises
7677

7778
- `FileNotFoundError` if any of the FTL files could not be found.
78-
- `ValueError` if any of the FTL files contain errors.
79+
- `ValueError` if any of the FTL files contain errors (strict mode only).
7980

8081
### `Bundle.get_translation`
8182

src/lib.rs

+14-8
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ struct Bundle {
2121
#[pymethods]
2222
impl Bundle {
2323
#[new]
24-
fn new(language: &str, ftl_filenames: &'_ Bound<'_, PyList>) -> PyResult<Self> {
24+
#[pyo3(signature = (language, ftl_filenames, strict=false))]
25+
fn new(language: &str, ftl_filenames: &'_ Bound<'_, PyList>, strict: bool) -> PyResult<Self> {
2526
let langid: LanguageIdentifier = language.parse().expect("Parsing failed");
2627
let mut bundle = FluentBundle::new_concurrent(vec![langid]);
2728

@@ -32,16 +33,21 @@ impl Bundle {
3233
Err(_) => return Err(PyFileNotFoundError::new_err(file_path.to_string())),
3334
};
3435

35-
let res = match FluentResource::try_new(contents) {
36-
Ok(res) => res,
36+
let resource = match FluentResource::try_new(contents) {
37+
Ok(resource) => resource,
3738
Err(error) => {
38-
return Err(PyValueError::new_err(format!(
39-
"{error:?} - Fluent file contains errors"
40-
)))
39+
if strict {
40+
return Err(PyValueError::new_err(format!(
41+
"{error:?} - Fluent file contains errors"
42+
)));
43+
} else {
44+
// The first element of the error is the parsed resource, minus any
45+
// invalid messages.
46+
error.0
47+
}
4148
}
4249
};
43-
44-
bundle.add_resource_overriding(res);
50+
bundle.add_resource_overriding(resource);
4551
}
4652

4753
Ok(Self { bundle })

src/rustfluent.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
class Bundle:
2-
def __init__(self, language: str, ftl_filenames: list[str]) -> None: ...
2+
def __init__(self, language: str, ftl_filenames: list[str], strict: bool = False) -> None: ...
33
def get_translation(self, identifier: str, variables: dict[str, str] | None = None) -> str: ...

tests/data/errors.ftl

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
bobbins
1+
invalid-message
2+
3+
valid-message = I'm valid.

tests/test_python_interface.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,18 @@ def test_file_not_found():
6666
fluent.Bundle("fr", [str(data_dir / "none.ftl")])
6767

6868

69-
def test_file_has_errors():
69+
@pytest.mark.parametrize("pass_strict_argument_explicitly", (True, False))
70+
def test_parses_other_parts_of_file_that_contains_errors_in_non_strict_mode(
71+
pass_strict_argument_explicitly,
72+
):
73+
kwargs = dict(strict=False) if pass_strict_argument_explicitly else {}
74+
75+
bundle = fluent.Bundle("fr", [str(data_dir / "errors.ftl")], **kwargs)
76+
translation = bundle.get_translation("valid-message")
77+
78+
assert translation == "I'm valid."
79+
80+
81+
def test_raises_value_error_on_file_that_contains_errors_in_strict_mode():
7082
with pytest.raises(ValueError):
71-
fluent.Bundle("fr", [str(data_dir / "errors.ftl")])
83+
fluent.Bundle("fr", [str(data_dir / "errors.ftl")], strict=True)

0 commit comments

Comments
 (0)