diff --git a/.travis.yml b/.travis.yml index 9b10699e081..7d2823ca521 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ matrix: env: FEATURES=python2 - name: Python 3.5 python: "3.5" - env: FEATURES=python3 + env: FEATURES="python3 test-doc" - name: Python 3.6 python: "3.6" env: FEATURES=python3 diff --git a/Cargo.toml b/Cargo.toml index 874df4bdc75..39d72be787c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,9 @@ extension-module = [] # are welcome. # abi3 = [] +# Use this feature to test the examples in the user guide +test-doc = [] + [workspace] members = [ "pyo3cls", diff --git a/README.md b/README.md index 503e7214568..5c9ac7541d7 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,9 @@ features = ["extension-module"] **`src/lib.rs`** ```rust +// Not required when using Rust 2018 +extern crate pyo3; + use pyo3::prelude::*; use pyo3::wrap_pyfunction; @@ -95,6 +98,9 @@ pyo3 = "0.6.0-alpha.4" Example program displaying the value of `sys.version`: ```rust +// Not required when using Rust 2018 +extern crate pyo3; + use pyo3::prelude::*; use pyo3::types::PyDict; diff --git a/ci/travis/test.sh b/ci/travis/test.sh index 70ebc8012b0..51011e8c44b 100755 --- a/ci/travis/test.sh +++ b/ci/travis/test.sh @@ -1,6 +1,7 @@ #!/bin/bash set -ex +cargo clean cargo test --features "$FEATURES num-complex" if [ $TRAVIS_JOB_NAME = 'Minimum nightly' ]; then cargo fmt --all -- --check diff --git a/guide/src/class.md b/guide/src/class.md index 21ad35b67b3..c4b1323db07 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -6,6 +6,7 @@ To define a custom python class, a rust struct needs to be annotated with the `#[pyclass]` attribute. ```rust +# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] @@ -35,6 +36,7 @@ You can get an instance of `PyRef` by `PyRef::new`, which does 3 things: You can use `PyRef` just like `&T`, because it implements `Deref`. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::types::PyDict; #[pyclass] @@ -54,6 +56,7 @@ dict.set_item("obj", obj).unwrap(); ### `PyRefMut` `PyRefMut` is a mutable version of `PyRef`. ```rust +# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] struct MyClass { @@ -71,6 +74,7 @@ obj.num = 5; You can use it to avoid lifetime problems. ```rust +# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] struct MyClass { @@ -110,6 +114,7 @@ To declare a constructor, you need to define a class method and annotate it with attribute. Only the python `__new__` method can be specified, `__init__` is not available. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::PyRawObject; #[pyclass] @@ -150,7 +155,8 @@ By default `PyObject` is used as default base class. To override default base cl `new` method accepts `PyRawObject` object. `obj` instance must be initialized with value of custom class struct. Subclass must call parent's `new` method. -```rust +```rust,ignore +# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::PyRawObject; #[pyclass] @@ -184,7 +190,7 @@ impl SubClass { } fn method2(&self) -> PyResult<()> { - self.get_base().method() + self.get_base().method() } } ``` @@ -200,6 +206,7 @@ Descriptor methods can be defined in attributes. i.e. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -223,7 +230,8 @@ If function name starts with `get_` or `set_` for getter or setter respectively. Descriptor name becomes function name with prefix removed. This is useful in case of rust's special keywords like `type`. -```rust +```rust,ignore +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -251,7 +259,8 @@ In this case property `num` is defined. And it is available from python code as Also both `#[getter]` and `#[setter]` attributes accepts one parameter. If this parameter is specified, it is used as a property name. i.e. -```rust +```rust,ignore +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -278,7 +287,8 @@ In this case the property `number` is defined and is available from python code For simple cases you can also define getters and setters in your Rust struct field definition, for example: -```rust +```rust,ignore +# extern crate pyo3; # use pyo3::prelude::*; #[pyclass] struct MyClass { @@ -296,6 +306,7 @@ To define a python compatible method, `impl` block for struct has to be annotate block with some variations, like descriptors, class method static methods, etc. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -323,6 +334,7 @@ The return type must be `PyResult` for some `T` that implements `IntoPyObject get injected by method wrapper. i.e ```rust +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -346,6 +358,7 @@ To specify a class method for a custom class, the method needs to be annotated with the `#[classmethod]` attribute. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # use pyo3::types::PyType; # #[pyclass] @@ -378,6 +391,7 @@ To specify a static method for a custom class, method needs to be annotated with `IntoPyObject`. ```rust +# extern crate pyo3; # use pyo3::prelude::*; # #[pyclass] # struct MyClass { @@ -400,6 +414,7 @@ To specify a custom `__call__` method for a custom class, call methods need to b the `#[call]` attribute. Arguments of the method are specified same as for instance method. ```rust +# extern crate pyo3; # use pyo3::prelude::*; use pyo3::types::PyTuple; # #[pyclass] @@ -442,6 +457,7 @@ Each parameter could be one of following type: Example: ```rust +# extern crate pyo3; # use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; # @@ -543,6 +559,8 @@ These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API. as every cycle must contain at least one mutable reference. Example: ```rust +extern crate pyo3; + use pyo3::prelude::*; use pyo3::PyTraverseError; use pyo3::gc::{PyGCProtocol, PyVisit}; @@ -583,14 +601,16 @@ collector, and it is possible to track them with `gc` module methods. Iterators can be defined using the [`PyIterProtocol`](https://docs.rs/pyo3/0.6.0-alpha.4/class/iter/trait.PyIterProtocol.html) trait. It includes two methods `__iter__` and `__next__`: - * `fn __iter__(&mut self) -> PyResult` - * `fn __next__(&mut self) -> PyResult>` + * `fn __iter__(slf: PyRefMut) -> PyResult` + * `fn __next__(slf: PyRefMut) -> PyResult>` Returning `Ok(None)` from `__next__` indicates that that there are no further items. Example: ```rust +extern crate pyo3; + use pyo3::prelude::*; use pyo3::PyIterProtocol; diff --git a/guide/src/conversions.md b/guide/src/conversions.md index a8b345688fd..537f86b1063 100644 --- a/guide/src/conversions.md +++ b/guide/src/conversions.md @@ -24,6 +24,7 @@ provides two methods: Both methods accept `args` and `kwargs` arguments. ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::types::{PyDict, PyTuple}; @@ -61,6 +62,7 @@ fn main() { [`IntoPyDict`][IntoPyDict] trait to convert other dict-like containers, e.g. `HashMap`, `BTreeMap` as well as tuples with up to 10 elements and `Vec`s where each element is a two element tuple. ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::types::{IntoPyDict, PyDict}; use std::collections::HashMap; diff --git a/guide/src/exception.md b/guide/src/exception.md index a6c4bb3c1ac..de12e83a906 100644 --- a/guide/src/exception.md +++ b/guide/src/exception.md @@ -5,6 +5,7 @@ You can use the `create_exception!` macro to define a new exception type: ```rust +# extern crate pyo3; use pyo3::create_exception; create_exception!(module, MyError, pyo3::exceptions::Exception); @@ -16,6 +17,7 @@ create_exception!(module, MyError, pyo3::exceptions::Exception); For example: ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::create_exception; use pyo3::types::PyDict; @@ -40,6 +42,7 @@ fn main() { To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html), then call [`PyErr::restore()`](https://docs.rs/pyo3/0.2.7/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state. ```rust +# extern crate pyo3; use pyo3::{Python, PyErr}; use pyo3::exceptions; @@ -64,6 +67,7 @@ has corresponding rust type, exceptions defined by `create_exception!` and `impo have rust type as well. ```rust +# extern crate pyo3; # use pyo3::exceptions; # use pyo3::prelude::*; # fn check_for_error() -> bool {false} @@ -82,6 +86,7 @@ Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#is in `PyO3` there is a [`Python::is_instance()`](https://docs.rs/pyo3/0.2.7/struct.Python.html#method.is_instance) method which does the same thing. ```rust +# extern crate pyo3; use pyo3::Python; use pyo3::types::{PyBool, PyList}; @@ -100,6 +105,7 @@ fn main() { To check the type of an exception, you can simply do: ```rust +# extern crate pyo3; # use pyo3::exceptions; # use pyo3::prelude::*; # fn main() { @@ -151,6 +157,7 @@ The code snippet above will raise `OSError` in Python if `TcpListener::bind()` r types so `try!` macro or `?` operator can be used. ```rust +# extern crate pyo3; use pyo3::prelude::*; fn parse_int(s: String) -> PyResult { @@ -168,6 +175,7 @@ It is possible to use exception defined in python code as native rust types. for that exception. ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::import_exception; diff --git a/guide/src/function.md b/guide/src/function.md index 65f0635457b..836d723fb78 100644 --- a/guide/src/function.md +++ b/guide/src/function.md @@ -6,6 +6,7 @@ the function to a [module](./module.md) One way is defining the function in the module definition. ```rust +# extern crate pyo3; use pyo3::prelude::*; #[pymodule] @@ -30,6 +31,7 @@ as first parameter, the function name as second and an instance of `Python` as third. ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::wrap_pyfunction; @@ -60,6 +62,7 @@ built-ins are new in Python 3 — in Python 2, it is simply considered to be par of the doc-string. ```rust +# extern crate pyo3; use pyo3::prelude::*; /// add(a, b, /) @@ -73,7 +76,7 @@ fn add(a: u64, b: u64) -> u64 { ``` When annotated like this, signatures are also correctly displayed in IPython. -``` +```ignore >>> pyo3_test.add? Signature: pyo3_test.add(a, b, /) Docstring: This function adds two unsigned 64-bit integers. diff --git a/guide/src/get_started.md b/guide/src/get_started.md index dbddab18013..d8d71cfea8e 100644 --- a/guide/src/get_started.md +++ b/guide/src/get_started.md @@ -45,6 +45,7 @@ features = ["extension-module"] **`src/lib.rs`** ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::wrap_pyfunction; @@ -89,6 +90,7 @@ pyo3 = "0.5" Example program displaying the value of `sys.version`: ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::types::PyDict; diff --git a/guide/src/module.md b/guide/src/module.md index 7a4a2ea8047..f18165d3f08 100644 --- a/guide/src/module.md +++ b/guide/src/module.md @@ -3,6 +3,7 @@ As shown in the Getting Started chapter, you can create a module as follows: ```rust +# extern crate pyo3; use pyo3::prelude::*; // add bindings to the generated python module @@ -52,6 +53,7 @@ Which means that the above Python code will print `This module is implemented in In python, modules are first class objects. This means can store them as values or add them to dicts or other modules: ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::{wrap_pyfunction, wrap_pymodule}; use pyo3::types::PyDict; diff --git a/guide/src/rust-cpython.md b/guide/src/rust-cpython.md index 466dc1a00e3..8295dc96114 100644 --- a/guide/src/rust-cpython.md +++ b/guide/src/rust-cpython.md @@ -25,6 +25,7 @@ py_class!(class MyClass |py| { **pyo3** ```rust +# extern crate pyo3; use pyo3::prelude::*; use pyo3::PyRawObject; diff --git a/tests/test_doc.rs b/tests/test_doc.rs index b5f46225a97..49688b64de5 100644 --- a/tests/test_doc.rs +++ b/tests/test_doc.rs @@ -14,8 +14,8 @@ fn assert_file>(path: P) { doc.test_file(path.as_ref()) } -#[ignore] #[test] +#[cfg(feature = "test-doc")] fn test_guide() { let guide_path = PathBuf::from("guide").join("src"); for entry in guide_path.read_dir().unwrap() { @@ -23,8 +23,8 @@ fn test_guide() { } } -#[ignore] #[test] +#[cfg(feature = "test-doc")] fn test_readme() { assert_file("README.md") }