Mercurial > public > mercurial-scm > hg-stable
comparison rust/hg-cpython/src/filepatterns.rs @ 42350:94f3a73b6672
rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
This change adds the `rust-cpython` interface for top-level functions and
exceptions in the filepatterns module.
Contrary to the Python implementation, this tries to have finer-grained
exceptions to allow for better readability and flow control down the line.
Differential Revision: https://phab.mercurial-scm.org/D6272
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Fri, 17 May 2019 09:36:29 -0400 |
parents | rust/hg-cpython/src/ancestors.rs@060c030c9993 |
children | 9609430d3625 |
comparison
equal
deleted
inserted
replaced
42349:e8f3740cc067 | 42350:94f3a73b6672 |
---|---|
1 // filepatterns.rs | |
2 // | |
3 // Copyright 2019, Georges Racinet <gracinet@anybox.fr>, | |
4 // Raphaël Gomès <rgomes@octobus.net> | |
5 // | |
6 // This software may be used and distributed according to the terms of the | |
7 // GNU General Public License version 2 or any later version. | |
8 | |
9 //! Bindings for the `hg::filepatterns` module provided by the | |
10 //! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns` | |
11 //! and can be used as replacement for the the pure `filepatterns` Python module. | |
12 //! | |
13 use cpython::{ | |
14 exc, PyDict, PyErr, PyModule, PyResult, PyString, PyTuple, Python, | |
15 ToPyObject, | |
16 }; | |
17 use hg::{build_single_regex, read_pattern_file, PatternTuple}; | |
18 use exceptions::{ | |
19 PatternError, | |
20 PatternFileError, | |
21 }; | |
22 | |
23 /// Rust does not like functions with different return signatures. | |
24 /// The 3-tuple version is always returned by the hg-core function, | |
25 /// the (potential) conversion is handled at this level since it is not likely | |
26 /// to have any measurable impact on performance. | |
27 /// | |
28 /// The Python implementation passes a function reference for `warn` instead | |
29 /// of a boolean that is used to emit warnings while parsing. The Rust | |
30 /// implementation chooses to accumulate the warnings and propagate them to | |
31 /// Python upon completion. See the `readpatternfile` function in `match.py` | |
32 /// for more details. | |
33 fn read_pattern_file_wrapper( | |
34 py: Python, | |
35 file_path: String, | |
36 warn: bool, | |
37 source_info: bool, | |
38 ) -> PyResult<PyTuple> { | |
39 match read_pattern_file(file_path, warn) { | |
40 Ok((patterns, warnings)) => { | |
41 if source_info { | |
42 return Ok((patterns, warnings).to_py_object(py)); | |
43 } | |
44 let itemgetter = |x: &PatternTuple| x.0.to_py_object(py); | |
45 let results: Vec<PyString> = | |
46 patterns.iter().map(itemgetter).collect(); | |
47 Ok((results, warnings).to_py_object(py)) | |
48 } | |
49 Err(e) => Err(PatternFileError::pynew(py, e)), | |
50 } | |
51 } | |
52 | |
53 fn build_single_regex_wrapper( | |
54 py: Python, | |
55 kind: String, | |
56 pat: String, | |
57 globsuffix: String, | |
58 ) -> PyResult<PyString> { | |
59 match build_single_regex( | |
60 kind.as_ref(), | |
61 pat.as_bytes(), | |
62 globsuffix.as_bytes(), | |
63 ) { | |
64 Ok(regex) => match String::from_utf8(regex) { | |
65 Ok(regex) => Ok(regex.to_py_object(py)), | |
66 Err(e) => Err(PyErr::new::<exc::UnicodeDecodeError, _>( | |
67 py, | |
68 e.to_string(), | |
69 )), | |
70 }, | |
71 Err(e) => Err(PatternError::pynew(py, e)), | |
72 } | |
73 } | |
74 | |
75 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> { | |
76 let dotted_name = &format!("{}.filepatterns", package); | |
77 let m = PyModule::new(py, dotted_name)?; | |
78 | |
79 m.add(py, "__package__", package)?; | |
80 m.add( | |
81 py, | |
82 "__doc__", | |
83 "Patterns files parsing - Rust implementation", | |
84 )?; | |
85 m.add( | |
86 py, | |
87 "build_single_regex", | |
88 py_fn!( | |
89 py, | |
90 build_single_regex_wrapper( | |
91 kind: String, | |
92 pat: String, | |
93 globsuffix: String | |
94 ) | |
95 ), | |
96 )?; | |
97 m.add( | |
98 py, | |
99 "read_pattern_file", | |
100 py_fn!( | |
101 py, | |
102 read_pattern_file_wrapper( | |
103 file_path: String, | |
104 warn: bool, | |
105 source_info: bool | |
106 ) | |
107 ), | |
108 )?; | |
109 | |
110 let sys = PyModule::import(py, "sys")?; | |
111 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?; | |
112 sys_modules.set_item(py, dotted_name, &m)?; | |
113 | |
114 Ok(m) | |
115 } |