rust/hg-cpython/src/filepatterns.rs
author Raphaël Gomès <rgomes@octobus.net>
Thu, 06 Jun 2019 15:30:56 +0200
changeset 42437 9609430d3625
parent 42328 94f3a73b6672
child 42609 326fdce22fb2
permissions -rw-r--r--
rust-filepatterns: use bytes instead of String In my initial patch, I introduced an unnecessary hard constraint on UTF-8 filenames and patterns which I forgot to remove. Although the performance penalty for using String might be negligible, we don't want to break compatibility with non-UTF-8 encodings for no reason. Moreover, this change allows for a cleaner Rust core API. This patch introduces a new utils module that is used with this fix. Finally, PatternError was not put inside the Python module generated by Rust, which would have raised a NameError. Differential Revision: https://phab.mercurial-scm.org/D6485
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
     1
// filepatterns.rs
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     2
//
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
     3
// Copyright 2019, Georges Racinet <gracinet@anybox.fr>,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
     4
// Raphaël Gomès <rgomes@octobus.net>
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     5
//
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     6
// This software may be used and distributed according to the terms of the
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     7
// GNU General Public License version 2 or any later version.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     8
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
     9
//! Bindings for the `hg::filepatterns` module provided by the
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    10
//! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns`
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    11
//! and can be used as replacement for the the pure `filepatterns` Python module.
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
    12
//!
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    13
use cpython::{
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    14
    PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    15
};
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    16
use exceptions::{PatternError, PatternFileError};
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    17
use hg::{build_single_regex, read_pattern_file, LineNumber, PatternTuple};
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    18
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    19
/// Rust does not like functions with different return signatures.
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    20
/// The 3-tuple version is always returned by the hg-core function,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    21
/// the (potential) conversion is handled at this level since it is not likely
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    22
/// to have any measurable impact on performance.
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    23
///
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    24
/// The Python implementation passes a function reference for `warn` instead
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    25
/// of a boolean that is used to emit warnings while parsing. The Rust
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    26
/// implementation chooses to accumulate the warnings and propagate them to
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    27
/// Python upon completion. See the `readpatternfile` function in `match.py`
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    28
/// for more details.
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    29
fn read_pattern_file_wrapper(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    30
    py: Python,
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    31
    file_path: PyObject,
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    32
    warn: bool,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    33
    source_info: bool,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    34
) -> PyResult<PyTuple> {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    35
    match read_pattern_file(file_path.extract::<PyBytes>(py)?.data(py), warn) {
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    36
        Ok((patterns, warnings)) => {
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    37
            if source_info {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    38
                let itemgetter = |x: &PatternTuple| {
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    39
                    (PyBytes::new(py, &x.0), x.1, PyBytes::new(py, &x.2))
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    40
                };
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    41
                let results: Vec<(PyBytes, LineNumber, PyBytes)> =
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    42
                    patterns.iter().map(itemgetter).collect();
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    43
                return Ok((results, warnings).to_py_object(py));
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    44
            }
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    45
            let itemgetter = |x: &PatternTuple| PyBytes::new(py, &x.0);
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    46
            let results: Vec<PyBytes> =
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    47
                patterns.iter().map(itemgetter).collect();
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    48
            Ok((results, warnings).to_py_object(py))
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    49
        }
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    50
        Err(e) => Err(PatternFileError::pynew(py, e)),
41053
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    51
    }
d9f439fcdb4c rust-cpython: binding for AncestorsIterator
Georges Racinet <gracinet@anybox.fr>
parents: 40965
diff changeset
    52
}
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    53
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    54
fn build_single_regex_wrapper(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    55
    py: Python,
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    56
    kind: PyObject,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    57
    pat: PyObject,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    58
    globsuffix: PyObject,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    59
) -> PyResult<PyBytes> {
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    60
    match build_single_regex(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    61
        kind.extract::<PyBytes>(py)?.data(py),
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    62
        pat.extract::<PyBytes>(py)?.data(py),
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    63
        globsuffix.extract::<PyBytes>(py)?.data(py),
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    64
    ) {
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    65
        Ok(regex) => Ok(PyBytes::new(py, &regex)),
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    66
        Err(e) => Err(PatternError::pynew(py, e)),
41114
b31a41f24864 rust-cpython: binding for LazyAncestors
Georges Racinet <gracinet@anybox.fr>
parents: 41053
diff changeset
    67
    }
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    68
}
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
    69
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    70
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    71
    let dotted_name = &format!("{}.filepatterns", package);
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    72
    let m = PyModule::new(py, dotted_name)?;
41188
006c9ce486fa rust-cpython: bindings for MissingAncestors
Georges Racinet <georges.racinet@octobus.net>
parents: 41187
diff changeset
    73
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    74
    m.add(py, "__package__", package)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    75
    m.add(
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    76
        py,
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    77
        "__doc__",
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    78
        "Patterns files parsing - Rust implementation",
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    79
    )?;
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    80
    m.add(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    81
        py,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    82
        "build_single_regex",
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    83
        py_fn!(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    84
            py,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    85
            build_single_regex_wrapper(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    86
                kind: PyObject,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    87
                pat: PyObject,
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    88
                globsuffix: PyObject
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    89
            )
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    90
        ),
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    91
    )?;
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    92
    m.add(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    93
        py,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    94
        "read_pattern_file",
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    95
        py_fn!(
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    96
            py,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    97
            read_pattern_file_wrapper(
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
    98
                file_path: PyObject,
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
    99
                warn: bool,
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
   100
                source_info: bool
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
   101
            )
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
   102
        ),
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
   103
    )?;
42437
9609430d3625 rust-filepatterns: use bytes instead of String
Raphaël Gomès <rgomes@octobus.net>
parents: 42328
diff changeset
   104
    m.add(py, "PatternError", py.get_type::<PatternError>())?;
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   105
    let sys = PyModule::import(py, "sys")?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   106
    let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   107
    sys_modules.set_item(py, dotted_name, &m)?;
42328
94f3a73b6672 rust-filepatterns: add `rust-cpython` bindings for `filepatterns`
Raphaël Gomès <rgomes@octobus.net>
parents: 41693
diff changeset
   108
40965
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   109
    Ok(m)
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   110
}