Skip to content

Commit

Permalink
Merge pull request #411 from ijl/rm-python2
Browse files Browse the repository at this point in the history
 Drop support for python2
  • Loading branch information
konstin authored Mar 29, 2019
2 parents bc7776e + 80179be commit 9f2afbc
Show file tree
Hide file tree
Showing 97 changed files with 342 additions and 6,170 deletions.
11 changes: 2 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,21 @@ cache:

matrix:
include:
- name: Python 2.7
python: "2.7"
env: FEATURES=python2
- name: Python 3.5
python: "3.5"
env: FEATURES="python3 test-doc"
env: FEATURES="test-doc"
- name: Python 3.6
python: "3.6"
env: FEATURES=python3
- name: Python 3.7
python: "3.7"
env: FEATURES=python3
- name: Python 3.8-dev
python: "3.8-dev"
env: FEATURES=python3
- name: Minimum nightly
python: "3.7"
# Keep this synced up with build.rs
env: FEATURES=python3 TRAVIS_RUST_VERSION=nightly-2019-02-07
env: TRAVIS_RUST_VERSION=nightly-2019-02-07
allow_failures:
- python: "3.8-dev"
env: FEATURES=python3

env:
global:
Expand Down
5 changes: 1 addition & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ version_check = "0.1.5"
[features]
default = []

# Use this feature when building python2 binding.
python2 = []

# Use this feature when building python3 binding.
# this is no longer needed internally, but setuptools-rust assumes this feature
python3 = []

# Use this feature when building an extension module.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste

## Usage

PyO3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.34.0-nightly 2019-02-06.
PyO3 supports python 3.5 and up. The minimum required rust version is 1.34.0-nightly 2019-02-06.

You can either write a native python module in rust or use python from a rust binary.

Expand Down
8 changes: 2 additions & 6 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,8 @@ version: 0.2.{build}
environment:
TARGET: x86_64-pc-windows-msvc
matrix:
- PYTHON: "C:/Python27-x64"
FEATURES: python2
- PYTHON: "C:/Python35-x64"
FEATURES: python3
- PYTHON: "C:/Python36-x64"
FEATURES: python3

install:
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
Expand All @@ -21,9 +17,9 @@ install:
- set RUST_BACKTRACE=1

build_script:
- cargo build --verbose --features %FEATURES%
- cargo build --verbose

test_script:
- cargo test --verbose --features %FEATURES%
- cargo test --verbose
- pip install setuptools-rust pytest pytest-benchmark
- cd examples/word-count && python setup.py install && pytest -v tests
15 changes: 11 additions & 4 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::fs::File;
use std::io;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use version_check::{is_min_date, is_min_version, supports_features};
Expand Down Expand Up @@ -482,11 +483,10 @@ fn configure(interpreter_version: &PythonVersion, lines: Vec<String>) -> Result<
println!("cargo:rustc-cfg=Py_3_{}", i);
flags += format!("CFG_Py_3_{},", i).as_ref();
}
println!("cargo:rustc-cfg=Py_3");
}
} else {
println!("cargo:rustc-cfg=Py_2");
flags += format!("CFG_Py_2,").as_ref();
// fail PYTHON_SYS_EXECUTABLE=python2 cargo ...
return Err("Python 2 is not supported".to_string());
}
return Ok(flags);
}
Expand Down Expand Up @@ -580,7 +580,14 @@ fn main() -> Result<(), String> {
find_interpreter_and_get_config()?
};

let flags = configure(&interpreter_version, lines)?;
let flags;
match configure(&interpreter_version, lines) {
Ok(val) => flags = val,
Err(err) => {
eprintln!("{}", err);
exit(1);
}
}

