@@ -13,123 +13,112 @@ use pyo3::create_exception;
1313create_exception ! ( rustfluent, ParserError , pyo3:: exceptions:: PyException ) ;
1414
1515#[ pymodule]
16- fn rustfluent ( m : & Bound < ' _ , PyModule > ) -> PyResult < ( ) > {
17- m. add_class :: < Bundle > ( ) ?;
18- m. add ( "ParserError" , m. py ( ) . get_type :: < ParserError > ( ) ) ?;
19- Ok ( ( ) )
20- }
21-
22- #[ pyclass]
23- struct Bundle {
24- bundle : FluentBundle < FluentResource > ,
25- }
16+ mod rustfluent {
17+ use super :: * ;
2618
27- #[ pymethods]
28- impl Bundle {
29- #[ new]
30- #[ pyo3( signature = ( language, ftl_filenames, strict=false ) ) ]
31- fn new ( language : & str , ftl_filenames : & ' _ Bound < ' _ , PyList > , strict : bool ) -> PyResult < Self > {
32- let langid: LanguageIdentifier = language. parse ( ) . expect ( "Parsing failed" ) ;
33- let mut bundle = FluentBundle :: new_concurrent ( vec ! [ langid] ) ;
19+ #[ pymodule_export]
20+ use super :: ParserError ;
3421
35- for file_path in ftl_filenames . iter ( ) {
36- let path_string = file_path . to_string ( ) ;
37- let contents = fs :: read_to_string ( path_string )
38- . map_err ( |_| PyFileNotFoundError :: new_err ( file_path . to_string ( ) ) ) ? ;
22+ # [ pyclass ]
23+ struct Bundle {
24+ bundle : FluentBundle < FluentResource > ,
25+ }
3926
40- let resource = match FluentResource :: try_new ( contents) {
41- Ok ( resource) => resource,
42- Err ( _) if strict => {
43- return Err ( ParserError :: new_err ( format ! (
44- "Error when parsing {file_path}."
27+ #[ pymethods]
28+ impl Bundle {
29+ #[ new]
30+ #[ pyo3( signature = ( language, ftl_filenames, strict=false ) ) ]
31+ fn new (
32+ language : & str ,
33+ ftl_filenames : & ' _ Bound < ' _ , PyList > ,
34+ strict : bool ,
35+ ) -> PyResult < Self > {
36+ let langid: LanguageIdentifier = match language. parse ( ) {
37+ Ok ( langid) => langid,
38+ Err ( _) => {
39+ return Err ( PyValueError :: new_err ( format ! (
40+ "Invalid language: '{language}'"
4541 ) ) ) ;
4642 }
47- Err ( error) => {
48- // The first element of the error is the parsed resource, minus any
49- // invalid messages.
50- error. 0
51- }
5243 } ;
53- bundle. add_resource_overriding ( resource) ;
54- }
44+ let mut bundle = FluentBundle :: new_concurrent ( vec ! [ langid] ) ;
5545
56- Ok ( Self { bundle } )
57- }
46+ for file_path in ftl_filenames. iter ( ) {
47+ let path_string = file_path. to_string ( ) ;
48+ let contents = fs:: read_to_string ( path_string)
49+ . map_err ( |_| PyFileNotFoundError :: new_err ( file_path. to_string ( ) ) ) ?;
50+
51+ let resource = match FluentResource :: try_new ( contents) {
52+ Ok ( resource) => resource,
53+ Err ( _) if strict => {
54+ return Err ( ParserError :: new_err ( format ! (
55+ "Error when parsing {file_path}."
56+ ) ) ) ;
57+ }
58+ Err ( ( resource, _errors) ) => resource,
59+ } ;
60+ bundle. add_resource_overriding ( resource) ;
61+ }
5862
59- #[ pyo3( signature = ( identifier, variables=None , use_isolating=true ) ) ]
60- pub fn get_translation (
61- & mut self ,
62- identifier : & str ,
63- variables : Option < & Bound < ' _ , PyDict > > ,
64- use_isolating : bool ,
65- ) -> PyResult < String > {
66- self . bundle . set_use_isolating ( use_isolating) ;
63+ Ok ( Self { bundle } )
64+ }
6765
68- let msg = self
69- . bundle
70- . get_message ( identifier)
71- . ok_or_else ( || ( PyValueError :: new_err ( format ! ( "{identifier} not found" ) ) ) ) ?;
66+ #[ pyo3( signature = ( identifier, variables=None , use_isolating=true ) ) ]
67+ pub fn get_translation (
68+ & mut self ,
69+ identifier : & str ,
70+ variables : Option < & Bound < ' _ , PyDict > > ,
71+ use_isolating : bool ,
72+ ) -> PyResult < String > {
73+ self . bundle . set_use_isolating ( use_isolating) ;
7274
73- let mut errors = vec ! [ ] ;
74- let pattern = msg . value ( ) . ok_or_else ( || {
75- PyValueError :: new_err ( format ! ( "{identifier} - Message has no value." , ) )
76- } ) ?;
75+ let msg = self
76+ . bundle
77+ . get_message ( identifier )
78+ . ok_or_else ( || ( PyValueError :: new_err ( format ! ( "{identifier} not found" ) ) ) ) ?;
7779
78- let mut args = FluentArgs :: new ( ) ;
80+ let pattern = msg. value ( ) . ok_or_else ( || {
81+ PyValueError :: new_err ( format ! ( "{identifier} - Message has no value." , ) )
82+ } ) ?;
7983
80- if let Some ( variables) = variables {
81- for variable in variables {
82- // Make sure the variable key is a Python string,
83- // raising a TypeError if not.
84- let python_key = variable. 0 ;
85- if !python_key. is_instance_of :: < PyString > ( ) {
86- return Err ( PyTypeError :: new_err ( format ! (
87- "Variable key not a str, got {python_key}."
88- ) ) ) ;
89- }
90- let key = python_key. to_string ( ) ;
91- // Set the variable value as a string or integer,
92- // raising a TypeError if not.
93- let python_value = variable. 1 ;
94- if python_value. is_instance_of :: < PyString > ( ) {
95- args. set ( key, python_value. to_string ( ) ) ;
96- } else if python_value. is_instance_of :: < PyInt > ( ) {
97- match python_value. extract :: < i32 > ( ) {
98- Ok ( int_value) => {
99- args. set ( key, int_value) ;
100- }
101- _ => {
102- // The Python integer overflowed i32.
103- // Fall back to displaying the variable key as its value.
104- let fallback_value = key. clone ( ) ;
105- args. set ( key, fallback_value) ;
106- }
84+ let mut args = FluentArgs :: new ( ) ;
85+
86+ if let Some ( variables) = variables {
87+ for ( python_key, python_value) in variables {
88+ // Make sure the variable key is a Python string,
89+ // raising a TypeError if not.
90+ if !python_key. is_instance_of :: < PyString > ( ) {
91+ return Err ( PyTypeError :: new_err ( format ! (
92+ "Variable key not a str, got {python_key}."
93+ ) ) ) ;
10794 }
108- } else if python_value. is_instance_of :: < PyDate > ( ) {
109- // Display the Python date as YYYY-MM-DD.
110- match python_value. extract :: < NaiveDate > ( ) {
111- Ok ( chrono_date) => {
112- args. set ( key, chrono_date. format ( "%Y-%m-%d" ) . to_string ( ) ) ;
113- }
114- _ => {
115- // Could not convert.
116- // Fall back to displaying the variable key as its value.
117- let fallback_value = key. clone ( ) ;
118- args. set ( key, fallback_value) ;
119- }
95+ let key = python_key. to_string ( ) ;
96+ // Set the variable value as a string or integer,
97+ // raising a TypeError if not.
98+ if python_value. is_instance_of :: < PyString > ( ) {
99+ args. set ( key, python_value. to_string ( ) ) ;
100+ } else if python_value. is_instance_of :: < PyInt > ( )
101+ && let Ok ( int_value) = python_value. extract :: < i32 > ( )
102+ {
103+ args. set ( key, int_value) ;
104+ } else if python_value. is_instance_of :: < PyDate > ( )
105+ && let Ok ( chrono_date) = python_value. extract :: < NaiveDate > ( )
106+ {
107+ args. set ( key, chrono_date. format ( "%Y-%m-%d" ) . to_string ( ) ) ;
108+ } else {
109+ // The variable value was of an unsupported type.
110+ // Fall back to displaying the variable key as its value.
111+ let fallback_value = key. clone ( ) ;
112+ args. set ( key, fallback_value) ;
120113 }
121- } else {
122- // The variable value was of an unsupported type.
123- // Fall back to displaying the variable key as its value.
124- let fallback_value = key. clone ( ) ;
125- args. set ( key, fallback_value) ;
126114 }
127115 }
128- }
129116
130- let value = self
131- . bundle
132- . format_pattern ( pattern, Some ( & args) , & mut errors) ;
133- Ok ( value. to_string ( ) )
117+ let mut errors = vec ! [ ] ;
118+ let value = self
119+ . bundle
120+ . format_pattern ( pattern, Some ( & args) , & mut errors) ;
121+ Ok ( value. to_string ( ) )
122+ }
134123 }
135124}
0 commit comments