##// END OF EJS Templates
py3: send bytes from Rust-created warning patterns...
Raphaël Gomès -
r44096:dc4e74d0 default
parent child Browse files
Show More
@@ -1,137 +1,136 b''
1 // filepatterns.rs
1 // filepatterns.rs
2 //
2 //
3 // Copyright 2019, Georges Racinet <gracinet@anybox.fr>,
3 // Copyright 2019, Georges Racinet <gracinet@anybox.fr>,
4 // Raphaël Gomès <rgomes@octobus.net>
4 // Raphaël Gomès <rgomes@octobus.net>
5 //
5 //
6 // This software may be used and distributed according to the terms of the
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.
7 // GNU General Public License version 2 or any later version.
8
8
9 //! Bindings for the `hg::filepatterns` module provided by the
9 //! Bindings for the `hg::filepatterns` module provided by the
10 //! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns`
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
11 //! and can be used as replacement for the the pure `filepatterns` Python
12 //! module.
12 //! module.
13 //!
13 //!
14 use crate::exceptions::{PatternError, PatternFileError};
14 use crate::exceptions::{PatternError, PatternFileError};
15 use cpython::{
15 use cpython::{
16 PyBytes, PyDict, PyModule, PyObject, PyResult, PyString, PyTuple, Python,
16 PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
17 ToPyObject,
18 };
17 };
19 use hg::{
18 use hg::{
20 build_single_regex, read_pattern_file, utils::files::get_path_from_bytes,
19 build_single_regex, read_pattern_file, utils::files::get_path_from_bytes,
21 LineNumber, PatternTuple,
20 LineNumber, PatternTuple,
22 };
21 };
23 use std::path::PathBuf;
22 use std::path::PathBuf;
24
23
25 /// Rust does not like functions with different return signatures.
24 /// Rust does not like functions with different return signatures.
26 /// The 3-tuple version is always returned by the hg-core function,
25 /// The 3-tuple version is always returned by the hg-core function,
27 /// the (potential) conversion is handled at this level since it is not likely
26 /// the (potential) conversion is handled at this level since it is not likely
28 /// to have any measurable impact on performance.
27 /// to have any measurable impact on performance.
29 ///
28 ///
30 /// The Python implementation passes a function reference for `warn` instead
29 /// The Python implementation passes a function reference for `warn` instead
31 /// of a boolean that is used to emit warnings while parsing. The Rust
30 /// of a boolean that is used to emit warnings while parsing. The Rust
32 /// implementation chooses to accumulate the warnings and propagate them to
31 /// implementation chooses to accumulate the warnings and propagate them to
33 /// Python upon completion. See the `readpatternfile` function in `match.py`
32 /// Python upon completion. See the `readpatternfile` function in `match.py`
34 /// for more details.
33 /// for more details.
35 fn read_pattern_file_wrapper(
34 fn read_pattern_file_wrapper(
36 py: Python,
35 py: Python,
37 file_path: PyObject,
36 file_path: PyObject,
38 warn: bool,
37 warn: bool,
39 source_info: bool,
38 source_info: bool,
40 ) -> PyResult<PyTuple> {
39 ) -> PyResult<PyTuple> {
41 let bytes = file_path.extract::<PyBytes>(py)?;
40 let bytes = file_path.extract::<PyBytes>(py)?;
42 let path = get_path_from_bytes(bytes.data(py));
41 let path = get_path_from_bytes(bytes.data(py));
43 match read_pattern_file(path, warn) {
42 match read_pattern_file(path, warn) {
44 Ok((patterns, warnings)) => {
43 Ok((patterns, warnings)) => {
45 if source_info {
44 if source_info {
46 let itemgetter = |x: &PatternTuple| {
45 let itemgetter = |x: &PatternTuple| {
47 (PyBytes::new(py, &x.0), x.1, PyBytes::new(py, &x.2))
46 (PyBytes::new(py, &x.0), x.1, PyBytes::new(py, &x.2))
48 };
47 };
49 let results: Vec<(PyBytes, LineNumber, PyBytes)> =
48 let results: Vec<(PyBytes, LineNumber, PyBytes)> =
50 patterns.iter().map(itemgetter).collect();
49 patterns.iter().map(itemgetter).collect();
51 return Ok((results, warnings_to_py_bytes(py, &warnings))
50 return Ok((results, warnings_to_py_bytes(py, &warnings))
52 .to_py_object(py));
51 .to_py_object(py));
53 }
52 }
54 let itemgetter = |x: &PatternTuple| PyBytes::new(py, &x.0);
53 let itemgetter = |x: &PatternTuple| PyBytes::new(py, &x.0);
55 let results: Vec<PyBytes> =
54 let results: Vec<PyBytes> =
56 patterns.iter().map(itemgetter).collect();
55 patterns.iter().map(itemgetter).collect();
57 Ok(
56 Ok(
58 (results, warnings_to_py_bytes(py, &warnings))
57 (results, warnings_to_py_bytes(py, &warnings))
59 .to_py_object(py),
58 .to_py_object(py),
60 )
59 )
61 }
60 }
62 Err(e) => Err(PatternFileError::pynew(py, e)),
61 Err(e) => Err(PatternFileError::pynew(py, e)),
63 }
62 }
64 }
63 }
65
64
66 fn warnings_to_py_bytes(
65 fn warnings_to_py_bytes(
67 py: Python,
66 py: Python,
68 warnings: &[(PathBuf, Vec<u8>)],
67 warnings: &[(PathBuf, Vec<u8>)],
69 ) -> Vec<(PyString, PyBytes)> {
68 ) -> Vec<(PyBytes, PyBytes)> {
70 warnings
69 warnings
71 .iter()
70 .iter()
72 .map(|(path, syn)| {
71 .map(|(path, syn)| {
73 (
72 (
74 PyString::new(py, &path.to_string_lossy()),
73 PyBytes::new(py, &path.to_string_lossy().as_bytes()),
75 PyBytes::new(py, syn),
74 PyBytes::new(py, syn),
76 )
75 )
77 })
76 })
78 .collect()
77 .collect()
79 }
78 }
80
79
81 fn build_single_regex_wrapper(
80 fn build_single_regex_wrapper(
82 py: Python,
81 py: Python,
83 kind: PyObject,
82 kind: PyObject,
84 pat: PyObject,
83 pat: PyObject,
85 globsuffix: PyObject,
84 globsuffix: PyObject,
86 ) -> PyResult<PyBytes> {
85 ) -> PyResult<PyBytes> {
87 match build_single_regex(
86 match build_single_regex(
88 kind.extract::<PyBytes>(py)?.data(py),
87 kind.extract::<PyBytes>(py)?.data(py),
89 pat.extract::<PyBytes>(py)?.data(py),
88 pat.extract::<PyBytes>(py)?.data(py),
90 globsuffix.extract::<PyBytes>(py)?.data(py),
89 globsuffix.extract::<PyBytes>(py)?.data(py),
91 ) {
90 ) {
92 Ok(regex) => Ok(PyBytes::new(py, &regex)),
91 Ok(regex) => Ok(PyBytes::new(py, &regex)),
93 Err(e) => Err(PatternError::pynew(py, e)),
92 Err(e) => Err(PatternError::pynew(py, e)),
94 }
93 }
95 }
94 }
96
95
97 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
96 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
98 let dotted_name = &format!("{}.filepatterns", package);
97 let dotted_name = &format!("{}.filepatterns", package);
99 let m = PyModule::new(py, dotted_name)?;
98 let m = PyModule::new(py, dotted_name)?;
100
99
101 m.add(py, "__package__", package)?;
100 m.add(py, "__package__", package)?;
102 m.add(
101 m.add(
103 py,
102 py,
104 "__doc__",
103 "__doc__",
105 "Patterns files parsing - Rust implementation",
104 "Patterns files parsing - Rust implementation",
106 )?;
105 )?;
107 m.add(
106 m.add(
108 py,
107 py,
109 "build_single_regex",
108 "build_single_regex",
110 py_fn!(
109 py_fn!(
111 py,
110 py,
112 build_single_regex_wrapper(
111 build_single_regex_wrapper(
113 kind: PyObject,
112 kind: PyObject,
114 pat: PyObject,
113 pat: PyObject,
115 globsuffix: PyObject
114 globsuffix: PyObject
116 )
115 )
117 ),
116 ),
118 )?;
117 )?;
119 m.add(
118 m.add(
120 py,
119 py,
121 "read_pattern_file",
120 "read_pattern_file",
122 py_fn!(
121 py_fn!(
123 py,
122 py,
124 read_pattern_file_wrapper(
123 read_pattern_file_wrapper(
125 file_path: PyObject,
124 file_path: PyObject,
126 warn: bool,
125 warn: bool,
127 source_info: bool
126 source_info: bool
128 )
127 )
129 ),
128 ),
130 )?;
129 )?;
131 m.add(py, "PatternError", py.get_type::<PatternError>())?;
130 m.add(py, "PatternError", py.get_type::<PatternError>())?;
132 let sys = PyModule::import(py, "sys")?;
131 let sys = PyModule::import(py, "sys")?;
133 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
132 let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
134 sys_modules.set_item(py, dotted_name, &m)?;
133 sys_modules.set_item(py, dotted_name, &m)?;
135
134
136 Ok(m)
135 Ok(m)
137 }
136 }
General Comments 0
You need to be logged in to leave comments. Login now