// WITH_THREAD is always on for 3.7
if interpreter_version.major == 3 && interpreter_version.minor.unwrap_or(0) >= 7 {
Expand Down
4 changes: 0 additions & 4 deletions examples/rustapi_module/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ def run(self):
def get_py_version_cfgs():
# For now each Cfg Py_3_X flag is interpreted as "at least 3.X"
version = sys.version_info[0:2]

if version[0] == 2:
return ["--cfg=Py_2"]

py3_min = 5
out_cfg = []
for minor in range(py3_min, version[1] + 1):
Expand Down
3 changes: 1 addition & 2 deletions examples/rustapi_module/tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[tox]
envlist = py27,
py35,
envlist = py35,
py36,
py37,
minversion = 2.9.0
Expand Down
4 changes: 2 additions & 2 deletions examples/word-count/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# word-count

Demonstrates searching for a file in plain python, with rust singlethreaded and with rust multithreaded.
Demonstrates searching for a file in plain python, with rust singlethreaded and with rust multithreaded.

## Build

Expand Down Expand Up @@ -35,7 +35,7 @@ pytest -v tests

## Testing

To test python 2.7, 3.5, 3.6 and 3.7, install tox globally and run
To test python 3.5, 3.6 and 3.7, install tox globally and run

```shell
tox
Expand Down
3 changes: 1 addition & 2 deletions examples/word-count/tox.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[tox]
envlist = py27,
py35,
envlist = py35,
py36,
py37,
minversion = 3.4.0
Expand Down
2 changes: 1 addition & 1 deletion guide/src/building-and-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Python version

PyO3 uses a build script to determine the python version and set the correct linker arguments. By default it uses the `python3` executable. With the `python2` feature it uses the `python2` executable. You can override the python interpreter by setting `PYTHON_SYS_EXECUTABLE`.
PyO3 uses a build script to determine the python version and set the correct linker arguments. By default it uses the `python3` executable. You can override the python interpreter by setting `PYTHON_SYS_EXECUTABLE`, e.g., `PYTHON_SYS_EXECUTABLE=python3.6`.

## Linking

Expand Down
14 changes: 2 additions & 12 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,18 +503,10 @@ Each methods corresponds to python's `self.attr`, `self.attr = value` and `del s
* `fn __str__(&self) -> PyResult<impl ToPyObject<ObjectType=PyString>>`

Possible return types for `__str__` and `__repr__` are `PyResult<String>` or `PyResult<PyString>`.
In Python 2.7, Unicode strings returned by `__str__` and `__repr__` will be converted to byte strings
by the Python runtime, which results in an exception if the string contains non-ASCII characters.

* `fn __bytes__(&self) -> PyResult<PyBytes>`

On Python 3.x, provides the conversion to `bytes`.
On Python 2.7, `__bytes__` is allowed but has no effect.

* `fn __unicode__(&self) -> PyResult<PyUnicode>`

On Python 2.7, provides the conversion to `unicode`.
On Python 3.x, `__unicode__` is allowed but has no effect.
Provides the conversion to `bytes`.

* `fn __format__(&self, format_spec: &str) -> PyResult<impl ToPyObject<ObjectType=PyString>>`

Expand All @@ -540,9 +532,7 @@ Each methods corresponds to python's `self.attr`, `self.attr = value` and `del s

* `fn __bool__(&self) -> PyResult<bool>`

Determines the "truthiness" of the object.
This method works for both python 3 and python 2,
even on Python 2.7 where the Python spelling was `__nonzero__`.
Determines the "truthyness" of the object.

### Garbage Collector Integration

Expand Down
2 changes: 1 addition & 1 deletion guide/src/get_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste

## Usage

PyO3 supports python 2.7 as well as python 3.5 and up. The minimum required rust version is 1.30.0-nightly 2018-08-18.
PyO3 supports python 3.5 and up. The minimum required rust version is 1.34.0-nightly 2019-02-06.

You can either write a native python module in rust or use python from a rust binary.

Expand Down
8 changes: 2 additions & 6 deletions guide/src/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,35 +56,31 @@ In python, modules are first class objects. This means can store them as values
# extern crate pyo3;
use pyo3::prelude::*;
use pyo3::{wrap_pyfunction, wrap_pymodule};
use pyo3::types::PyDict;
use pyo3::types::IntoPyDict;

#[pyfunction]
#[cfg(Py_3)]
fn subfunction() -> String {
"Subfunction".to_string()
}

#[pymodule]
#[cfg(Py_3)]
fn submodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pyfunction!(subfunction))?;
Ok(())
}

#[pymodule]
#[cfg(Py_3)]
fn supermodule(_py: Python, module: &PyModule) -> PyResult<()> {
module.add_wrapped(wrap_pymodule!(submodule))?;
Ok(())
}

