rust/hg-cpython/src/filepatterns.rs
changeset 42437 9609430d3625
parent 42328 94f3a73b6672
child 42609 326fdce22fb2
equal deleted inserted replaced
42436:dc5bd66a8270 42437:9609430d3625
     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 module.
    11 //! and can be used as replacement for the the pure `filepatterns` Python module.
    12 //!
    12 //!
    13 use cpython::{
    13 use cpython::{
    14     exc, PyDict, PyErr, PyModule, PyResult, PyString, PyTuple, Python,
    14     PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
    15     ToPyObject,
       
    16 };
    15 };
    17 use hg::{build_single_regex, read_pattern_file, PatternTuple};
    16 use exceptions::{PatternError, PatternFileError};
    18 use exceptions::{
    17 use hg::{build_single_regex, read_pattern_file, LineNumber, PatternTuple};
    19     PatternError,
       
    20     PatternFileError,
       
    21 };
       
    22 
    18 
    23 /// Rust does not like functions with different return signatures.
    19 /// Rust does not like functions with different return signatures.
    24 /// The 3-tuple version is always returned by the hg-core function,
    20 /// 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
    21 /// the (potential) conversion is handled at this level since it is not likely
    26 /// to have any measurable impact on performance.
    22 /// to have any measurable impact on performance.
    30 /// implementation chooses to accumulate the warnings and propagate them to
    26 /// implementation chooses to accumulate the warnings and propagate them to
    31 /// Python upon completion. See the `readpatternfile` function in `match.py`
    27 /// Python upon completion. See the `readpatternfile` function in `match.py`
    32 /// for more details.
    28 /// for more details.
    33 fn read_pattern_file_wrapper(
    29 fn read_pattern_file_wrapper(
    34     py: Python,
    30     py: Python,
    35     file_path: String,
    31     file_path: PyObject,
    36     warn: bool,
    32     warn: bool,
    37     source_info: bool,
    33     source_info: bool,
    38 ) -> PyResult<PyTuple> {
    34 ) -> PyResult<PyTuple> {
    39     match read_pattern_file(file_path, warn) {
    35     match read_pattern_file(file_path.extract::<PyBytes>(py)?.data(py), warn) {
    40         Ok((patterns, warnings)) => {
    36         Ok((patterns, warnings)) => {
    41             if source_info {
    37             if source_info {
    42                 return Ok((patterns, warnings).to_py_object(py));
    38                 let itemgetter = |x: &PatternTuple| {
       
    39                     (PyBytes::new(py, &x.0), x.1, PyBytes::new(py, &x.2))
       
    40                 };
       
    41                 let results: Vec<(PyBytes, LineNumber, PyBytes)> =
       
    42                     patterns.iter().map(itemgetter).collect();
       
    43                 return Ok((results, warnings).to_py_object(py));
    43             }
    44             }
    44             let itemgetter = |x: &PatternTuple| x.0.to_py_object(py);
    45             let itemgetter = |x: &PatternTuple| PyBytes::new(py, &x.0);
    45             let results: Vec<PyString> =
    46             let results: Vec<PyBytes> =
    46                 patterns.iter().map(itemgetter).collect();
    47                 patterns.iter().map(itemgetter).collect();
    47             Ok((results, warnings).to_py_object(py))
    48             Ok((results, warnings).to_py_object(py))
    48         }
    49         }
    49         Err(e) => Err(PatternFileError::pynew(py, e)),
    50         Err(e) => Err(PatternFileError::pynew(py, e)),
    50     }
    51     }
    51 }
    52 }
    52 
    53 
    53 fn build_single_regex_wrapper(
    54 fn build_single_regex_wrapper(
    54     py: Python,
    55     py: Python,
    55     kind: String,
    56     kind: PyObject,
    56     pat: String,
    57     pat: PyObject,
    57     globsuffix: String,
    58     globsuffix: PyObject,
    58 ) -> PyResult<PyString> {
    59 ) -> PyResult<PyBytes> {
    59     match build_single_regex(
    60     match build_single_regex(
    60         kind.as_ref(),
    61         kind.extract::<PyBytes>(py)?.data(py),
    61         pat.as_bytes(),
    62         pat.extract::<PyBytes>(py)?.data(py),
    62         globsuffix.as_bytes(),
    63         globsuffix.extract::<PyBytes>(py)?.data(py),
    63     ) {
    64     ) {
    64         Ok(regex) => match String::from_utf8(regex) {
    65         Ok(regex) => Ok(PyBytes::new(py, &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)),
    66         Err(e) => Err(PatternError::pynew(py, e)),
    72     }
    67     }
    73 }
    68 }
    74 
    69 
    75 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
    70 pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
    86         py,
    81         py,
    87         "build_single_regex",
    82         "build_single_regex",
    88         py_fn!(
    83         py_fn!(
    89             py,
    84             py,
    90             build_single_regex_wrapper(
    85             build_single_regex_wrapper(
    91                 kind: String,
    86                 kind: PyObject,
    92                 pat: String,
    87                 pat: PyObject,
    93                 globsuffix: String
    88                 globsuffix: PyObject
    94             )
    89             )
    95         ),
    90         ),
    96     )?;
    91     )?;
    97     m.add(
    92     m.add(
    98         py,
    93         py,
    99         "read_pattern_file",
    94         "read_pattern_file",
   100         py_fn!(
    95         py_fn!(
   101             py,
    96             py,
   102             read_pattern_file_wrapper(
    97             read_pattern_file_wrapper(
   103                 file_path: String,
    98                 file_path: PyObject,
   104                 warn: bool,
    99                 warn: bool,
   105                 source_info: bool
   100                 source_info: bool
   106             )
   101             )
   107         ),
   102         ),
   108     )?;
   103     )?;
   109 
   104     m.add(py, "PatternError", py.get_type::<PatternError>())?;
   110     let sys = PyModule::import(py, "sys")?;
   105     let sys = PyModule::import(py, "sys")?;
   111     let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
   106     let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
   112     sys_modules.set_item(py, dotted_name, &m)?;
   107     sys_modules.set_item(py, dotted_name, &m)?;
   113 
   108 
   114     Ok(m)
   109     Ok(m)