From 7ddcf45ec5dabc43b1ad7b6a91d219bc9f8225c6 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sun, 18 Oct 2020 18:36:31 +0100 Subject: [PATCH 1/2] Fix lifetime soundness in freelist --- pyo3-derive-backend/src/pyclass.rs | 2 +- src/freelist.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 558a6f6e..032935d5 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -267,7 +267,7 @@ fn impl_class( quote! { impl pyo3::freelist::PyClassWithFreeList for #cls { #[inline] - fn get_free_list(_py: pyo3::Python) -> &'static mut pyo3::freelist::FreeList<*mut pyo3::ffi::PyObject> { + fn get_free_list(_py: pyo3::Python) -> &mut pyo3::freelist::FreeList<*mut pyo3::ffi::PyObject> { static mut FREELIST: *mut pyo3::freelist::FreeList<*mut pyo3::ffi::PyObject> = 0 as *mut _; unsafe { if FREELIST.is_null() { diff --git a/src/freelist.rs b/src/freelist.rs index 65331773..5b56c337 100644 --- a/src/freelist.rs +++ b/src/freelist.rs @@ -12,7 +12,7 @@ use std::os::raw::c_void; /// The performance improvement applies to types that are often created and deleted in a row, /// so that they can benefit from a freelist. pub trait PyClassWithFreeList { - fn get_free_list(py: Python) -> &'static mut FreeList<*mut ffi::PyObject>; + fn get_free_list(py: Python) -> &mut FreeList<*mut ffi::PyObject>; } pub enum Slot { From afd9b823d2a7d099af400354aaed38e5c90f6b2a Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Sun, 18 Oct 2020 19:02:27 +0100 Subject: [PATCH 2/2] Drop support for Python 3.5 --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 3 +++ README.md | 2 +- build.rs | 2 +- examples/rustapi_module/setup.py | 2 +- examples/rustapi_module/src/datetime.rs | 17 +++++------- .../rustapi_module/tests/test_datetime.py | 23 +++------------- examples/word-count/tox.ini | 6 ++--- src/exceptions.rs | 1 - src/ffi/ceval.rs | 6 +---- src/ffi/code.rs | 8 ------ src/ffi/datetime.rs | 26 +++++++++---------- src/ffi/dictobject.rs | 1 - src/ffi/fileobject.rs | 1 - src/ffi/genobject.rs | 8 ------ src/ffi/mod.rs | 2 -- src/ffi/osmodule.rs | 1 - src/ffi/pydebug.rs | 2 +- src/ffi/pyerrors.rs | 2 -- src/ffi/pylifecycle.rs | 1 - src/ffi/pystate.rs | 3 --- src/ffi/warnings.rs | 1 - src/types/datetime.rs | 12 ++++----- tests/test_datetime.rs | 8 ------ 24 files changed, 40 insertions(+), 100 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2886d489..4c4caaa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: fail-fast: false # If one platform fails, allow the rest to keep testing. matrix: rust: [stable] - python-version: [3.5, 3.6, 3.7, 3.8, 3.9, pypy3] + python-version: [3.6, 3.7, 3.8, 3.9, pypy3] platform: [ { os: "macOS-latest", python-architecture: "x64", rust-target: "x86_64-apple-darwin" }, { os: "ubuntu-latest", python-architecture: "x64", rust-target: "x86_64-unknown-linux-gnu" }, diff --git a/CHANGELOG.md b/CHANGELOG.md index 98fceb83..6c41bcf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Packaging +- Drop support for Python 3.5 (as it is now end-of-life). [#1250](https://github.com/PyO3/pyo3/pull/1250) + ### Added - Add argument names to `TypeError` messages generated by pymethod wrappers. [#1212](https://github.com/PyO3/pyo3/pull/1212) diff --git a/README.md b/README.md index def67db2..53ace4f3 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ A comparison with rust-cpython can be found [in the guide](https://pyo3.rs/maste ## Usage -PyO3 supports Python 3.5 and up. The minimum required Rust version is 1.39.0. +PyO3 supports Python 3.6 and up. The minimum required Rust version is 1.39.0. Building with PyPy is also possible (via cpyext) for Python 3.6, targeted PyPy version is 7.3+. Please refer to the [pypy section in the guide](https://pyo3.rs/master/pypy.html). diff --git a/build.rs b/build.rs index 05d90f47..b77e4ad6 100644 --- a/build.rs +++ b/build.rs @@ -770,7 +770,7 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result { } if let Some(minor) = interpreter_config.version.minor { - for i in 5..(minor + 1) { + for i in 6..(minor + 1) { println!("cargo:rustc-cfg=Py_3_{}", i); flags += format!("CFG_Py_3_{},", i).as_ref(); } diff --git a/examples/rustapi_module/setup.py b/examples/rustapi_module/setup.py index f1fe9002..c4a51c58 100644 --- a/examples/rustapi_module/setup.py +++ b/examples/rustapi_module/setup.py @@ -59,7 +59,7 @@ class CargoModifiedSdist(SdistCommand): 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] - py3_min = 5 + py3_min = 6 out_cfg = [] for minor in range(py3_min, version[1] + 1): out_cfg.append("--cfg=Py_3_%d" % minor) diff --git a/examples/rustapi_module/src/datetime.rs b/examples/rustapi_module/src/datetime.rs index 062dc958..72fba0f0 100644 --- a/examples/rustapi_module/src/datetime.rs +++ b/examples/rustapi_module/src/datetime.rs @@ -42,7 +42,7 @@ fn make_time<'p>( ) } -#[cfg(Py_3_6)] +#[cfg(not(PyPy))] #[pyfunction] fn time_with_fold<'p>( py: Python<'p>, @@ -77,7 +77,7 @@ fn get_time_tuple<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple { ) } -#[cfg(all(Py_3_6, not(PyPy)))] +#[cfg(not(PyPy))] #[pyfunction] fn get_time_tuple_fold<'p>(py: Python<'p>, dt: &PyTime) -> &'p PyTuple { PyTuple::new( @@ -156,7 +156,7 @@ fn get_datetime_tuple<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple { ) } -#[cfg(all(Py_3_6, not(PyPy)))] +#[cfg(not(PyPy))] #[pyfunction] fn get_datetime_tuple_fold<'p>(py: Python<'p>, dt: &PyDateTime) -> &'p PyTuple { PyTuple::new( @@ -226,15 +226,12 @@ fn datetime(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(get_datetime_tuple, m)?)?; m.add_function(wrap_pyfunction!(datetime_from_timestamp, m)?)?; - // Python 3.6+ functions - #[cfg(Py_3_6)] + // Functions not supported by PyPy + #[cfg(not(PyPy))] { m.add_function(wrap_pyfunction!(time_with_fold, m)?)?; - #[cfg(not(PyPy))] - { - m.add_function(wrap_pyfunction!(get_time_tuple_fold, m)?)?; - m.add_function(wrap_pyfunction!(get_datetime_tuple_fold, m)?)?; - } + m.add_function(wrap_pyfunction!(get_time_tuple_fold, m)?)?; + m.add_function(wrap_pyfunction!(get_datetime_tuple_fold, m)?)?; } m.add_function(wrap_pyfunction!(issue_219, m)?)?; diff --git a/examples/rustapi_module/tests/test_datetime.py b/examples/rustapi_module/tests/test_datetime.py index fa9cb89a..421dec70 100644 --- a/examples/rustapi_module/tests/test_datetime.py +++ b/examples/rustapi_module/tests/test_datetime.py @@ -69,18 +69,6 @@ else: MAX_DATETIME = pdt.datetime(9999, 12, 31, 18, 59, 59) PYPY = platform.python_implementation() == "PyPy" -HAS_FOLD = getattr(pdt.datetime, "fold", False) and not PYPY - - -xfail_date_bounds = pytest.mark.xfail( - sys.version_info < (3, 6), - reason="Date bounds were not checked in the C constructor prior to version 3.6", -) - -xfail_macos_datetime_bounds = pytest.mark.xfail( - sys.version_info < (3, 6) and platform.system() == "Darwin", - reason="Unclearly failing. See https://github.com/PyO3/pyo3/pull/830 for more.", -) # Tests @@ -96,13 +84,11 @@ def test_date_accessors(d): assert act == exp -@xfail_date_bounds def test_invalid_date_fails(): with pytest.raises(ValueError): rdt.make_date(2017, 2, 30) -@xfail_macos_datetime_bounds @given(d=st.dates(MIN_DATETIME.date(), MAX_DATETIME.date())) def test_date_from_timestamp(d): if PYPY and d < pdt.date(1900, 1, 1): @@ -136,7 +122,7 @@ def test_time(t): assert act == exp -@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6") +@pytest.mark.xfail(PYPY, reason="Feature not available on PyPy") @given(t=st.times()) def test_time_fold(t): t_nofold = t.replace(fold=0) @@ -149,7 +135,7 @@ def test_time_fold(t): assert act == exp -@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6") +@pytest.mark.xfail(PYPY, reason="Feature not available on PyPy") @pytest.mark.parametrize("fold", [False, True]) def test_time_fold(fold): t = rdt.time_with_fold(0, 0, 0, 0, None, fold) @@ -165,7 +151,6 @@ def test_invalid_time_fails_xfail(args): rdt.make_time(*args) -@xfail_date_bounds @pytest.mark.parametrize( "args", [ @@ -218,7 +203,7 @@ def test_datetime_tuple(dt): assert act == exp -@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6") +@pytest.mark.xfail(PYPY, reason="Feature not available on PyPy") @given(dt=st.datetimes()) def test_datetime_tuple_fold(dt): dt_fold = dt.replace(fold=1) @@ -231,7 +216,6 @@ def test_datetime_tuple_fold(dt): assert act == exp -@xfail_date_bounds def test_invalid_datetime_fails(): with pytest.raises(ValueError): rdt.make_datetime(2011, 1, 42, 0, 0, 0, 0) @@ -242,7 +226,6 @@ def test_datetime_typeerror(): rdt.make_datetime("2011", 1, 1, 0, 0, 0, 0) -@xfail_macos_datetime_bounds @given(dt=st.datetimes(MIN_DATETIME, MAX_DATETIME)) @example(dt=pdt.datetime(1970, 1, 2, 0, 0)) def test_datetime_from_timestamp(dt): diff --git a/examples/word-count/tox.ini b/examples/word-count/tox.ini index 7a7d545d..1bc625bf 100644 --- a/examples/word-count/tox.ini +++ b/examples/word-count/tox.ini @@ -1,10 +1,10 @@ [tox] -envlist = py35, - py36, +envlist = py36, py37, py38, + py39, pypy3 -minversion = 3.4.0 +minversion = 3.6.0 skip_missing_interpreters = true isolated_build = true diff --git a/src/exceptions.rs b/src/exceptions.rs index 8bed1fb0..97483d41 100644 --- a/src/exceptions.rs +++ b/src/exceptions.rs @@ -308,7 +308,6 @@ impl_native_exception!( impl_native_exception!(PyOSError, OSError, PyExc_OSError, ffi::PyOSErrorObject); impl_native_exception!(PyImportError, ImportError, PyExc_ImportError); -#[cfg(Py_3_6)] impl_native_exception!( PyModuleNotFoundError, ModuleNotFoundError, diff --git a/src/ffi/ceval.rs b/src/ffi/ceval.rs index 21f4445f..31b00d7b 100644 --- a/src/ffi/ceval.rs +++ b/src/ffi/ceval.rs @@ -1,4 +1,3 @@ -#[cfg(Py_3_6)] use crate::ffi::code::FreeFunc; use crate::ffi::object::PyObject; use crate::ffi::pystate::PyThreadState; @@ -49,8 +48,7 @@ extern "C" { fn _Py_CheckRecursiveCall(_where: *mut c_char) -> c_int; } -// TODO: Py_EnterRecursiveCall etc. -#[cfg(Py_3_6)] +// TODO: Py_EnterRecursiveCall etc pub type _PyFrameEvalFunction = extern "C" fn(*mut crate::ffi::PyFrameObject, c_int) -> *mut PyObject; @@ -59,12 +57,10 @@ extern "C" { pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char; pub fn PyEval_GetCallStats(arg1: *mut PyObject) -> *mut PyObject; pub fn PyEval_EvalFrame(arg1: *mut crate::ffi::PyFrameObject) -> *mut PyObject; - #[cfg(Py_3_6)] pub fn _PyEval_EvalFrameDefault( arg1: *mut crate::ffi::PyFrameObject, exc: c_int, ) -> *mut PyObject; - #[cfg(Py_3_6)] pub fn _PyEval_RequestCodeExtraIndex(func: FreeFunc) -> c_int; pub fn PyEval_EvalFrameEx(f: *mut crate::ffi::PyFrameObject, exc: c_int) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")] diff --git a/src/ffi/code.rs b/src/ffi/code.rs index aadc835f..643e0652 100644 --- a/src/ffi/code.rs +++ b/src/ffi/code.rs @@ -14,7 +14,6 @@ pub struct PyCodeObject { pub co_nlocals: c_int, pub co_stacksize: c_int, pub co_flags: c_int, - #[cfg(Py_3_6)] pub co_firstlineno: c_int, pub co_code: *mut PyObject, pub co_consts: *mut PyObject, @@ -25,12 +24,9 @@ pub struct PyCodeObject { pub co_cell2arg: *mut c_uchar, pub co_filename: *mut PyObject, pub co_name: *mut PyObject, - #[cfg(not(Py_3_6))] - pub co_firstlineno: c_int, pub co_lnotab: *mut PyObject, pub co_zombieframe: *mut c_void, pub co_weakreflist: *mut PyObject, - #[cfg(Py_3_6)] pub co_extra: *mut c_void, #[cfg(Py_3_8)] pub co_opcache_map: *mut c_uchar, @@ -70,8 +66,6 @@ pub const CO_FUTURE_BARRY_AS_BDFL: c_int = 0x4_0000; pub const CO_FUTURE_GENERATOR_STOP: c_int = 0x8_0000; pub const CO_MAXBLOCKS: usize = 20; - -#[cfg(Py_3_6)] pub type FreeFunc = extern "C" fn(*mut c_void) -> c_void; #[cfg_attr(windows, link(name = "pythonXY"))] @@ -80,13 +74,11 @@ extern "C" { } extern "C" { - #[cfg(Py_3_6)] pub fn _PyCode_GetExtra( code: *mut PyObject, index: Py_ssize_t, extra: *const *mut c_void, ) -> c_int; - #[cfg(Py_3_6)] pub fn _PyCode_SetExtra(code: *mut PyObject, index: Py_ssize_t, extra: *mut c_void) -> c_int; #[cfg_attr(PyPy, link_name = "PyPyCode_New")] diff --git a/src/ffi/datetime.rs b/src/ffi/datetime.rs index e26dc034..8ed85eaa 100644 --- a/src/ffi/datetime.rs +++ b/src/ffi/datetime.rs @@ -29,7 +29,7 @@ pub struct PyDateTime_CAPI { pub TimeType: *mut PyTypeObject, pub DeltaType: *mut PyTypeObject, pub TZInfoType: *mut PyTypeObject, - #[cfg(Py_3_7)] + #[cfg(all(Py_3_7, not(PyPy)))] pub TimeZone_UTC: *mut PyObject, #[cfg_attr(PyPy, link_name = "_PyPyDate_FromDate")] pub Date_FromDate: unsafe extern "C" fn( @@ -67,7 +67,7 @@ pub struct PyDateTime_CAPI { normalize: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, - #[cfg(Py_3_7)] + #[cfg(all(Py_3_7, not(PyPy)))] pub TimeZone_FromTimeZone: unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject, @@ -80,7 +80,7 @@ pub struct PyDateTime_CAPI { // Defined for PyPy as `PyDate_FromTimestamp` pub Date_FromTimestamp: unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject, - #[cfg(Py_3_6)] + #[cfg(not(PyPy))] pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn( year: c_int, month: c_int, @@ -93,7 +93,7 @@ pub struct PyDateTime_CAPI { fold: c_int, cls: *mut PyTypeObject, ) -> *mut PyObject, - #[cfg(Py_3_6)] + #[cfg(not(PyPy))] pub Time_FromTimeAndFold: unsafe extern "C" fn( hour: c_int, minute: c_int, @@ -154,6 +154,7 @@ const _PyDateTime_DATETIME_DATASIZE: usize = 10; /// Structure representing a `datetime.date` pub struct PyDateTime_Date { pub ob_base: PyObject, + #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub hastzinfo: c_char, pub data: [c_uchar; _PyDateTime_DATE_DATASIZE], @@ -164,10 +165,12 @@ pub struct PyDateTime_Date { /// Structure representing a `datetime.time` pub struct PyDateTime_Time { pub ob_base: PyObject, + #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub hastzinfo: c_char, + #[cfg(not(PyPy))] pub data: [c_uchar; _PyDateTime_TIME_DATASIZE], - #[cfg(Py_3_6)] + #[cfg(not(PyPy))] pub fold: c_uchar, pub tzinfo: *mut PyObject, } @@ -177,10 +180,12 @@ pub struct PyDateTime_Time { /// Structure representing a `datetime.datetime` pub struct PyDateTime_DateTime { pub ob_base: PyObject, + #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub hastzinfo: c_char, + #[cfg(not(PyPy))] pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE], - #[cfg(Py_3_6)] + #[cfg(not(PyPy))] pub fold: c_uchar, pub tzinfo: *mut PyObject, } @@ -190,6 +195,7 @@ pub struct PyDateTime_DateTime { /// Structure representing a `datetime.timedelta` pub struct PyDateTime_Delta { pub ob_base: PyObject, + #[cfg(not(PyPy))] pub hashcode: Py_hash_t, pub days: c_int, pub seconds: c_int, @@ -381,7 +387,6 @@ macro_rules! _PyDateTime_GET_MICROSECOND { }; } -#[cfg(Py_3_6)] #[cfg(not(PyPy))] macro_rules! _PyDateTime_GET_FOLD { ($o: expr) => { @@ -429,13 +434,10 @@ pub unsafe fn PyDateTime_DATE_GET_MICROSECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE) } -#[cfg(Py_3_6)] #[inline] #[cfg(not(PyPy))] /// Retrieve the fold component of a `PyDateTime_DateTime`. /// Returns a signed integer in the interval `[0, 1]` -/// -/// Added in version Python 3.6 pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar { _PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime) } @@ -482,12 +484,10 @@ pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int { _PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0) } -#[cfg(all(Py_3_6, not(PyPy)))] +#[cfg(not(PyPy))] #[inline] /// Retrieve the fold component of a `PyDateTime_Time`. /// Returns a signed integer in the interval `[0, 1]` -/// -/// Added in version Python 3.6 pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar { _PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time) } diff --git a/src/ffi/dictobject.rs b/src/ffi/dictobject.rs index 4a1ba8e1..fa37ed1e 100644 --- a/src/ffi/dictobject.rs +++ b/src/ffi/dictobject.rs @@ -30,7 +30,6 @@ pub struct PyDictKeysObject { pub struct PyDictObject { pub ob_base: PyObject, pub ma_used: Py_ssize_t, - #[cfg(Py_3_6)] pub ma_version_tag: u64, pub ma_keys: *mut PyDictKeysObject, pub ma_values: *mut *mut PyObject, diff --git a/src/ffi/fileobject.rs b/src/ffi/fileobject.rs index 1a2562b6..61307496 100644 --- a/src/ffi/fileobject.rs +++ b/src/ffi/fileobject.rs @@ -27,7 +27,6 @@ extern "C" { #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut Py_FileSystemDefaultEncoding: *const c_char; - #[cfg(Py_3_6)] pub static mut Py_FileSystemDefaultEncodeErrors: *const c_char; pub static mut Py_HasFileSystemDefaultEncoding: c_int; } diff --git a/src/ffi/genobject.rs b/src/ffi/genobject.rs index f67fe54c..af7a936b 100644 --- a/src/ffi/genobject.rs +++ b/src/ffi/genobject.rs @@ -58,20 +58,12 @@ pub unsafe fn PyCoroWrapper_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, &mut _PyCoroWrapper_Type) } -#[cfg(Py_3_6)] #[cfg_attr(windows, link(name = "pythonXY"))] extern "C" { pub static mut PyAsyncGen_Type: PyTypeObject; } -#[cfg(Py_3_6)] #[inline] pub unsafe fn PyAsyncGen_Check(op: *mut PyObject) -> c_int { PyObject_TypeCheck(op, &mut PyAsyncGen_Type) } - -#[cfg(not(Py_3_6))] -#[inline] -pub unsafe fn PyAsyncGen_Check(_op: *mut PyObject) -> c_int { - 0 -} diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index 4015b2cd..5182a695 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -34,7 +34,6 @@ pub use self::moduleobject::*; pub use self::object::*; pub use self::objectabstract::*; pub use self::objimpl::*; -#[cfg(Py_3_6)] pub use self::osmodule::*; pub use self::pyarena::*; pub use self::pycapsule::*; @@ -124,7 +123,6 @@ mod pythonrun; // TODO some functions need to be moved to pylifecycle mod ceval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 mod import; mod intrcheck; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 -#[cfg(Py_3_6)] mod osmodule; mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5 diff --git a/src/ffi/osmodule.rs b/src/ffi/osmodule.rs index 35e4c3f7..f15682bd 100644 --- a/src/ffi/osmodule.rs +++ b/src/ffi/osmodule.rs @@ -1,4 +1,3 @@ -// This header is new in Python 3.6 use crate::ffi::object::PyObject; extern "C" { diff --git a/src/ffi/pydebug.rs b/src/ffi/pydebug.rs index 6422716d..1ebda05e 100644 --- a/src/ffi/pydebug.rs +++ b/src/ffi/pydebug.rs @@ -32,6 +32,6 @@ extern "C" { #[cfg_attr(PyPy, link_name = "PyPy_HashRandomizationFlag")] pub static mut Py_HashRandomizationFlag: c_int; pub static mut Py_IsolatedFlag: c_int; - #[cfg(all(Py_3_6, windows))] + #[cfg(windows)] pub static mut Py_LegacyWindowsStdioFlag: c_int; } diff --git a/src/ffi/pyerrors.rs b/src/ffi/pyerrors.rs index e88fc240..7a36bcb0 100644 --- a/src/ffi/pyerrors.rs +++ b/src/ffi/pyerrors.rs @@ -201,7 +201,6 @@ extern "C" { pub static mut PyExc_OSError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_ImportError")] pub static mut PyExc_ImportError: *mut PyObject; - #[cfg(Py_3_6)] #[cfg_attr(PyPy, link_name = "PyPyExc_ModuleNotFoundError")] pub static mut PyExc_ModuleNotFoundError: *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyExc_IndexError")] @@ -339,7 +338,6 @@ extern "C" { ) -> *mut PyObject; #[cfg_attr(PyPy, link_name = "PyPyErr_Format")] pub fn PyErr_Format(exception: *mut PyObject, format: *const c_char, ...) -> *mut PyObject; - #[cfg(Py_3_6)] pub fn PyErr_SetImportErrorSubclass( arg1: *mut PyObject, arg2: *mut PyObject, diff --git a/src/ffi/pylifecycle.rs b/src/ffi/pylifecycle.rs index c5e36138..d3c92385 100644 --- a/src/ffi/pylifecycle.rs +++ b/src/ffi/pylifecycle.rs @@ -6,7 +6,6 @@ extern "C" { pub fn Py_Initialize(); pub fn Py_InitializeEx(arg1: c_int); pub fn Py_Finalize(); - #[cfg(Py_3_6)] pub fn Py_FinalizeEx() -> c_int; #[cfg_attr(PyPy, link_name = "PyPy_IsInitialized")] diff --git a/src/ffi/pystate.rs b/src/ffi/pystate.rs index 2b883d97..1eaad51d 100644 --- a/src/ffi/pystate.rs +++ b/src/ffi/pystate.rs @@ -1,17 +1,14 @@ -#[cfg(Py_3_6)] use crate::ffi::ceval::_PyFrameEvalFunction; use crate::ffi::moduleobject::PyModuleDef; use crate::ffi::object::PyObject; use std::os::raw::{c_int, c_long}; -#[cfg(Py_3_6)] pub const MAX_CO_EXTRA_USERS: c_int = 255; #[repr(C)] #[derive(Copy, Clone)] pub struct PyInterpreterState { pub ob_base: PyObject, - #[cfg(Py_3_6)] pub eval_frame: _PyFrameEvalFunction, } diff --git a/src/ffi/warnings.rs b/src/ffi/warnings.rs index c70dfccd..2e2731cc 100644 --- a/src/ffi/warnings.rs +++ b/src/ffi/warnings.rs @@ -16,7 +16,6 @@ extern "C" { format: *const c_char, ... ) -> c_int; - #[cfg(Py_3_6)] pub fn PyErr_ResourceWarning( source: *mut PyObject, stack_level: Py_ssize_t, diff --git a/src/types/datetime.rs b/src/types/datetime.rs index 6d2696ab..89dbeb20 100644 --- a/src/types/datetime.rs +++ b/src/types/datetime.rs @@ -11,7 +11,7 @@ use crate::ffi; use crate::ffi::datetime::{PyDateTime_FromTimestamp, PyDate_FromTimestamp}; use crate::ffi::PyDateTimeAPI; use crate::ffi::{PyDateTime_Check, PyDate_Check, PyDelta_Check, PyTZInfo_Check, PyTime_Check}; -#[cfg(all(Py_3_6, not(PyPy)))] +#[cfg(not(PyPy))] use crate::ffi::{PyDateTime_DATE_GET_FOLD, PyDateTime_TIME_GET_FOLD}; use crate::ffi::{ PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE, @@ -57,7 +57,7 @@ pub trait PyTimeAccess { fn get_minute(&self) -> u8; fn get_second(&self) -> u8; fn get_microsecond(&self) -> u32; - #[cfg(all(Py_3_6, not(PyPy)))] + #[cfg(not(PyPy))] fn get_fold(&self) -> u8; } @@ -223,7 +223,7 @@ impl PyTimeAccess for PyDateTime { unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 } } - #[cfg(all(Py_3_6, not(PyPy)))] + #[cfg(not(PyPy))] fn get_fold(&self) -> u8 { unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) as u8 } } @@ -262,10 +262,8 @@ impl PyTime { } } - #[cfg(Py_3_6)] + #[cfg(not(PyPy))] /// Alternate constructor that takes a `fold` argument - /// - /// First available in Python 3.6. pub fn new_with_fold<'p>( py: Python<'p>, hour: u8, @@ -307,7 +305,7 @@ impl PyTimeAccess for PyTime { unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 } } - #[cfg(all(Py_3_6, not(PyPy)))] + #[cfg(not(PyPy))] fn get_fold(&self) -> u8 { unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) as u8 } } diff --git a/tests/test_datetime.rs b/tests/test_datetime.rs index f3114838..bbdff7fa 100644 --- a/tests/test_datetime.rs +++ b/tests/test_datetime.rs @@ -121,7 +121,6 @@ fn test_datetime_utc() { assert_approx_eq!(offset, 0f32); } -#[cfg(Py_3_6)] static INVALID_DATES: &[(i32, u8, u8)] = &[ (-1, 1, 1), (0, 1, 1), @@ -134,16 +133,13 @@ static INVALID_DATES: &[(i32, u8, u8)] = &[ (2018, 1, 32), ]; -#[cfg(Py_3_6)] static INVALID_TIMES: &[(u8, u8, u8, u32)] = &[(25, 0, 0, 0), (255, 0, 0, 0), (0, 60, 0, 0), (0, 0, 61, 0)]; -#[cfg(Py_3_6)] #[test] fn test_pydate_out_of_bounds() { use pyo3::types::PyDate; - // This test is an XFAIL on Python < 3.6 until bounds checking is implemented let gil = Python::acquire_gil(); let py = gil.python(); for val in INVALID_DATES { @@ -153,12 +149,10 @@ fn test_pydate_out_of_bounds() { } } -#[cfg(Py_3_6)] #[test] fn test_pytime_out_of_bounds() { use pyo3::types::PyTime; - // This test is an XFAIL on Python < 3.6 until bounds checking is implemented let gil = Python::acquire_gil(); let py = gil.python(); for val in INVALID_TIMES { @@ -168,13 +162,11 @@ fn test_pytime_out_of_bounds() { } } -#[cfg(Py_3_6)] #[test] fn test_pydatetime_out_of_bounds() { use pyo3::types::PyDateTime; use std::iter; - // This test is an XFAIL on Python < 3.6 until bounds checking is implemented let gil = Python::acquire_gil(); let py = gil.python(); let valid_time = (0, 0, 0, 0);