#[cfg(Py_3)]
fn nested_call() {
let gil = GILGuard::acquire();
let py = gil.python();
let supermodule = wrap_pymodule!(supermodule)(py);
let ctx = [("supermodule", supermodule)].into_py_dict(py);

py.run("assert supermodule.submodule.subfuntion() == 'Subfunction'", None, Some(&ctx)).unwrap();
py.run("assert supermodule.submodule.subfunction() == 'Subfunction'", None, Some(&ctx)).unwrap();
}
```
5 changes: 0 additions & 5 deletions pyo3-derive-backend/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,6 @@ pub const OBJECT: Proto = Proto {
pyres: true,
proto: "pyo3::class::basic::PyObjectBytesProtocol",
},
MethodProto::Unary {
name: "__unicode__",
pyres: true,
proto: "pyo3::class::basic::PyObjectUnicodeProtocol",
},
MethodProto::Unary {
name: "__bool__",
pyres: false,
Expand Down
2 changes: 1 addition & 1 deletion pyo3-derive-backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod pymethod;
mod pyproto;
mod utils;

pub use module::{add_fn_to_module, process_functions_in_module, py2_init, py3_init};
pub use module::{add_fn_to_module, process_functions_in_module, py_init};
pub use pyclass::{build_py_class, PyClassArgs};
pub use pyfunction::PyFunctionAttr;
pub use pyimpl::{build_py_methods, impl_methods};
Expand Down
14 changes: 1 addition & 13 deletions pyo3-derive-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use syn::Ident;

/// Generates the function that is called by the python interpreter to initialize the native
/// module
pub fn py3_init(fnname: &Ident, name: &Ident, doc: syn::Lit) -> TokenStream {
pub fn py_init(fnname: &Ident, name: &Ident, doc: syn::Lit) -> TokenStream {
let cb_name = Ident::new(&format!("PyInit_{}", name), Span::call_site());

quote! {
Expand All @@ -27,18 +27,6 @@ pub fn py3_init(fnname: &Ident, name: &Ident, doc: syn::Lit) -> TokenStream {
}
}

pub fn py2_init(fnname: &Ident, name: &Ident, doc: syn::Lit) -> TokenStream {
let cb_name = Ident::new(&format!("init{}", name), Span::call_site());

quote! {
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn #cb_name() {
pyo3::derive_utils::make_module(concat!(stringify!(#name), "\0"), #doc, #fnname)
}
}
}

/// Finds and takes care of the #[pyfn(...)] in `#[pymodule]`
pub fn process_functions_in_module(func: &mut syn::ItemFn) {
let mut stmts: Vec<syn::Stmt> = Vec::new();
Expand Down
27 changes: 3 additions & 24 deletions pyo3cls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,15 @@ use proc_macro::TokenStream;
use proc_macro2::Span;
use pyo3_derive_backend::{
add_fn_to_module, build_py_class, build_py_methods, build_py_proto, get_doc,
process_functions_in_module, py2_init, py3_init, PyClassArgs, PyFunctionAttr,
process_functions_in_module, py_init, PyClassArgs, PyFunctionAttr,
};
use quote::quote;
use syn::parse_macro_input;

#[proc_macro_attribute]
pub fn pymodule2(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as syn::ItemFn);

let modname = if attr.is_empty() {
ast.ident.clone()
} else {
parse_macro_input!(attr as syn::Ident)
};

process_functions_in_module(&mut ast);

let expanded = py2_init(&ast.ident, &modname, get_doc(&ast.attrs, false));

quote!(
#ast
#expanded
)
.into()
}

/// Internally, this proc macro create a new c function called `PyInit_{my_module}`
/// that then calls the init function you provided
#[proc_macro_attribute]
pub fn pymodule3(attr: TokenStream, input: TokenStream) -> TokenStream {
pub fn pymodule(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut ast = parse_macro_input!(input as syn::ItemFn);

let modname = if attr.is_empty() {
Expand All @@ -47,7 +26,7 @@ pub fn pymodule3(attr: TokenStream, input: TokenStream) -> TokenStream {

process_functions_in_module(&mut ast);

let expanded = py3_init(&ast.ident, &modname, get_doc(&ast.attrs, false));
let expanded = py_init(&ast.ident, &modname, get_doc(&ast.attrs, false));

quote!(
#ast
Expand Down
13 changes: 2 additions & 11 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,23 +289,15 @@ impl PyBuffer {
#[inline]
pub fn is_c_contiguous(&self) -> bool {
unsafe {
// Python 2.7 is not const-correct, so we need the cast to *mut
ffi::PyBuffer_IsContiguous(
&*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer,
b'C' as libc::c_char,
) != 0
ffi::PyBuffer_IsContiguous(&*self.0 as *const ffi::Py_buffer, b'C' as libc::c_char) != 0
}
}

/// Gets whether the buffer is contiguous in Fortran-style order (first index varies fastest when visiting items in order of memory address).
#[inline]
pub fn is_fortran_contiguous(&self) -> bool {
unsafe {
// Python 2.7 is not const-correct, so we need the cast to *mut
ffi::PyBuffer_IsContiguous(
&*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer,
b'F' as libc::c_char,
) != 0
ffi::PyBuffer_IsContiguous(&*self.0 as *const ffi::Py_buffer, b'F' as libc::c_char) != 0
}
}

Expand Down Expand Up @@ -713,7 +705,6 @@ mod test {
}

#[test]
#[cfg(Py_3)] // array.array doesn't implement the buffer protocol in python 2.7
fn test_array_buffer() {
let gil = Python::acquire_gil();
let py = gil.python();
Expand Down
Loading

0 comments on commit 9f2afbc

Please sign in to comment.