rust/hg-cpython/src/lib.rs
author Raphaël Gomès <rgomes@octobus.net>
Fri, 18 Aug 2023 14:34:29 +0200
changeset 50990 4c5f6e95df84
parent 50005 136aa80aa8b2
permissions -rw-r--r--
rust: make `Revision` a newtype This change is the one we've been building towards during this series. The aim is to make `Revision` mean more than a simple integer, holding the information that it is valid for a given revlog index. While this still allows for programmer error, since creating a revision directly and querying a different index with a "checked" revision are still possible, the friction created by the newtype will hopefully make us think twice about which type to use. Enough of the Rust ecosystem relies on the newtype pattern to be efficiently optimized away (even compiler in codegen testsĀ¹), so I'm not worried about this being a fundamental problem. [1] https://github.com/rust-lang/rust/blob/7a70647f195f6b0a0f1ebd72b1542ba91a32f43a/tests/codegen/vec-in-place.rs#L47
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     1
// lib.rs
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     2
//
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     3
// Copyright 2018 Georges Racinet <gracinet@anybox.fr>
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     4
//
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     5
// 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
     6
// 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
     7
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     8
//! Python bindings of `hg-core` objects using the `cpython` crate.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
     9
//! Once compiled, the resulting single shared library object can be placed in
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    10
//! the `mercurial` package directly as `rustext.so` or `rustext.dll`.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    11
//! It holds several modules, so that from the point of view of Python,
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    12
//! it behaves as the `cext` package.
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    13
//!
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    14
//! Example:
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41131
diff changeset
    15
//!
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41131
diff changeset
    16
//! ```text
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    17
//! >>> from mercurial.rustext import ancestor
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    18
//! >>> ancestor.__doc__
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    19
//! 'Generic DAG ancestor algorithms - Rust implementation'
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    20
//! ```
50005
136aa80aa8b2 rust-clippy: disable some lints crate-wide for `hg-cpython`
Raphaël Gomès <rgomes@octobus.net>
parents: 48930
diff changeset
    21
#![allow(clippy::too_many_arguments)] // rust-cpython macros
136aa80aa8b2 rust-clippy: disable some lints crate-wide for `hg-cpython`
Raphaël Gomès <rgomes@octobus.net>
parents: 48930
diff changeset
    22
#![allow(clippy::zero_ptr)] // rust-cpython macros
136aa80aa8b2 rust-clippy: disable some lints crate-wide for `hg-cpython`
Raphaël Gomès <rgomes@octobus.net>
parents: 48930
diff changeset
    23
#![allow(clippy::needless_update)] // rust-cpython macros
136aa80aa8b2 rust-clippy: disable some lints crate-wide for `hg-cpython`
Raphaël Gomès <rgomes@octobus.net>
parents: 48930
diff changeset
    24
#![allow(clippy::manual_strip)] // rust-cpython macros
136aa80aa8b2 rust-clippy: disable some lints crate-wide for `hg-cpython`
Raphaël Gomès <rgomes@octobus.net>
parents: 48930
diff changeset
    25
#![allow(clippy::type_complexity)] // rust-cpython macros
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    26
50990
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    27
use cpython::{FromPyObject, PyInt, Python, ToPyObject};
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    28
use hg::{BaseRevision, Revision};
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    29
42609
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Raphaël Gomès <rgomes@octobus.net>
parents: 42560
diff changeset
    30
/// This crate uses nested private macros, `extern crate` is still needed in
326fdce22fb2 rust: switch hg-core and hg-cpython to rust 2018 edition
Raphaël Gomès <rgomes@octobus.net>
parents: 42560
diff changeset
    31
/// 2018 edition.
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    32
#[macro_use]
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    33
extern crate cpython;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    34
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41131
diff changeset
    35
pub mod ancestors;
41055
4c25038c112c rust-cpython: implement Graph using C parents function
Georges Racinet <gracinet@anybox.fr>
parents: 40978
diff changeset
    36
mod cindex;
41240
ff333620a4cc rust-cpython: moved generic conversion fn out of ancestors module
Georges Racinet <georges.racinet@octobus.net>
parents: 41184
diff changeset
    37
mod conversion;
42768
30320c7bf79f rust-cpython: add macro for sharing references
Raphaël Gomès <rgomes@octobus.net>
parents: 42763
diff changeset
    38
#[macro_use]
30320c7bf79f rust-cpython: add macro for sharing references
Raphaël Gomès <rgomes@octobus.net>
parents: 42763
diff changeset
    39
pub mod ref_sharing;
45960
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    40
pub mod copy_tracing;
41705
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    41
pub mod dagops;
44541
d4f19eb471ca rust-cpython: add `debug` module to expose debug information to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 44222
diff changeset
    42
pub mod debug;
42560
d26e4a434fe5 rust: run rfmt on all hg-core/hg-cpython code
Raphaël Gomès <rgomes@octobus.net>
parents: 42379
diff changeset
    43
pub mod dirstate;
42217
13b64247f48f rust-discovery: cpython bindings for the core logic
Georges Racinet <georges.racinet@octobus.net>
parents: 41705
diff changeset
    44
