Format
This commit is contained in:
parent
a9b05711b0
commit
9f45efebaf
|
@ -1,3 +1,4 @@
|
|||
hypothesis>=3.55
|
||||
pytest>=3.5.0
|
||||
setuptools-rust>=0.10.2
|
||||
black
|
|
@ -12,7 +12,8 @@ class PyTest(TestCommand):
|
|||
self.run_command("test_rust")
|
||||
|
||||
import subprocess
|
||||
errno = subprocess.call(['pytest', 'tests'])
|
||||
|
||||
errno = subprocess.call(["pytest", "tests"])
|
||||
raise SystemExit(errno)
|
||||
|
||||
|
||||
|
@ -21,41 +22,48 @@ def get_py_version_cfgs():
|
|||
version = sys.version_info[0:2]
|
||||
|
||||
if version[0] == 2:
|
||||
return ['--cfg=Py_2']
|
||||
return ["--cfg=Py_2"]
|
||||
|
||||
py3_min = 5
|
||||
out_cfg = []
|
||||
for minor in range(py3_min, version[1] + 1):
|
||||
out_cfg.append('--cfg=Py_3_%d' % minor)
|
||||
out_cfg.append("--cfg=Py_3_%d" % minor)
|
||||
|
||||
return out_cfg
|
||||
|
||||
|
||||
install_requires = []
|
||||
tests_require = install_requires + ['pytest', 'pytest-benchmark']
|
||||
tests_require = install_requires + ["pytest", "pytest-benchmark"]
|
||||
|
||||
setup(
|
||||
name='rustapi-module',
|
||||
version='0.1.0',
|
||||
name="rustapi-module",
|
||||
version="0.1.0",
|
||||
classifiers=[
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Development Status :: 3 - Alpha',
|
||||
'Intended Audience :: Developers',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Rust',
|
||||
'Operating System :: POSIX',
|
||||
'Operating System :: MacOS :: MacOS X',
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Programming Language :: Python",
|
||||
"Programming Language :: Rust",
|
||||
"Operating System :: POSIX",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
],
|
||||
packages=["rustapi_module"],
|
||||
rust_extensions=[
|
||||
RustExtension(
|
||||
"rustapi_module.othermod", "Cargo.toml", rustc_flags=get_py_version_cfgs()
|
||||
),
|
||||
RustExtension(
|
||||
"rustapi_module.datetime", "Cargo.toml", rustc_flags=get_py_version_cfgs()
|
||||
),
|
||||
RustExtension(
|
||||
"rustapi_module.subclassing",
|
||||
"Cargo.toml",
|
||||
rustc_flags=get_py_version_cfgs(),
|
||||
),
|
||||
],
|
||||
packages=['rustapi_module'],
|
||||
rust_extensions=[RustExtension('rustapi_module.othermod', 'Cargo.toml',
|
||||
rustc_flags=get_py_version_cfgs()),
|
||||
RustExtension('rustapi_module.datetime', 'Cargo.toml',
|
||||
rustc_flags=get_py_version_cfgs()),
|
||||
RustExtension('rustapi_module.subclassing', 'Cargo.toml',
|
||||
rustc_flags=get_py_version_cfgs())],
|
||||
install_requires=install_requires,
|
||||
tests_require=tests_require,
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
cmdclass=dict(test=PyTest)
|
||||
cmdclass=dict(test=PyTest),
|
||||
)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use pyo3::prelude::*;
|
||||
use pyo3::types::{
|
||||
PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess,
|
||||
PyTuple, PyTzInfo,
|
||||
PyDate, PyDateAccess, PyDateTime, PyDelta, PyDeltaAccess, PyTime, PyTimeAccess, PyTuple,
|
||||
PyTzInfo,
|
||||
};
|
||||
|
||||
#[pyfunction]
|
||||
|
|
|
@ -6,6 +6,6 @@ extern crate pyo3;
|
|||
use pyo3::prelude::*;
|
||||
use subclassing::Subclassable;
|
||||
|
||||
pub mod datetime;
|
||||
pub mod othermod;
|
||||
pub mod subclassing;
|
||||
pub mod datetime;
|
||||
|
|
|
@ -18,4 +18,3 @@ fn subclassing(_py: Python, m: &PyModule) -> PyResult<()> {
|
|||
m.add_class::<Subclassable>()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
import rustapi_module.datetime as rdt
|
||||
|
||||
import sys
|
||||
import datetime as pdt
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
import pytest
|
||||
import rustapi_module.datetime as rdt
|
||||
from hypothesis import given
|
||||
from hypothesis import strategies as st
|
||||
from hypothesis.strategies import dates, datetimes
|
||||
|
||||
|
||||
# Constants
|
||||
def _get_utc():
|
||||
timezone = getattr(pdt, 'timezone', None)
|
||||
timezone = getattr(pdt, "timezone", None)
|
||||
if timezone:
|
||||
return timezone.utc
|
||||
else:
|
||||
|
||||
class UTC(pdt.tzinfo):
|
||||
def utcoffset(self, dt):
|
||||
return pdt.timedelta(0)
|
||||
|
@ -26,6 +27,7 @@ def _get_utc():
|
|||
|
||||
return UTC()
|
||||
|
||||
|
||||
UTC = _get_utc()
|
||||
|
||||
MAX_SECONDS = int(pdt.timedelta.max.total_seconds())
|
||||
|
@ -42,19 +44,22 @@ except Exception:
|
|||
MAX_MICROSECONDS = int(pdt.timedelta.max.total_seconds() * 1e6)
|
||||
MIN_MICROSECONDS = int(pdt.timedelta.min.total_seconds() * 1e6)
|
||||
|
||||
HAS_FOLD = getattr(pdt.datetime, 'fold', False)
|
||||
|
||||
HAS_FOLD = getattr(pdt.datetime, "fold", False)
|
||||
|
||||
# Helper functions
|
||||
get_timestamp = getattr(pdt.datetime, 'timestamp', None)
|
||||
get_timestamp = getattr(pdt.datetime, "timestamp", None)
|
||||
if get_timestamp is None:
|
||||
|
||||
def get_timestamp(dt):
|
||||
# Python 2 compatibility
|
||||
return (dt - pdt.datetime(1970, 1, 1)).total_seconds()
|
||||
|
||||
|
||||
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_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",
|
||||
)
|
||||
|
||||
|
||||
# Tests
|
||||
def test_date():
|
||||
|
@ -81,11 +86,14 @@ def test_date_from_timestamp(d):
|
|||
assert rdt.date_from_timestamp(int(ts)) == pdt.date.fromtimestamp(ts)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args, kwargs', [
|
||||
((0, 0, 0, 0, None), {}),
|
||||
((1, 12, 14, 124731), {}),
|
||||
((1, 12, 14, 124731), {'tzinfo': UTC}),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args, kwargs",
|
||||
[
|
||||
((0, 0, 0, 0, None), {}),
|
||||
((1, 12, 14, 124731), {}),
|
||||
((1, 12, 14, 124731), {"tzinfo": UTC}),
|
||||
],
|
||||
)
|
||||
def test_time(args, kwargs):
|
||||
act = rdt.make_time(*args, **kwargs)
|
||||
exp = pdt.time(*args, **kwargs)
|
||||
|
@ -116,55 +124,58 @@ def test_time_fold(t):
|
|||
|
||||
|
||||
@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6")
|
||||
@pytest.mark.parametrize('fold', [False, True])
|
||||
@pytest.mark.parametrize("fold", [False, True])
|
||||
def test_time_fold(fold):
|
||||
t = rdt.time_with_fold(0, 0, 0, 0, None, fold)
|
||||
assert t.fold == fold
|
||||
|
||||
|
||||
@pytest.mark.xfail
|
||||
@pytest.mark.parametrize('args', [
|
||||
(-1, 0, 0, 0),
|
||||
(0, -1, 0, 0),
|
||||
(0, 0, -1, 0),
|
||||
(0, 0, 0, -1),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args", [(-1, 0, 0, 0), (0, -1, 0, 0), (0, 0, -1, 0), (0, 0, 0, -1)]
|
||||
)
|
||||
def test_invalid_time_fails_xfail(args):
|
||||
with pytest.raises(ValueError):
|
||||
rdt.make_time(*args)
|
||||
|
||||
|
||||
@xfail_date_bounds
|
||||
@pytest.mark.parametrize('args', [
|
||||
(24, 0, 0, 0),
|
||||
(25, 0, 0, 0),
|
||||
(0, 60, 0, 0),
|
||||
(0, 61, 0, 0),
|
||||
(0, 0, 60, 0),
|
||||
(0, 0, 61, 0),
|
||||
(0, 0, 0, 1000000)
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args",
|
||||
[
|
||||
(24, 0, 0, 0),
|
||||
(25, 0, 0, 0),
|
||||
(0, 60, 0, 0),
|
||||
(0, 61, 0, 0),
|
||||
(0, 0, 60, 0),
|
||||
(0, 0, 61, 0),
|
||||
(0, 0, 0, 1000000),
|
||||
],
|
||||
)
|
||||
def test_invalid_time_fails(args):
|
||||
with pytest.raises(ValueError):
|
||||
rdt.make_time(*args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args', [
|
||||
('0', 0, 0, 0),
|
||||
(0, '0', 0, 0),
|
||||
(0, 0, '0', 0),
|
||||
(0, 0, 0, '0'),
|
||||
(0, 0, 0, 0, 'UTC')
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args",
|
||||
[
|
||||
("0", 0, 0, 0),
|
||||
(0, "0", 0, 0),
|
||||
(0, 0, "0", 0),
|
||||
(0, 0, 0, "0"),
|
||||
(0, 0, 0, 0, "UTC"),
|
||||
],
|
||||
)
|
||||
def test_time_typeerror(args):
|
||||
with pytest.raises(TypeError):
|
||||
rdt.make_time(*args)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args, kwargs', [
|
||||
((2017, 9, 1, 12, 45, 30, 0), {}),
|
||||
((2017, 9, 1, 12, 45, 30, 0), {'tzinfo': UTC}),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args, kwargs",
|
||||
[((2017, 9, 1, 12, 45, 30, 0), {}), ((2017, 9, 1, 12, 45, 30, 0), {"tzinfo": UTC})],
|
||||
)
|
||||
def test_datetime(args, kwargs):
|
||||
act = rdt.make_datetime(*args, **kwargs)
|
||||
exp = pdt.datetime(*args, **kwargs)
|
||||
|
@ -176,7 +187,7 @@ def test_datetime(args, kwargs):
|
|||
@given(dt=st.datetimes())
|
||||
def test_datetime_tuple(dt):
|
||||
act = rdt.get_datetime_tuple(dt)
|
||||
exp = dt.timetuple()[0:6] + (dt.microsecond, )
|
||||
exp = dt.timetuple()[0:6] + (dt.microsecond,)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
@ -202,7 +213,7 @@ def test_invalid_datetime_fails():
|
|||
|
||||
def test_datetime_typeerror():
|
||||
with pytest.raises(TypeError):
|
||||
rdt.make_datetime('2011', 1, 1, 0, 0, 0, 0)
|
||||
rdt.make_datetime("2011", 1, 1, 0, 0, 0, 0)
|
||||
|
||||
|
||||
@given(dt=datetimes())
|
||||
|
@ -219,17 +230,20 @@ def test_datetime_from_timestamp_tzinfo():
|
|||
assert d1.tzinfo is d2.tzinfo
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args', [
|
||||
(0, 0, 0),
|
||||
(1, 0, 0),
|
||||
(-1, 0, 0),
|
||||
(0, 1, 0),
|
||||
(0, -1, 0),
|
||||
(1, -1, 0),
|
||||
(-1, 1, 0),
|
||||
(0, 0, 123456),
|
||||
(0, 0, -123456),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args",
|
||||
[
|
||||
(0, 0, 0),
|
||||
(1, 0, 0),
|
||||
(-1, 0, 0),
|
||||
(0, 1, 0),
|
||||
(0, -1, 0),
|
||||
(1, -1, 0),
|
||||
(-1, 1, 0),
|
||||
(0, 0, 123456),
|
||||
(0, 0, -123456),
|
||||
],
|
||||
)
|
||||
def test_delta(args):
|
||||
act = pdt.timedelta(*args)
|
||||
exp = rdt.make_delta(*args)
|
||||
|
@ -245,24 +259,29 @@ def test_delta_accessors(td):
|
|||
assert act == exp
|
||||
|
||||
|
||||
@pytest.mark.parametrize('args,err_type', [
|
||||
((MAX_DAYS + 1, 0, 0), OverflowError),
|
||||
((MIN_DAYS - 1, 0, 0), OverflowError),
|
||||
((0, MAX_SECONDS + 1, 0), OverflowError),
|
||||
((0, MIN_SECONDS - 1, 0), OverflowError),
|
||||
((0, 0, MAX_MICROSECONDS + 1), OverflowError),
|
||||
((0, 0, MIN_MICROSECONDS - 1), OverflowError),
|
||||
(('0', 0, 0), TypeError),
|
||||
((0, '0', 0), TypeError),
|
||||
((0, 0, '0'), TypeError),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
"args,err_type",
|
||||
[
|
||||
((MAX_DAYS + 1, 0, 0), OverflowError),
|
||||
((MIN_DAYS - 1, 0, 0), OverflowError),
|
||||
((0, MAX_SECONDS + 1, 0), OverflowError),
|
||||
((0, MIN_SECONDS - 1, 0), OverflowError),
|
||||
((0, 0, MAX_MICROSECONDS + 1), OverflowError),
|
||||
((0, 0, MIN_MICROSECONDS - 1), OverflowError),
|
||||
(("0", 0, 0), TypeError),
|
||||
((0, "0", 0), TypeError),
|
||||
((0, 0, "0"), TypeError),
|
||||
],
|
||||
)
|
||||
def test_delta_err(args, err_type):
|
||||
with pytest.raises(err_type):
|
||||
rdt.make_delta(*args)
|
||||
|
||||
|
||||
def test_issue_219():
|
||||
rdt.issue_219()
|
||||
|
||||
|
||||
def test_tz_class():
|
||||
tzi = rdt.TzClass()
|
||||
|
||||
|
@ -272,9 +291,9 @@ def test_tz_class():
|
|||
assert dt.utcoffset() == pdt.timedelta(hours=1)
|
||||
assert dt.dst() is None
|
||||
|
||||
|
||||
def test_tz_class_introspection():
|
||||
tzi = rdt.TzClass()
|
||||
|
||||
assert tzi.__class__ == rdt.TzClass
|
||||
assert repr(tzi).startswith('<rustapi_module.datetime.TzClass object at')
|
||||
|
||||
assert repr(tzi).startswith("<rustapi_module.datetime.TzClass object at")
|
||||
|
|
|
@ -1,24 +1,25 @@
|
|||
from rustapi_module import othermod
|
||||
|
||||
from hypothesis import given, assume
|
||||
from hypothesis import strategies as st
|
||||
from rustapi_module import othermod
|
||||
|
||||
INTEGER32_ST = st.integers(min_value=(-(2 ** 31)), max_value=(2 ** 31 - 1))
|
||||
USIZE_ST = st.integers(min_value=othermod.USIZE_MIN, max_value=othermod.USIZE_MAX)
|
||||
|
||||
INTEGER32_ST = st.integers(min_value=(-(2**31)), max_value=(2**31 - 1))
|
||||
USIZE_ST = st.integers(min_value=othermod.USIZE_MIN,
|
||||
max_value=othermod.USIZE_MAX)
|
||||
|
||||
@given(x=INTEGER32_ST)
|
||||
def test_double(x):
|
||||
expected = x*2
|
||||
assume(-(2**31) <= expected <= (2**31 - 1))
|
||||
expected = x * 2
|
||||
assume(-(2 ** 31) <= expected <= (2 ** 31 - 1))
|
||||
assert othermod.double(x) == expected
|
||||
|
||||
|
||||
def test_modclass():
|
||||
# Test that the repr of the class itself doesn't crash anything
|
||||
repr(othermod.ModClass)
|
||||
|
||||
assert isinstance(othermod.ModClass, type)
|
||||
|
||||
|
||||
def test_modclass_instance():
|
||||
mi = othermod.ModClass()
|
||||
|
||||
|
@ -28,9 +29,9 @@ def test_modclass_instance():
|
|||
assert isinstance(mi, othermod.ModClass)
|
||||
assert isinstance(mi, object)
|
||||
|
||||
|
||||
@given(x=USIZE_ST)
|
||||
def test_modclas_noop(x):
|
||||
mi = othermod.ModClass()
|
||||
|
||||
assert mi.noop(x) == x
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::ffi;
|
|||
use crate::instance;
|
||||
use crate::object::PyObject;
|
||||
use crate::objectprotocol::ObjectProtocol;
|
||||
use crate::python::{IntoPyPointer, Python, ToPyPointer, NonNullPyObject};
|
||||
use crate::python::{IntoPyPointer, NonNullPyObject, Python, ToPyPointer};
|
||||
use crate::pythonrun;
|
||||
use crate::typeob::PyTypeCreate;
|
||||
use crate::typeob::{PyTypeInfo, PyTypeObject};
|
||||
|
@ -122,8 +122,10 @@ impl<T> Py<T> {
|
|||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> Py<T> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => { Py(nonnull_ptr, std::marker::PhantomData) },
|
||||
None => { crate::err::panic_after_error(); }
|
||||
Some(nonnull_ptr) => Py(nonnull_ptr, std::marker::PhantomData),
|
||||
None => {
|
||||
crate::err::panic_after_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,8 +135,8 @@ impl<T> Py<T> {
|
|||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<Py<T>> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => { Ok(Py(nonnull_ptr, std::marker::PhantomData)) },
|
||||
None => { Err(PyErr::fetch(py)) }
|
||||
Some(nonnull_ptr) => Ok(Py(nonnull_ptr, std::marker::PhantomData)),
|
||||
None => Err(PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::conversion::{
|
|||
use crate::err::{PyDowncastError, PyErr, PyResult};
|
||||
use crate::ffi;
|
||||
use crate::instance::{AsPyRef, PyObjectWithToken};
|
||||
use crate::python::{IntoPyPointer, Python, ToPyPointer, NonNullPyObject};
|
||||
use crate::python::{IntoPyPointer, NonNullPyObject, Python, ToPyPointer};
|
||||
use crate::pythonrun;
|
||||
use crate::types::{PyDict, PyObjectRef, PyTuple};
|
||||
|
||||
|
@ -46,8 +46,10 @@ impl PyObject {
|
|||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(_py: Python, ptr: *mut ffi::PyObject) -> PyObject {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => { PyObject(nonnull_ptr) },
|
||||
None => { crate::err::panic_after_error(); }
|
||||
Some(nonnull_ptr) => PyObject(nonnull_ptr),
|
||||
None => {
|
||||
crate::err::panic_after_error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,8 +58,8 @@ impl PyObject {
|
|||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyObject> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => { Ok(PyObject(nonnull_ptr)) },
|
||||
None => { Err(PyErr::fetch(py)) }
|
||||
Some(nonnull_ptr) => Ok(PyObject(nonnull_ptr)),
|
||||
None => Err(PyErr::fetch(py)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,8 +68,8 @@ impl PyObject {
|
|||
/// Returns `None` if the pointer is `null`.
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject) -> Option<PyObject> {
|
||||
match NonNull::new(ptr) {
|
||||
Some(nonnull_ptr) => { Some(PyObject(nonnull_ptr)) },
|
||||
None => { None }
|
||||
Some(nonnull_ptr) => Some(PyObject(nonnull_ptr)),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ use crate::pythonrun::{self, GILGuard};
|
|||
use crate::typeob::PyTypeCreate;
|
||||
use crate::typeob::{PyTypeInfo, PyTypeObject};
|
||||
use crate::types::{PyDict, PyModule, PyObjectRef, PyType};
|
||||
use std;
|
||||
use std::ffi::CString;
|
||||
use std::marker::PhantomData;
|
||||
use std::os::raw::c_int;
|
||||
use std::ptr::NonNull;
|
||||
use std;
|
||||
|
||||
pub type NonNullPyObject = NonNull<ffi::PyObject>;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
use crate::ffi;
|
||||
use crate::python::{Python, NonNullPyObject};
|
||||
use crate::python::{NonNullPyObject, Python};
|
||||
use crate::types::PyObjectRef;
|
||||
use spin;
|
||||
use std::{any, marker, rc, sync};
|
||||
|
|
Loading…
Reference in a new issue