cpython 0.5.0

Bindings to Python
Documentation
use cpython::{py_class, GILGuard, Python};

py_class!(class Owner |py| {
    @shared data string: String;
});

fn prepare_env() -> (GILGuard, Owner) {
    let gil = Python::acquire_gil();
    let owner = {
        let py = gil.python();
        Owner::create_instance(py, "new".to_owned()).unwrap()
    };
    (gil, owner)
}

#[test]
fn test_leaked_borrow() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let leaked = owner.string(py).leak_immutable();
    let leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap();
    assert_eq!(*leaked_ref, "new");
}

#[test]
fn test_leaked_borrow_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let leaked = owner.string(py).leak_immutable();
    let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
    let mut leaked_ref = unsafe { leaked_iter.try_borrow_mut(py) }.unwrap();
    assert_eq!(leaked_ref.next(), Some('n'));
    assert_eq!(leaked_ref.next(), Some('e'));
    assert_eq!(leaked_ref.next(), Some('w'));
    assert_eq!(leaked_ref.next(), None);
}

#[test]
fn test_leaked_borrow_after_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let leaked = owner.string(py).leak_immutable();
    owner.string(py).borrow_mut().clear();
    assert!(unsafe { leaked.try_borrow(py) }.is_err());
}

#[test]
fn test_leaked_borrow_mut_after_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let leaked = owner.string(py).leak_immutable();
    let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
    owner.string(py).borrow_mut().clear();
    assert!(unsafe { leaked_iter.try_borrow_mut(py) }.is_err());
}

#[test]
#[should_panic(expected = "map() over invalidated leaked reference")]
fn test_leaked_map_after_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let leaked = owner.string(py).leak_immutable();
    owner.string(py).borrow_mut().clear();
    let _leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
}

#[test]
fn test_try_borrow_mut_while_leaked_ref() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    assert!(owner.string(py).try_borrow_mut().is_ok());
    let leaked = owner.string(py).leak_immutable();
    {
        let _leaked_ref = unsafe { leaked.try_borrow(py) }.unwrap();
        assert!(owner.string(py).try_borrow_mut().is_err());
        {
            let _leaked_ref2 = unsafe { leaked.try_borrow(py) }.unwrap();
            assert!(owner.string(py).try_borrow_mut().is_err());
        }
        assert!(owner.string(py).try_borrow_mut().is_err());
    }
    assert!(owner.string(py).try_borrow_mut().is_ok());
}

#[test]
fn test_try_borrow_mut_while_leaked_ref_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    assert!(owner.string(py).try_borrow_mut().is_ok());
    let leaked = owner.string(py).leak_immutable();
    let mut leaked_iter = unsafe { leaked.map(py, |s| s.chars()) };
    {
        let _leaked_ref = unsafe { leaked_iter.try_borrow_mut(py) }.unwrap();
        assert!(owner.string(py).try_borrow_mut().is_err());
    }
    assert!(owner.string(py).try_borrow_mut().is_ok());
}

#[test]
fn test_try_leak_while_borrow_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _mut_ref = owner.string(py).borrow_mut();
    assert!(owner.string(py).try_leak_immutable().is_err());
}

#[test]
#[should_panic(expected = "already mutably borrowed")]
fn test_leak_while_borrow_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _mut_ref = owner.string(py).borrow_mut();
    owner.string(py).leak_immutable();
}

#[test]
fn test_try_borrow_mut_while_borrow() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _ref = owner.string(py).borrow();
    assert!(owner.string(py).try_borrow_mut().is_err());
}

#[test]
#[should_panic(expected = "already borrowed")]
fn test_borrow_mut_while_borrow() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _ref = owner.string(py).borrow();
    owner.string(py).borrow_mut();
}

#[test]
fn test_try_borrow_while_borrow_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _mut_ref = owner.string(py).borrow_mut();
    assert!(owner.string(py).try_borrow().is_err());
}

#[test]
#[should_panic(expected = "already mutably borrowed")]
fn test_borrow_while_borrow_mut() {
    let (gil, owner) = prepare_env();
    let py = gil.python();
    let _mut_ref = owner.string(py).borrow_mut();
    owner.string(py).borrow();
}