pub mod discovery;
41184
dcf818267bc1 rust-cpython: rustdoc improvements
Georges Racinet <georges.racinet@octobus.net>
parents: 41131
diff changeset
    45
pub mod exceptions;
47981
8f031a274cd6 rust: Move PyBytesWithData out of copy-tracing code
Simon Sapin <simon.sapin@octobus.net>
parents: 45960
diff changeset
    46
mod pybytes_deref;
43951
f98f0e3ddaa1 rust-index: add a function to convert PyObject index for hg-core
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43289
diff changeset
    47
pub mod revlog;
43251
970978975574 rust-utils: introduce a debug util to print the python stack trace
Raphaël Gomès <rgomes@octobus.net>
parents: 42829
diff changeset
    48
pub mod utils;
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    49
50990
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    50
/// Revision as exposed to/from the Python layer.
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    51
///
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    52
/// We need this indirection because of the orphan rule, meaning we can't
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    53
/// implement a foreign trait (like [`cpython::ToPyObject`])
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    54
/// for a foreign type (like [`hg::UncheckedRevision`]).
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    55
///
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    56
/// This also acts as a deterrent against blindly trusting Python to send
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    57
/// us valid revision numbers.
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    58
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    59
pub struct PyRevision(BaseRevision);
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    60
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    61
impl From<Revision> for PyRevision {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    62
    fn from(r: Revision) -> Self {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    63
        PyRevision(r.0)
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    64
    }
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    65
}
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    66
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    67
impl<'s> FromPyObject<'s> for PyRevision {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    68
    fn extract(
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    69
        py: Python,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    70
        obj: &'s cpython::PyObject,
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    71
    ) -> cpython::PyResult<Self> {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    72
        Ok(Self(obj.extract::<BaseRevision>(py)?))
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    73
    }
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    74
}
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    75
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    76
impl ToPyObject for PyRevision {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    77
    type ObjectType = PyInt;
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    78
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    79
    fn to_py_object(&self, py: Python) -> Self::ObjectType {
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    80
        self.0.to_py_object(py)
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    81
    }
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    82
}
4c5f6e95df84 rust: make `Revision` a newtype
Raphaël Gomès <rgomes@octobus.net>
parents: 50005
diff changeset
    83
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    84
py_module_initializer!(rustext, initrustext, PyInit_rustext, |py, m| {
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    85
    m.add(
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    86
        py,
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    87
        "__doc__",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    88
        "Mercurial core concepts - Rust implementation",
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    89
    )?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    90
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    91
    let dotted_name: String = m.get(py, "__name__")?.extract(py)?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
    92
    m.add(py, "ancestor", ancestors::init_module(py, &dotted_name)?)?;
41705
0c7b353ce100 rust-cpython: binding for headrevs()
Georges Racinet <georges.racinet@octobus.net>
parents: 41240
diff changeset
    93
    m.add(py, "dagop", dagops::init_module(py, &dotted_name)?)?;
44541
d4f19eb471ca rust-cpython: add `debug` module to expose debug information to Python
Raphaël Gomès <rgomes@octobus.net>
parents: 44222
diff changeset
    94
    m.add(py, "debug", debug::init_module(py, &dotted_name)?)?;
45960
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    95
    m.add(
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    96
        py,
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    97
        "copy_tracing",
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    98
        copy_tracing::init_module(py, &dotted_name)?,
50c5ee3bdf9a copies: introduce the hg-cpython wrapper for `combine_changeset_copies`
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 44541
diff changeset
    99
    )?;
42217
13b64247f48f rust-discovery: cpython bindings for the core logic
Georges Racinet <georges.racinet@octobus.net>
parents: 41705
diff changeset
   100
    m.add(py, "discovery", discovery::init_module(py, &dotted_name)?)?;
42330
e240bec26626 rust-dirstate: add rust-cpython bindings to the new parse/pack functions
Raphaël Gomès <rgomes@octobus.net>
parents: 42217
diff changeset
   101
    m.add(py, "dirstate", dirstate::init_module(py, &dotted_name)?)?;
43966
b69d5f3a41d0 rust-index: add a struct wrapping the C index
Georges Racinet <georges.racinet@octobus.net>
parents: 43951
diff changeset
   102
    m.add(py, "revlog", revlog::init_module(py, &dotted_name)?)?;
40978
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   103
    m.add(py, "GraphError", py.get_type::<exceptions::GraphError>())?;
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   104
    Ok(())
5532823e8c18 rust-cpython: start cpython crate bindings
Georges Racinet <gracinet@anybox.fr>
parents:
diff changeset
   105
});
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   106
48930
7b068abe4aa2 rust: jettison Python 2 support
Augie Fackler <augie@google.com>
parents: 48042
diff changeset
   107
#[cfg(not(feature = "python3-bin"))]
43289
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   108
#[test]
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   109
#[ignore]
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   110
fn libpython_must_be_linked_to_run_tests() {
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   111
    // stub function to tell that some tests wouldn't run
8d432d3a2d7c rust-cpython: prepare for writing tests that require libpython
Yuya Nishihara <yuya@tcha.org>
parents: 43251
diff changeset
   112
}