Merge pull request #200 from pganssle/datetime
Initial datetime bindings
This commit is contained in:
commit
3e7d5280ca
|
@ -38,7 +38,7 @@ before_install:
|
|||
- source ./ci/travis/setup.sh
|
||||
|
||||
install:
|
||||
- pip install setuptools-rust pytest pytest-benchmark
|
||||
- pip install setuptools-rust pytest pytest-benchmark tox
|
||||
|
||||
script:
|
||||
- ./ci/travis/test.sh
|
||||
|
|
|
@ -7,7 +7,11 @@ cargo test --features $FEATURES
|
|||
|
||||
for example in examples/*; do
|
||||
cd $example
|
||||
python setup.py install
|
||||
if [ -f tox.ini ]; then
|
||||
tox -e py
|
||||
else
|
||||
pip install -e .
|
||||
pytest -v tests
|
||||
fi
|
||||
cd $TRAVIS_BUILD_DIR
|
||||
done
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
.pytest_cache
|
||||
.mypy_cache
|
||||
.hypothesis
|
||||
.tox
|
||||
|
||||
*.py[co]
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
authors = ["PyO3 Authors"]
|
||||
name = "rustapi-module"
|
||||
version = "0.1.0"
|
||||
description = "A Python wrapper for the Rust API for purposes of testing"
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.pyo3]
|
||||
path = "../../"
|
||||
features = ["extension-module"]
|
||||
|
||||
[lib]
|
||||
name = "rustapi_module"
|
||||
crate-type = ["cdylib"]
|
|
@ -0,0 +1,2 @@
|
|||
[build-system]
|
||||
requires = ["setuptools", "wheel", "setuptools_rust>=0.10.2"]
|
|
@ -0,0 +1,3 @@
|
|||
hypothesis>=3.55
|
||||
pytest>=3.5.0
|
||||
setuptools-rust>=0.10.2
|
|
@ -0,0 +1,56 @@
|
|||
import sys
|
||||
|
||||
from setuptools import setup
|
||||
from setuptools.command.test import test as TestCommand
|
||||
from setuptools_rust import RustExtension
|
||||
|
||||
|
||||
class PyTest(TestCommand):
|
||||
user_options = []
|
||||
|
||||
def run(self):
|
||||
self.run_command("test_rust")
|
||||
|
||||
import subprocess
|
||||
errno = subprocess.call(['pytest', 'tests'])
|
||||
raise SystemExit(errno)
|
||||
|
||||
|
||||
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):
|
||||
out_cfg.append('--cfg=Py_3_%d' % minor)
|
||||
|
||||
return out_cfg
|
||||
|
||||
install_requires = []
|
||||
tests_require = install_requires + ['pytest', 'pytest-benchmark']
|
||||
|
||||
setup(
|
||||
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',
|
||||
],
|
||||
packages=['rustapi_module'],
|
||||
rust_extensions=[RustExtension('rustapi_module.datetime', '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)
|
||||
)
|
|
@ -0,0 +1,217 @@
|
|||
#![feature(specialization)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate pyo3;
|
||||
|
||||
use pyo3::prelude::PyDeltaAccess;
|
||||
use pyo3::prelude::PyModule;
|
||||
use pyo3::prelude::PyObject;
|
||||
use pyo3::prelude::{pyfunction, pymodinit};
|
||||
use pyo3::prelude::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo};
|
||||
use pyo3::prelude::{PyDateAccess, PyTimeAccess};
|
||||
use pyo3::prelude::{PyDict, PyTuple};
|
||||
use pyo3::{ObjectProtocol, ToPyObject};
|
||||
use pyo3::{Py, PyResult, Python};
|
||||
|
||||
#[pyfunction]
|
||||
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
|
||||
PyDate::new(py, year, month, day)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_date_tuple(py: Python, d: &PyDate) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[d.get_year(), d.get_month() as i32, d.get_day() as i32],
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn date_from_timestamp(py: Python, ts: i64) -> PyResult<Py<PyDate>> {
|
||||
let timestamp = ts.to_object(py);
|
||||
let args = PyTuple::new(py, &[timestamp]);
|
||||
PyDate::from_timestamp(py, &args.to_object(py))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn make_time(
|
||||
py: Python,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
PyTime::new(
|
||||
py,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
microsecond,
|
||||
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[pyfunction]
|
||||
fn time_with_fold(
|
||||
py: Python,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
fold: bool,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
PyTime::new_with_fold(
|
||||
py,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
microsecond,
|
||||
tzinfo.map(|o| o.to_object(py)).as_ref(),
|
||||
fold,
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_time_tuple(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
dt.get_hour() as u32,
|
||||
dt.get_minute() as u32,
|
||||
dt.get_second() as u32,
|
||||
dt.get_microsecond(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[pyfunction]
|
||||
fn get_time_tuple_fold(py: Python, dt: &PyTime) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
dt.get_hour() as u32,
|
||||
dt.get_minute() as u32,
|
||||
dt.get_second() as u32,
|
||||
dt.get_microsecond(),
|
||||
dt.get_fold() as u32,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn make_delta(py: Python, days: i32, seconds: i32, microseconds: i32) -> PyResult<Py<PyDelta>> {
|
||||
PyDelta::new(py, days, seconds, microseconds, true)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_delta_tuple(py: Python, delta: &PyDelta) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
delta.get_days(),
|
||||
delta.get_seconds(),
|
||||
delta.get_microseconds(),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn make_datetime(
|
||||
py: Python,
|
||||
year: i32,
|
||||
month: u8,
|
||||
day: u8,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyTzInfo>,
|
||||
) -> PyResult<Py<PyDateTime>> {
|
||||
PyDateTime::new(
|
||||
py,
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second,
|
||||
microsecond,
|
||||
tzinfo.map(|o| (o.to_object(py))).as_ref(),
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn get_datetime_tuple(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
dt.get_year(),
|
||||
dt.get_month() as i32,
|
||||
dt.get_day() as i32,
|
||||
dt.get_hour() as i32,
|
||||
dt.get_minute() as i32,
|
||||
dt.get_second() as i32,
|
||||
dt.get_microsecond() as i32,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[pyfunction]
|
||||
fn get_datetime_tuple_fold(py: Python, dt: &PyDateTime) -> Py<PyTuple> {
|
||||
PyTuple::new(
|
||||
py,
|
||||
&[
|
||||
dt.get_year(),
|
||||
dt.get_month() as i32,
|
||||
dt.get_day() as i32,
|
||||
dt.get_hour() as i32,
|
||||
dt.get_minute() as i32,
|
||||
dt.get_second() as i32,
|
||||
dt.get_microsecond() as i32,
|
||||
dt.get_fold() as i32,
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult<Py<PyDateTime>> {
|
||||
let timestamp: PyObject = ts.to_object(py);
|
||||
let tzi: PyObject = match tz {
|
||||
Some(t) => t.to_object(py),
|
||||
None => py.None(),
|
||||
};
|
||||
|
||||
let args = PyTuple::new(py, &[timestamp, tzi]);
|
||||
let kwargs = PyDict::new(py);
|
||||
|
||||
PyDateTime::from_timestamp(py, &args.to_object(py), &kwargs.to_object(py))
|
||||
}
|
||||
|
||||
#[pymodinit]
|
||||
fn datetime(_py: Python, m: &PyModule) -> PyResult<()> {
|
||||
m.add_function(wrap_function!(make_date))?;
|
||||
m.add_function(wrap_function!(get_date_tuple))?;
|
||||
m.add_function(wrap_function!(date_from_timestamp))?;
|
||||
m.add_function(wrap_function!(make_time))?;
|
||||
m.add_function(wrap_function!(get_time_tuple))?;
|
||||
m.add_function(wrap_function!(make_delta))?;
|
||||
m.add_function(wrap_function!(get_delta_tuple))?;
|
||||
m.add_function(wrap_function!(make_datetime))?;
|
||||
m.add_function(wrap_function!(get_datetime_tuple))?;
|
||||
m.add_function(wrap_function!(datetime_from_timestamp))?;
|
||||
|
||||
// Python 3.6+ functions
|
||||
#[cfg(Py_3_6)]
|
||||
{
|
||||
m.add_function(wrap_function!(time_with_fold));
|
||||
m.add_function(wrap_function!(get_time_tuple_fold));
|
||||
m.add_function(wrap_function!(get_datetime_tuple_fold));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,263 @@
|
|||
import rustapi_module.datetime as rdt
|
||||
|
||||
import sys
|
||||
import datetime as pdt
|
||||
|
||||
import pytest
|
||||
|
||||
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)
|
||||
if timezone:
|
||||
return timezone.utc
|
||||
else:
|
||||
class UTC(pdt.tzinfo):
|
||||
def utcoffset(self, dt):
|
||||
return pdt.timedelta(0)
|
||||
|
||||
def dst(self, dt):
|
||||
return pdt.timedelta(0)
|
||||
|
||||
def tzname(self, dt):
|
||||
return "UTC"
|
||||
|
||||
return UTC()
|
||||
|
||||
UTC = _get_utc()
|
||||
|
||||
MAX_SECONDS = int(pdt.timedelta.max.total_seconds())
|
||||
MIN_SECONDS = int(pdt.timedelta.min.total_seconds())
|
||||
|
||||
try:
|
||||
MAX_DAYS = pdt.timedelta.max // pdt.timedelta(days=1)
|
||||
MIN_DAYS = pdt.timedelta.min // pdt.timedelta(days=1)
|
||||
except Exception:
|
||||
# Python 2 compatibility
|
||||
MAX_DAYS = MAX_SECONDS // pdt.timedelta(days=1).total_seconds()
|
||||
MIN_DAYS = MIN_SECONDS // pdt.timedelta(days=1).total_seconds()
|
||||
|
||||
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)
|
||||
|
||||
|
||||
# Helper functions
|
||||
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")
|
||||
|
||||
# Tests
|
||||
def test_date():
|
||||
assert rdt.make_date(2017, 9, 1) == pdt.date(2017, 9, 1)
|
||||
|
||||
|
||||
@given(d=st.dates())
|
||||
def test_date_accessors(d):
|
||||
act = rdt.get_date_tuple(d)
|
||||
exp = (d.year, d.month, d.day)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
@xfail_date_bounds
|
||||
def test_invalid_date_fails():
|
||||
with pytest.raises(ValueError):
|
||||
rdt.make_date(2017, 2, 30)
|
||||
|
||||
|
||||
@given(d=dates())
|
||||
def test_date_from_timestamp(d):
|
||||
ts = get_timestamp(pdt.datetime.combine(d, pdt.time(0)))
|
||||
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}),
|
||||
])
|
||||
def test_time(args, kwargs):
|
||||
act = rdt.make_time(*args, **kwargs)
|
||||
exp = pdt.time(*args, **kwargs)
|
||||
|
||||
assert act == exp
|
||||
assert act.tzinfo is exp.tzinfo
|
||||
|
||||
|
||||
@given(t=st.times())
|
||||
def test_time(t):
|
||||
act = rdt.get_time_tuple(t)
|
||||
exp = (t.hour, t.minute, t.second, t.microsecond)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6")
|
||||
@given(t=st.times())
|
||||
def test_time_fold(t):
|
||||
t_nofold = t.replace(fold=0)
|
||||
t_fold = t.replace(fold=1)
|
||||
|
||||
for t in (t_nofold, t_fold):
|
||||
act = rdt.get_time_tuple_fold(t)
|
||||
exp = (t.hour, t.minute, t.second, t.microsecond, t.fold)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6")
|
||||
@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),
|
||||
])
|
||||
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)
|
||||
])
|
||||
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')
|
||||
])
|
||||
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}),
|
||||
])
|
||||
def test_datetime(args, kwargs):
|
||||
act = rdt.make_datetime(*args, **kwargs)
|
||||
exp = pdt.datetime(*args, **kwargs)
|
||||
|
||||
assert act == exp
|
||||
assert act.tzinfo is exp.tzinfo
|
||||
|
||||
|
||||
@given(dt=st.datetimes())
|
||||
def test_datetime_tuple(dt):
|
||||
act = rdt.get_datetime_tuple(dt)
|
||||
exp = dt.timetuple()[0:6] + (dt.microsecond, )
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
@pytest.mark.skipif(not HAS_FOLD, reason="Feature not available before 3.6")
|
||||
@given(dt=st.datetimes())
|
||||
def test_datetime_tuple_fold(dt):
|
||||
dt_fold = dt.replace(fold=1)
|
||||
dt_nofold = dt.replace(fold=0)
|
||||
|
||||
for dt in (dt_fold, dt_nofold):
|
||||
act = rdt.get_datetime_tuple_fold(dt)
|
||||
exp = dt.timetuple()[0:6] + (dt.microsecond, dt.fold)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def test_datetime_typeerror():
|
||||
with pytest.raises(TypeError):
|
||||
rdt.make_datetime('2011', 1, 1, 0, 0, 0, 0)
|
||||
|
||||
|
||||
@given(dt=datetimes())
|
||||
def test_datetime_from_timestamp(dt):
|
||||
ts = get_timestamp(dt)
|
||||
assert rdt.datetime_from_timestamp(ts) == pdt.datetime.fromtimestamp(ts)
|
||||
|
||||
|
||||
def test_datetime_from_timestamp_tzinfo():
|
||||
d1 = rdt.datetime_from_timestamp(0, tz=UTC)
|
||||
d2 = rdt.datetime_from_timestamp(0, tz=UTC)
|
||||
|
||||
assert d1 == d2
|
||||
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),
|
||||
])
|
||||
def test_delta(args):
|
||||
act = pdt.timedelta(*args)
|
||||
exp = rdt.make_delta(*args)
|
||||
|
||||
assert act == exp
|
||||
|
||||
|
||||
@given(td=st.timedeltas())
|
||||
def test_delta_accessors(td):
|
||||
act = rdt.get_delta_tuple(td)
|
||||
exp = (td.days, td.seconds, td.microseconds)
|
||||
|
||||
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),
|
||||
])
|
||||
def test_delta_err(args, err_type):
|
||||
with pytest.raises(err_type):
|
||||
rdt.make_delta(*args)
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[tox]
|
||||
envlist = py27,
|
||||
py35,
|
||||
py36,
|
||||
py37,
|
||||
minversion = 2.9.0
|
||||
skip_missing_interpreters = true
|
||||
|
||||
[testenv]
|
||||
description = Run the unit tests under {basepython}
|
||||
deps = -rrequirements-dev.txt
|
||||
usedevelop = True
|
||||
commands = pip install -e .
|
||||
pytest
|
|
@ -86,7 +86,7 @@ fn impl_class(
|
|||
let extra = if let Some(token) = token {
|
||||
Some(quote! {
|
||||
impl ::pyo3::PyObjectWithToken for #cls {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn py<'p>(&'p self) -> ::pyo3::Python<'p> {
|
||||
self.#token.py()
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ fn impl_class(
|
|||
}
|
||||
|
||||
impl ::pyo3::typeob::PyTypeObject for #cls {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn init_type() {
|
||||
static START: std::sync::Once = std::sync::ONCE_INIT;
|
||||
START.call_once(|| {
|
||||
|
|
|
@ -0,0 +1,410 @@
|
|||
#![cfg_attr(feature="cargo-clippy", allow(type_complexity))]
|
||||
|
||||
use ffi::PyCapsule_Import;
|
||||
use ffi::Py_hash_t;
|
||||
use ffi::{PyObject, PyTypeObject};
|
||||
use ffi::{PyObject_TypeCheck, Py_TYPE};
|
||||
use std::ffi::CString;
|
||||
use std::ops::Deref;
|
||||
use std::os::raw::{c_char, c_int, c_uchar};
|
||||
use std::ptr;
|
||||
use std::sync::Once;
|
||||
|
||||
#[cfg_attr(windows, link(name = "pythonXY"))]
|
||||
extern "C" {
|
||||
pub static mut PyDateTime_DateType: PyTypeObject;
|
||||
pub static mut PyDateTime_TimeType: PyTypeObject;
|
||||
pub static mut PyDateTime_DateTimeType: PyTypeObject;
|
||||
|
||||
pub static mut PyDateTime_DeltaType: PyTypeObject;
|
||||
pub static mut PyDateTime_TZInfoType: PyTypeObject;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyDateTime_CAPI {
|
||||
pub DateType: *mut PyTypeObject,
|
||||
pub DateTimeType: *mut PyTypeObject,
|
||||
pub TimeType: *mut PyTypeObject,
|
||||
pub DeltaType: *mut PyTypeObject,
|
||||
pub TZInfoType: *mut PyTypeObject,
|
||||
#[cfg(Py_3_7)]
|
||||
pub TimeZone_UTC: *mut PyObject,
|
||||
|
||||
pub Date_FromDate:
|
||||
unsafe extern "C" fn(year: c_int, month: c_int, day: c_int, cls: *mut PyTypeObject)
|
||||
-> *mut PyObject,
|
||||
pub DateTime_FromDateAndTime: unsafe extern "C" fn(
|
||||
year: c_int,
|
||||
month: c_int,
|
||||
day: c_int,
|
||||
hour: c_int,
|
||||
minute: c_int,
|
||||
second: c_int,
|
||||
microsecond: c_int,
|
||||
tzinfo: *mut PyObject,
|
||||
cls: *mut PyTypeObject,
|
||||
) -> *mut PyObject,
|
||||
pub Time_FromTime: unsafe extern "C" fn(
|
||||
hour: c_int,
|
||||
minute: c_int,
|
||||
second: c_int,
|
||||
microsecond: c_int,
|
||||
tzinfo: *mut PyObject,
|
||||
cls: *mut PyTypeObject,
|
||||
) -> *mut PyObject,
|
||||
pub Delta_FromDelta: unsafe extern "C" fn(
|
||||
days: c_int,
|
||||
seconds: c_int,
|
||||
microseconds: c_int,
|
||||
normalize: c_int,
|
||||
cls: *mut PyTypeObject,
|
||||
) -> *mut PyObject,
|
||||
#[cfg(Py_3_7)]
|
||||
pub TimeZone_FromTimeZone:
|
||||
unsafe extern "C" fn(offset: *mut PyObject, name: *mut PyObject) -> *mut PyObject,
|
||||
pub DateTime_FromTimestamp:
|
||||
unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject, kwargs: *mut PyObject)
|
||||
-> *mut PyObject,
|
||||
pub Date_FromTimestamp:
|
||||
unsafe extern "C" fn(cls: *mut PyTypeObject, args: *mut PyObject) -> *mut PyObject,
|
||||
#[cfg(Py_3_6)]
|
||||
pub DateTime_FromDateAndTimeAndFold: unsafe extern "C" fn(
|
||||
year: c_int,
|
||||
month: c_int,
|
||||
day: c_int,
|
||||
hour: c_int,
|
||||
minute: c_int,
|
||||
second: c_int,
|
||||
microsecond: c_int,
|
||||
tzinfo: *mut PyObject,
|
||||
fold: c_int,
|
||||
cls: *mut PyTypeObject,
|
||||
) -> *mut PyObject,
|
||||
#[cfg(Py_3_6)]
|
||||
pub Time_FromTimeAndFold: unsafe extern "C" fn(
|
||||
hour: c_int,
|
||||
minute: c_int,
|
||||
second: c_int,
|
||||
microsecond: c_int,
|
||||
tzinfo: *mut PyObject,
|
||||
fold: c_int,
|
||||
cls: *mut PyTypeObject,
|
||||
) -> *mut PyObject,
|
||||
}
|
||||
|
||||
// Type struct wrappers
|
||||
|
||||
const _PyDateTime_DATE_DATASIZE: usize = 4;
|
||||
const _PyDateTime_TIME_DATASIZE: usize = 6;
|
||||
const _PyDateTime_DATETIME_DATASIZE: usize = 10;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyDateTime_Date {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
pub hastzinfo: c_char,
|
||||
pub data: [c_uchar; _PyDateTime_DATE_DATASIZE],
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyDateTime_Time {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
pub hastzinfo: c_char,
|
||||
pub data: [c_uchar; _PyDateTime_TIME_DATASIZE],
|
||||
#[cfg(Py_3_6)]
|
||||
pub fold: c_uchar,
|
||||
pub tzinfo: *mut PyObject,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyDateTime_DateTime {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
pub hastzinfo: c_char,
|
||||
pub data: [c_uchar; _PyDateTime_DATETIME_DATASIZE],
|
||||
#[cfg(Py_3_6)]
|
||||
pub fold: c_uchar,
|
||||
pub tzinfo: *mut PyObject,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyDateTime_Delta {
|
||||
pub ob_base: PyObject,
|
||||
pub hashcode: Py_hash_t,
|
||||
pub days: c_int,
|
||||
pub seconds: c_int,
|
||||
pub microseconds: c_int,
|
||||
}
|
||||
|
||||
// C API Capsule
|
||||
// Note: This is "roll-your-own" lazy-static implementation is necessary because
|
||||
// of the interaction between the call_once locks and the GIL. It turns out that
|
||||
// calling PyCapsule_Import releases and re-acquires the GIL during the import,
|
||||
// so if you have two threads attempting to use the PyDateTimeAPI singleton
|
||||
// under the GIL, it causes a deadlock; what happens is:
|
||||
//
|
||||
// Thread 1 acquires GIL
|
||||
// Thread 1 acquires the call_once lock
|
||||
// Thread 1 calls PyCapsule_Import, thus releasing the GIL
|
||||
// Thread 2 acquires the GIL
|
||||
// Thread 2 blocks waiting for the call_once lock
|
||||
// Thread 1 blocks waiting for the GIL
|
||||
//
|
||||
// However, Python's import mechanism acquires a module-specific lock around
|
||||
// each import call, so all call importing datetime will return the same
|
||||
// object, making the call_once lock superfluous. As such, we can weaken
|
||||
// the guarantees of the cache, such that PyDateTime_IMPORT can be called
|
||||
// until __PY_DATETIME_API_UNSAFE_CACHE is populated, which will happen exactly
|
||||
// one time. So long as PyDateTime_IMPORT has no side effects (it should not),
|
||||
// this will be at most a slight waste of resources.
|
||||
static PY_DATETIME_API_ONCE: Once = Once::new();
|
||||
static mut PY_DATETIME_API_UNSAFE_CACHE: *const PyDateTime_CAPI = ptr::null();
|
||||
|
||||
pub struct PyDateTimeAPI {
|
||||
__private_field: (),
|
||||
}
|
||||
pub static PyDateTimeAPI: PyDateTimeAPI = PyDateTimeAPI {
|
||||
__private_field: (),
|
||||
};
|
||||
|
||||
impl Deref for PyDateTimeAPI {
|
||||
type Target = PyDateTime_CAPI;
|
||||
|
||||
fn deref(&self) -> &'static PyDateTime_CAPI {
|
||||
unsafe {
|
||||
if !PY_DATETIME_API_UNSAFE_CACHE.is_null() {
|
||||
&(*PY_DATETIME_API_UNSAFE_CACHE)
|
||||
} else {
|
||||
PyDateTime_IMPORT()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_IMPORT() -> &'static PyDateTime_CAPI {
|
||||
// PyDateTime_CAPSULE_NAME is a macro in C
|
||||
let PyDateTime_CAPSULE_NAME = CString::new("datetime.datetime_CAPI").unwrap();
|
||||
|
||||
let capsule = PyCapsule_Import(PyDateTime_CAPSULE_NAME.as_ptr(), 1) as *const PyDateTime_CAPI;
|
||||
|
||||
PY_DATETIME_API_ONCE.call_once(move || {
|
||||
PY_DATETIME_API_UNSAFE_CACHE = capsule;
|
||||
});
|
||||
|
||||
&(*PY_DATETIME_API_UNSAFE_CACHE)
|
||||
}
|
||||
|
||||
//
|
||||
// Type Check macros
|
||||
//
|
||||
#[inline]
|
||||
pub unsafe fn PyDate_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDate_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DateType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DateTimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DateTimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyTime_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.TimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyTime_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.TimeType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDelta_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.DeltaType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDelta_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.DeltaType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyTZInfo_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, PyDateTimeAPI.TZInfoType) as c_int
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyTZInfo_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == PyDateTimeAPI.TZInfoType) as c_int
|
||||
}
|
||||
|
||||
//
|
||||
// Accessor functions
|
||||
//
|
||||
macro_rules! _access_field {
|
||||
($obj:expr, $type: ident, $field:tt) => {
|
||||
(*($obj as *mut $type)).$field
|
||||
};
|
||||
}
|
||||
|
||||
// Accessor functions for PyDateTime_Date and PyDateTime_DateTime
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_GET_YEAR(o: *mut PyObject) -> c_int {
|
||||
// This should work for Date or DateTime
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
(c_int::from(d.data[0]) << 8 | c_int::from(d.data[1]))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_GET_MONTH(o: *mut PyObject) -> c_int {
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
c_int::from(d.data[2])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_GET_DAY(o: *mut PyObject) -> c_int {
|
||||
let d = *(o as *mut PyDateTime_Date);
|
||||
c_int::from(d.data[3])
|
||||
}
|
||||
|
||||
// Accessor macros for times
|
||||
macro_rules! _PyDateTime_GET_HOUR {
|
||||
($o: expr, $offset:expr) => {
|
||||
c_int::from((*$o).data[$offset + 0])
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! _PyDateTime_GET_MINUTE {
|
||||
($o: expr, $offset:expr) => {
|
||||
c_int::from((*$o).data[$offset + 1])
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! _PyDateTime_GET_SECOND {
|
||||
($o: expr, $offset:expr) => {
|
||||
c_int::from((*$o).data[$offset + 2])
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! _PyDateTime_GET_MICROSECOND {
|
||||
($o: expr, $offset:expr) => {
|
||||
(c_int::from((*$o).data[$offset + 3]) << 16)
|
||||
| (c_int::from((*$o).data[$offset + 4]) << 8)
|
||||
| (c_int::from((*$o).data[$offset + 5]))
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
macro_rules! _PyDateTime_GET_FOLD {
|
||||
($o: expr) => {
|
||||
(*$o).fold
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! _PyDateTime_GET_TZINFO {
|
||||
($o: expr) => {
|
||||
(*$o).tzinfo
|
||||
};
|
||||
}
|
||||
|
||||
// Accessor functions for DateTime
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DATE_GET_HOUR(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DATE_GET_MINUTE(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DATE_GET_SECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_DateTime), _PyDateTime_DATE_DATASIZE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
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]
|
||||
pub unsafe fn PyDateTime_DATE_GET_FOLD(o: *mut PyObject) -> c_uchar {
|
||||
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_DateTime)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DATE_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
|
||||
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_DateTime)
|
||||
}
|
||||
|
||||
// Accessor functions for Time
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_HOUR(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_HOUR!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_MINUTE(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MINUTE!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_SECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_SECOND!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_MICROSECOND(o: *mut PyObject) -> c_int {
|
||||
_PyDateTime_GET_MICROSECOND!((o as *mut PyDateTime_Time), 0)
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_FOLD(o: *mut PyObject) -> c_uchar {
|
||||
_PyDateTime_GET_FOLD!(o as *mut PyDateTime_Time)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_TIME_GET_TZINFO(o: *mut PyObject) -> *mut PyObject {
|
||||
_PyDateTime_GET_TZINFO!(o as *mut PyDateTime_Time)
|
||||
}
|
||||
|
||||
// Accessor functions for PyDateTime_Delta
|
||||
macro_rules! _access_delta_field {
|
||||
($obj:expr, $field:tt) => {
|
||||
_access_field!($obj, PyDateTime_Delta, $field)
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DELTA_GET_DAYS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, days)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DELTA_GET_SECONDS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, seconds)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyDateTime_DELTA_GET_MICROSECONDS(o: *mut PyObject) -> c_int {
|
||||
_access_delta_field!(o, microseconds)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
|
||||
|
||||
#[cfg(not(Py_3))]
|
||||
pub use ffi2::*;
|
||||
|
||||
#[cfg(Py_3)]
|
||||
pub use ffi3::*;
|
||||
|
||||
pub use self::datetime::*;
|
||||
|
||||
pub(crate) mod datetime;
|
|
@ -12,18 +12,18 @@ extern "C" {
|
|||
pub fn PyBool_FromLong(arg1: c_long) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyBool_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_False() -> *mut PyObject {
|
||||
&mut _Py_ZeroStruct as *mut PyBoolObject as *mut PyObject
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_True() -> *mut PyObject {
|
||||
&mut _Py_TrueStruct as *mut PyBoolObject as *mut PyObject
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
pub static mut PyBuffer_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBuffer_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyBuffer_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -42,7 +42,7 @@ extern "C" {
|
|||
pub fn PyByteArray_Resize(bytearray: *mut PyObject, len: Py_ssize_t) -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyByteArray_AS_STRING(o: *mut PyObject) -> *mut c_char {
|
||||
PyByteArray_AsString(o)
|
||||
// #define PyByteArray_AS_STRING(self) \
|
||||
|
@ -50,7 +50,7 @@ pub unsafe fn PyByteArray_AS_STRING(o: *mut PyObject) -> *mut c_char {
|
|||
// Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_bytes : _PyByteArray_empty_string)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyByteArray_GET_SIZE(o: *mut PyObject) -> Py_ssize_t {
|
||||
// #define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)),Py_SIZE(self))
|
||||
PyByteArray_Size(o)
|
||||
|
|
|
@ -19,7 +19,7 @@ extern "C" {
|
|||
pub static mut PyCell_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCell_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCell_Type) as c_int
|
||||
}
|
||||
|
@ -31,12 +31,12 @@ extern "C" {
|
|||
pub fn PyCell_Set(op: *mut PyObject, obj: *mut PyObject) -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCell_GET(op: *mut PyObject) -> *mut PyObject {
|
||||
(*(op as *mut PyCellObject)).ob_ref
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCell_SET(op: *mut PyObject, obj: *mut PyObject) {
|
||||
(*(op as *mut PyCellObject)).ob_ref = obj;
|
||||
}
|
||||
|
|
|
@ -56,19 +56,19 @@ extern "C" {
|
|||
pub static mut PyMethod_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyClass_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyClass_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyInstance_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyInstance_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMethod_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyMethod_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
@ -100,17 +100,17 @@ extern "C" {
|
|||
pub fn PyMethod_ClearFreeList() -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMethod_GET_FUNCTION(meth: *mut PyObject) -> *mut PyObject {
|
||||
(*(meth as *mut PyMethodObject)).im_func
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMethod_GET_SELF(meth: *mut PyObject) -> *mut PyObject {
|
||||
(*(meth as *mut PyMethodObject)).im_self
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMethod_GET_CLASS(meth: *mut PyObject) -> *mut PyObject {
|
||||
(*(meth as *mut PyMethodObject)).im_class
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
pub static mut PyCObject_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCObject_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCObject_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ extern "C" {
|
|||
) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCode_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ extern "C" {
|
|||
pub static mut PyComplex_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyComplex_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyComplex_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -86,7 +86,7 @@ extern "C" {
|
|||
) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDescr_IsData(d: *mut PyObject) -> c_int {
|
||||
(*Py_TYPE(d)).tp_descr_set.is_some() as c_int
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ extern "C" {
|
|||
pub static mut PyDictValues_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyDict_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -7,12 +7,12 @@ extern "C" {
|
|||
pub static mut PyFile_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFile_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyFile_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFile_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyFile_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -19,12 +19,12 @@ extern "C" {
|
|||
pub static mut PyFloat_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyFloat_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyFloat_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
pub static mut PyFunction_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFunction_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyFunction_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -23,12 +23,12 @@ extern "C" {
|
|||
pub static mut PyGen_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyGen_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyGen_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@ extern "C" {
|
|||
pub static mut PyInt_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyInt_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_INT_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyInt_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyInt_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -10,12 +10,12 @@ extern "C" {
|
|||
pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PySeqIter_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCallIter_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -21,30 +21,30 @@ extern "C" {
|
|||
pub static mut PyList_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyList_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
// Macro, trading safety for speed
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {
|
||||
*(*(op as *mut PyListObject)).ob_item.offset(i as isize)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
|
||||
Py_SIZE(op)
|
||||
}
|
||||
|
||||
/// Macro, *only* to be used to fill in brand new lists
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {
|
||||
*(*(op as *mut PyListObject)).ob_item.offset(i as isize) = v;
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ extern "C" {
|
|||
pub static mut PyLong_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyLong_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -7,18 +7,18 @@ extern "C" {
|
|||
pub static mut PyMemoryView_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyMemoryView_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMemoryView_GET_BUFFER(op: *mut PyObject) -> *mut Py_buffer {
|
||||
&mut (*(op as *mut PyMemoryViewObject)).view
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMemoryView_GET_BASE(op: *mut PyObject) -> *mut PyObject {
|
||||
(*(op as *mut PyMemoryViewObject)).view.obj
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
pub static mut PyCFunction_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyCFunction_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
@ -119,7 +119,7 @@ extern "C" {
|
|||
pub fn PyCFunction_ClearFreeList() -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject {
|
||||
PyCFunction_NewEx(ml, slf, ptr::null_mut())
|
||||
}
|
||||
|
|
|
@ -132,13 +132,13 @@ pub const Py_file_input: c_int = 257;
|
|||
pub const Py_eval_input: c_int = 258;
|
||||
|
||||
#[cfg(not(py_sys_config = "Py_USING_UNICODE"))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn PyUnicode_Check(op: *mut PyObject) -> libc::c_int {
|
||||
0
|
||||
}
|
||||
|
||||
#[cfg(not(py_sys_config = "Py_USING_UNICODE"))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub fn PyUnicode_CheckExact(op: *mut PyObject) -> libc::c_int {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ pub const PYTHON_API_VERSION: c_int = 1013;
|
|||
target_pointer_width = "64",
|
||||
not(py_sys_config = "Py_TRACE_REFS")
|
||||
))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_InitModule4(
|
||||
name: *const c_char,
|
||||
methods: *mut PyMethodDef,
|
||||
|
@ -107,7 +107,7 @@ pub unsafe fn Py_InitModule4(
|
|||
}
|
||||
|
||||
#[cfg(all(target_pointer_width = "64", py_sys_config = "Py_TRACE_REFS"))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_InitModule4(
|
||||
name: *const c_char,
|
||||
methods: *mut PyMethodDef,
|
||||
|
@ -122,7 +122,7 @@ pub unsafe fn Py_InitModule4(
|
|||
not(target_pointer_width = "64"),
|
||||
py_sys_config = "Py_TRACE_REFS"
|
||||
))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_InitModule4(
|
||||
name: *const c_char,
|
||||
methods: *mut PyMethodDef,
|
||||
|
@ -133,7 +133,7 @@ pub unsafe fn Py_InitModule4(
|
|||
Py_InitModule4TraceRefs(name, methods, doc, _self, apiver)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_InitModule(name: *const c_char, methods: *mut PyMethodDef) -> *mut PyObject {
|
||||
Py_InitModule4(
|
||||
name,
|
||||
|
@ -144,7 +144,7 @@ pub unsafe fn Py_InitModule(name: *const c_char, methods: *mut PyMethodDef) -> *
|
|||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_InitModule3(
|
||||
name: *const c_char,
|
||||
methods: *mut PyMethodDef,
|
||||
|
|
|
@ -8,12 +8,12 @@ extern "C" {
|
|||
pub static mut PyModule_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyModule_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyModule_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::os::raw::{c_char, c_double, c_int, c_long, c_uint, c_void};
|
|||
use std::ptr;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct PyObject {
|
||||
#[cfg(py_sys_config = "Py_TRACE_REFS")]
|
||||
pub _ob_next: *mut PyObject,
|
||||
|
@ -37,17 +37,17 @@ pub struct PyVarObject {
|
|||
pub ob_size: Py_ssize_t,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
|
||||
(*ob).ob_refcnt
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
|
||||
(*ob).ob_type
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
|
||||
(*(ob as *mut PyVarObject)).ob_size
|
||||
}
|
||||
|
@ -564,7 +564,7 @@ extern "C" {
|
|||
pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
|
||||
(Py_TYPE(ob) == tp || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int
|
||||
}
|
||||
|
@ -576,12 +576,12 @@ extern "C" {
|
|||
pub static mut PySuper_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == (&mut PyType_Type as *mut _)) as c_int
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ extern "C" {
|
|||
pub fn PyObject_Str(o: *mut PyObject) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_Bytes(o: *mut PyObject) -> *mut PyObject {
|
||||
PyObject_Str(o)
|
||||
}
|
||||
|
@ -755,18 +755,18 @@ pub const Py_TPFLAGS_DEFAULT: c_long = (Py_TPFLAGS_HAVE_GETCHARBUFFER
|
|||
| Py_TPFLAGS_HAVE_INDEX
|
||||
| 0);
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_long) -> c_int {
|
||||
(((*t).tp_flags & f) != 0) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_long) -> c_int {
|
||||
PyType_HasFeature(t, f)
|
||||
}
|
||||
|
||||
// Reference counting macros.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
||||
if cfg!(py_sys_config = "Py_REF_DEBUG") {
|
||||
Py_IncRef(op)
|
||||
|
@ -775,7 +775,7 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
||||
if cfg!(py_sys_config = "Py_REF_DEBUG") || cfg!(py_sys_config = "COUNT_ALLOCS") {
|
||||
Py_DecRef(op)
|
||||
|
@ -787,7 +787,7 @@ pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_CLEAR(op: &mut *mut PyObject) {
|
||||
let tmp = *op;
|
||||
if !tmp.is_null() {
|
||||
|
@ -796,14 +796,14 @@ pub unsafe fn Py_CLEAR(op: &mut *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_XINCREF(op: *mut PyObject) {
|
||||
if !op.is_null() {
|
||||
Py_INCREF(op)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_XDECREF(op: *mut PyObject) {
|
||||
if !op.is_null() {
|
||||
Py_DECREF(op)
|
||||
|
@ -819,12 +819,12 @@ extern "C" {
|
|||
static mut _Py_NotImplementedStruct: PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_None() -> *mut PyObject {
|
||||
&mut _Py_NoneStruct
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_NotImplemented() -> *mut PyObject {
|
||||
&mut _Py_NotImplementedStruct
|
||||
}
|
||||
|
@ -855,7 +855,7 @@ extern "C" {
|
|||
|
||||
pub const PyTrash_UNWIND_LEVEL: c_int = 50;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_TRASHCAN<F: FnOnce() -> ()>(op: *mut PyObject, body: F) {
|
||||
let tstate = ffi2::pystate::PyThreadState_GET();
|
||||
if tstate.is_null() || (*tstate).trash_delete_nesting < PyTrash_UNWIND_LEVEL {
|
||||
|
|
|
@ -30,14 +30,14 @@ extern "C" {
|
|||
}
|
||||
|
||||
/// Test if a type has a GC head
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[allow(unused_parens)]
|
||||
pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
|
||||
PyType_HasFeature((t), Py_TPFLAGS_HAVE_GC)
|
||||
}
|
||||
|
||||
/// Test if an object has a GC head
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
|
||||
(PyType_IS_GC(Py_TYPE(o)) != 0 && match (*Py_TYPE(o)).tp_is_gc {
|
||||
Some(tp_is_gc) => tp_is_gc(o) != 0,
|
||||
|
@ -46,13 +46,13 @@ pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
|
|||
}
|
||||
|
||||
/* Test if a type supports weak references */
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[allow(unused_parens)]
|
||||
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
|
||||
(PyType_HasFeature((t), Py_TPFLAGS_HAVE_WEAKREFS) != 0 && ((*t).tp_weaklistoffset > 0)) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
|
||||
let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset as isize;
|
||||
(o as *mut c_char).offset(weaklistoffset) as *mut *mut PyObject
|
||||
|
|
|
@ -92,13 +92,13 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[cfg(py_sys_config = "Py_DEBUG")]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyThreadState_GET() -> *mut PyThreadState {
|
||||
PyThreadState_Get()
|
||||
}
|
||||
|
||||
#[cfg(not(py_sys_config = "Py_DEBUG"))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyThreadState_GET() -> *mut PyThreadState {
|
||||
_PyThreadState_Current
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ extern "C" {
|
|||
pub static mut PyRange_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyRange_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
static mut _Py_EllipsisObject: PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_Ellipsis() -> *mut PyObject {
|
||||
&mut _Py_EllipsisObject
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ extern "C" {
|
|||
pub static mut PyEllipsis_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PySlice_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@ extern "C" {
|
|||
pub static mut PyString_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyString_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_STRING_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBaseString_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(
|
||||
Py_TYPE(op),
|
||||
|
@ -36,18 +36,18 @@ pub unsafe fn PyBaseString_Check(op: *mut PyObject) -> c_int {
|
|||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyString_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyString_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyString_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
|
||||
(*(op as *mut PyStringObject)).ob_size
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyString_AS_STRING(op: *mut PyObject) -> *mut c_char {
|
||||
(*(op as *mut PyStringObject)).ob_sval.as_mut_ptr()
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
|||
pub static mut PyTraceBack_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyTraceBack_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -20,19 +20,19 @@ extern "C" {
|
|||
pub static mut PyTuple_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyTuple_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
// Macro, trading safety for speed
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {
|
||||
*(*(op as *mut PyTupleObject))
|
||||
.ob_item
|
||||
|
@ -40,13 +40,13 @@ pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObjec
|
|||
.offset(i as isize)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
|
||||
Py_SIZE(op)
|
||||
}
|
||||
|
||||
/// Macro, *only* to be used to fill in brand new tuples
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {
|
||||
*(*(op as *mut PyTupleObject))
|
||||
.ob_item
|
||||
|
|
|
@ -35,33 +35,33 @@ extern "C" {
|
|||
pub static mut PyUnicode_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int {
|
||||
let u: *mut PyTypeObject = &mut PyUnicode_Type;
|
||||
(Py_TYPE(op) == u) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_GET_SIZE(o: *mut PyObject) -> Py_ssize_t {
|
||||
(*(o as *mut PyUnicodeObject)).length
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_GET_DATA_SIZE(o: *mut PyObject) -> Py_ssize_t {
|
||||
(*(o as *mut PyUnicodeObject)).length * Py_UNICODE_SIZE
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_AS_UNICODE(o: *mut PyObject) -> *mut Py_UNICODE {
|
||||
(*(o as *mut PyUnicodeObject)).data
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_AS_DATA(o: *mut PyObject) -> *const c_char {
|
||||
(*(o as *mut PyUnicodeObject)).data as *const c_char
|
||||
}
|
||||
|
@ -642,31 +642,31 @@ extern "C" {
|
|||
fn _PyUnicodeUCS2_IsAlpha(ch: Py_UNICODE) -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(py_sys_config = "Py_UNICODE_SIZE_4")]
|
||||
pub unsafe fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject {
|
||||
PyUnicodeUCS4_FromStringAndSize(u, size)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(py_sys_config = "Py_UNICODE_SIZE_4"))]
|
||||
pub unsafe fn PyUnicode_FromStringAndSize(u: *const c_char, size: Py_ssize_t) -> *mut PyObject {
|
||||
PyUnicodeUCS2_FromStringAndSize(u, size)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(py_sys_config = "Py_UNICODE_SIZE_4")]
|
||||
pub unsafe fn PyUnicode_AsUTF8String(u: *mut PyObject) -> *mut PyObject {
|
||||
PyUnicodeUCS4_AsUTF8String(u)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(py_sys_config = "Py_UNICODE_SIZE_4"))]
|
||||
pub unsafe fn PyUnicode_AsUTF8String(u: *mut PyObject) -> *mut PyObject {
|
||||
PyUnicodeUCS2_AsUTF8String(u)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(py_sys_config = "Py_UNICODE_SIZE_4")]
|
||||
pub unsafe fn PyUnicode_FromEncodedObject(
|
||||
obj: *mut PyObject,
|
||||
|
@ -676,7 +676,7 @@ pub unsafe fn PyUnicode_FromEncodedObject(
|
|||
PyUnicodeUCS4_FromEncodedObject(obj, encoding, errors)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(py_sys_config = "Py_UNICODE_SIZE_4"))]
|
||||
pub unsafe fn PyUnicode_FromEncodedObject(
|
||||
obj: *mut PyObject,
|
||||
|
|
|
@ -25,23 +25,23 @@ extern "C" {
|
|||
static mut _PyWeakref_CallableProxyType: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut _PyWeakref_RefType)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut _PyWeakref_RefType) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int {
|
||||
((Py_TYPE(op) == &mut _PyWeakref_ProxyType)
|
||||
|| (Py_TYPE(op) == &mut _PyWeakref_CallableProxyType)) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_Check(op: *mut PyObject) -> c_int {
|
||||
(PyWeakref_CheckRef(op) != 0 || PyWeakref_CheckProxy(op) != 0) as c_int
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ extern "C" {
|
|||
pub fn _PyWeakref_ClearRef(slf: *mut PyWeakReference);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_GET_OBJECT(_ref: *mut PyObject) -> *mut PyObject {
|
||||
let obj = (*(_ref as *mut PyWeakReference)).wr_object;
|
||||
if Py_REFCNT(obj) > 0 {
|
||||
|
|
|
@ -10,17 +10,17 @@ extern "C" {
|
|||
pub fn PyBool_FromLong(arg1: c_long) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBool_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyBool_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_False() -> *mut PyObject {
|
||||
&mut _Py_FalseStruct as *mut PyLongObject as *mut PyObject
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_True() -> *mut PyObject {
|
||||
&mut _Py_TrueStruct as *mut PyLongObject as *mut PyObject
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ extern "C" {
|
|||
pub static mut PyByteArrayIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyByteArray_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyByteArray_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyByteArray_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyByteArray_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ extern "C" {
|
|||
pub static mut PyBytesIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBytes_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_BYTES_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyBytes_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyBytes_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ extern "C" {
|
|||
pub static mut PyComplex_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyComplex_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyComplex_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyComplex_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyComplex_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -13,32 +13,32 @@ extern "C" {
|
|||
pub static mut PyDictValues_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDict_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_DICT_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDict_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyDict_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDictKeys_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyDictKeys_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDictItems_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyDictItems_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDictValues_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyDictValues_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyDictViewSet_Check(op: *mut PyObject) -> c_int {
|
||||
(PyDictKeys_Check(op) != 0 || PyDictItems_Check(op) != 0) as c_int
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ extern "C" {
|
|||
pub static mut PyFloat_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFloat_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyFloat_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyFloat_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyFloat_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -23,12 +23,12 @@ extern "C" {
|
|||
pub static mut PyGen_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyGen_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyGen_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyGen_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyGen_Type) as c_int
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ extern "C" {
|
|||
pub static mut PyCoro_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCoro_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyCoro_Type)
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ extern "C" {
|
|||
pub static mut _PyCoroWrapper_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCoroWrapper_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut _PyCoroWrapper_Type)
|
||||
}
|
||||
|
@ -66,13 +66,13 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyAsyncGen_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyAsyncGen_Type)
|
||||
}
|
||||
|
||||
#[cfg(not(Py_3_6))]
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyAsyncGen_Check(_op: *mut PyObject) -> c_int {
|
||||
0
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ extern "C" {
|
|||
pub fn PyCallIter_New(arg1: *mut PyObject, arg2: *mut PyObject) -> *mut PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PySeqIter_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PySeqIter_Type) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCallIter_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCallIter_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ extern "C" {
|
|||
pub static mut PyListRevIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LIST_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyList_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyList_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ extern "C" {
|
|||
pub static mut PyLong_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyLong_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_LONG_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyLong_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyLong_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
pub static mut PyMemoryView_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyMemoryView_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyMemoryView_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
pub static mut PyCFunction_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyCFunction_Type) as c_int
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ impl Default for PyMethodDef {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyCFunction_New(ml: *mut PyMethodDef, slf: *mut PyObject) -> *mut PyObject {
|
||||
PyCFunction_NewEx(ml, slf, ptr::null_mut())
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ extern "C" {
|
|||
pub static mut PyModule_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyModule_Check(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut PyModule_Type)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyModule_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyModule_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ pub struct PyVarObject {
|
|||
pub ob_size: Py_ssize_t,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
|
||||
if ob.is_null() {
|
||||
panic!();
|
||||
|
@ -42,12 +42,12 @@ pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
|
|||
(*ob).ob_refcnt
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_TYPE(ob: *mut PyObject) -> *mut PyTypeObject {
|
||||
(*ob).ob_type
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_SIZE(ob: *mut PyObject) -> Py_ssize_t {
|
||||
(*(ob as *mut PyVarObject)).ob_size
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ extern "C" {
|
|||
pub fn PyType_IsSubtype(a: *mut PyTypeObject, b: *mut PyTypeObject) -> c_int;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_TypeCheck(ob: *mut PyObject, tp: *mut PyTypeObject) -> c_int {
|
||||
(Py_TYPE(ob) == tp || PyType_IsSubtype(Py_TYPE(ob), tp) != 0) as c_int
|
||||
}
|
||||
|
@ -633,12 +633,12 @@ extern "C" {
|
|||
pub fn PyType_GetFlags(arg1: *mut PyTypeObject) -> c_ulong;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TYPE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyType_Type) as c_int
|
||||
}
|
||||
|
@ -753,19 +753,19 @@ pub const Py_TPFLAGS_DEFAULT: c_ulong =
|
|||
|
||||
pub const Py_TPFLAGS_HAVE_FINALIZE: c_ulong = 1;
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(Py_LIMITED_API)]
|
||||
pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_ulong) -> c_int {
|
||||
((PyType_GetFlags(t) & f) != 0) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyType_HasFeature(t: *mut PyTypeObject, f: c_ulong) -> c_int {
|
||||
(((*t).tp_flags & f) != 0) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyType_FastSubclass(t: *mut PyTypeObject, f: c_ulong) -> c_int {
|
||||
PyType_HasFeature(t, f)
|
||||
}
|
||||
|
@ -776,7 +776,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// Reference counting macros.
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
||||
if cfg!(py_sys_config = "Py_REF_DEBUG") {
|
||||
Py_IncRef(op)
|
||||
|
@ -785,7 +785,7 @@ pub unsafe fn Py_INCREF(op: *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
||||
if cfg!(py_sys_config = "Py_REF_DEBUG") {
|
||||
Py_DecRef(op)
|
||||
|
@ -797,7 +797,7 @@ pub unsafe fn Py_DECREF(op: *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_CLEAR(op: &mut *mut PyObject) {
|
||||
let tmp = *op;
|
||||
if !tmp.is_null() {
|
||||
|
@ -806,14 +806,14 @@ pub unsafe fn Py_CLEAR(op: &mut *mut PyObject) {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_XINCREF(op: *mut PyObject) {
|
||||
if !op.is_null() {
|
||||
Py_INCREF(op)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_XDECREF(op: *mut PyObject) {
|
||||
if !op.is_null() {
|
||||
Py_DECREF(op)
|
||||
|
@ -829,12 +829,12 @@ extern "C" {
|
|||
static mut _Py_NotImplementedStruct: PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_None() -> *mut PyObject {
|
||||
&mut _Py_NoneStruct
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_NotImplemented() -> *mut PyObject {
|
||||
&mut _Py_NotImplementedStruct
|
||||
}
|
||||
|
|
|
@ -48,14 +48,14 @@ extern "C" {
|
|||
}
|
||||
|
||||
/// Test if a type has a GC head
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[allow(unused_parens)]
|
||||
pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
|
||||
PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC)
|
||||
}
|
||||
|
||||
/// Test if an object has a GC head
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
|
||||
(PyType_IS_GC(Py_TYPE(o)) != 0 && match (*Py_TYPE(o)).tp_is_gc {
|
||||
|
@ -80,13 +80,13 @@ extern "C" {
|
|||
}
|
||||
|
||||
/// Test if a type supports weak references
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
|
||||
((*t).tp_weaklistoffset > 0) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
|
||||
let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset as isize;
|
||||
|
|
|
@ -58,7 +58,7 @@ extern "C" {
|
|||
pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyThreadState_GET() -> *mut PyThreadState {
|
||||
PyThreadState_Get()
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
pub static mut PyLongRangeIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyRange_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyRange_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ extern "C" {
|
|||
static mut _Py_EllipsisObject: PyObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn Py_Ellipsis() -> *mut PyObject {
|
||||
&mut _Py_EllipsisObject
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ extern "C" {
|
|||
pub static mut PyEllipsis_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PySlice_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PySlice_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ extern "C" {
|
|||
pub static mut PyTraceBack_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTraceBack_Check(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyTraceBack_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ extern "C" {
|
|||
pub static mut PyTupleIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_TUPLE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyTuple_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyTuple_Type) as c_int
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
// Macro, trading safety for speed
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObject {
|
||||
*(*(op as *mut PyTupleObject))
|
||||
|
@ -50,14 +50,14 @@ pub unsafe fn PyTuple_GET_ITEM(op: *mut PyObject, i: Py_ssize_t) -> *mut PyObjec
|
|||
.offset(i as isize)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyTuple_GET_SIZE(op: *mut PyObject) -> Py_ssize_t {
|
||||
Py_SIZE(op)
|
||||
}
|
||||
|
||||
/// Macro, *only* to be used to fill in brand new tuples
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub unsafe fn PyTuple_SET_ITEM(op: *mut PyObject, i: Py_ssize_t, v: *mut PyObject) {
|
||||
*(*(op as *mut PyTupleObject))
|
||||
|
|
|
@ -16,12 +16,12 @@ extern "C" {
|
|||
pub static mut PyUnicodeIter_Type: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_Check(op: *mut PyObject) -> c_int {
|
||||
PyType_FastSubclass(Py_TYPE(op), Py_TPFLAGS_UNICODE_SUBCLASS)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyUnicode_CheckExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut PyUnicode_Type) as c_int
|
||||
}
|
||||
|
|
|
@ -10,23 +10,23 @@ extern "C" {
|
|||
static mut _PyWeakref_CallableProxyType: PyTypeObject;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckRef(op: *mut PyObject) -> c_int {
|
||||
PyObject_TypeCheck(op, &mut _PyWeakref_RefType)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckRefExact(op: *mut PyObject) -> c_int {
|
||||
(Py_TYPE(op) == &mut _PyWeakref_RefType) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_CheckProxy(op: *mut PyObject) -> c_int {
|
||||
((Py_TYPE(op) == &mut _PyWeakref_ProxyType)
|
||||
|| (Py_TYPE(op) == &mut _PyWeakref_CallableProxyType)) as c_int
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
pub unsafe fn PyWeakref_Check(op: *mut PyObject) -> c_int {
|
||||
(PyWeakref_CheckRef(op) != 0 || PyWeakref_CheckProxy(op) != 0) as c_int
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ impl PyToken {
|
|||
PyToken(PhantomData)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
|
||||
pub fn py(&self) -> Python {
|
||||
unsafe { Python::assume_gil_acquired() }
|
||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -129,21 +129,15 @@ extern crate spin;
|
|||
#[doc(hidden)]
|
||||
pub extern crate mashup;
|
||||
|
||||
/// Rust FFI declarations for Python
|
||||
pub mod ffi;
|
||||
|
||||
#[cfg(not(Py_3))]
|
||||
mod ffi2;
|
||||
|
||||
#[cfg(Py_3)]
|
||||
mod ffi3;
|
||||
|
||||
/// Rust FFI declarations for Python
|
||||
pub mod ffi {
|
||||
#[cfg(not(Py_3))]
|
||||
pub use ffi2::*;
|
||||
|
||||
#[cfg(Py_3)]
|
||||
pub use ffi3::*;
|
||||
}
|
||||
|
||||
pub use conversion::{
|
||||
FromPyObject, IntoPyObject, IntoPyTuple, PyTryFrom, PyTryInto, ReturnTypeIntoPyResult,
|
||||
ToBorrowedObject, ToPyObject,
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
use err::PyResult;
|
||||
use ffi;
|
||||
use ffi::PyDateTimeAPI;
|
||||
use ffi::{PyDateTime_Check, PyDateTime_DateTimeType};
|
||||
use ffi::{
|
||||
PyDateTime_DATE_GET_HOUR, PyDateTime_DATE_GET_MICROSECOND, PyDateTime_DATE_GET_MINUTE,
|
||||
PyDateTime_DATE_GET_SECOND,
|
||||
};
|
||||
use ffi::{
|
||||
PyDateTime_DELTA_GET_DAYS, PyDateTime_DELTA_GET_MICROSECONDS, PyDateTime_DELTA_GET_SECONDS,
|
||||
};
|
||||
use ffi::{PyDateTime_DateType, PyDate_Check};
|
||||
use ffi::{PyDateTime_DeltaType, PyDelta_Check};
|
||||
use ffi::{PyDateTime_GET_DAY, PyDateTime_GET_MONTH, PyDateTime_GET_YEAR};
|
||||
use ffi::{
|
||||
PyDateTime_TIME_GET_HOUR, PyDateTime_TIME_GET_MICROSECOND, PyDateTime_TIME_GET_MINUTE,
|
||||
PyDateTime_TIME_GET_SECOND,
|
||||
};
|
||||
use ffi::{PyDateTime_TZInfoType, PyTZInfo_Check};
|
||||
use ffi::{PyDateTime_TimeType, PyTime_Check};
|
||||
use object::PyObject;
|
||||
use std::os::raw::c_int;
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
use ffi::{PyDateTime_DATE_GET_FOLD, PyDateTime_TIME_GET_FOLD};
|
||||
|
||||
use instance::Py;
|
||||
use python::{Python, ToPyPointer};
|
||||
|
||||
// Traits
|
||||
pub trait PyDateAccess {
|
||||
fn get_year(&self) -> i32;
|
||||
fn get_month(&self) -> u8;
|
||||
fn get_day(&self) -> u8;
|
||||
}
|
||||
|
||||
pub trait PyDeltaAccess {
|
||||
fn get_days(&self) -> i32;
|
||||
fn get_seconds(&self) -> i32;
|
||||
fn get_microseconds(&self) -> i32;
|
||||
}
|
||||
|
||||
pub trait PyTimeAccess {
|
||||
fn get_hour(&self) -> u8;
|
||||
fn get_minute(&self) -> u8;
|
||||
fn get_second(&self) -> u8;
|
||||
fn get_microsecond(&self) -> u32;
|
||||
#[cfg(Py_3_6)]
|
||||
fn get_fold(&self) -> u8;
|
||||
}
|
||||
|
||||
// datetime.date bindings
|
||||
pub struct PyDate(PyObject);
|
||||
pyobject_native_type!(PyDate, PyDateTime_DateType, PyDate_Check);
|
||||
|
||||
impl PyDate {
|
||||
pub fn new(py: Python, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Date_FromDate)(
|
||||
year as c_int,
|
||||
month as c_int,
|
||||
day as c_int,
|
||||
PyDateTimeAPI.DateType,
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_timestamp(py: Python, args: &PyObject) -> PyResult<Py<PyDate>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Date_FromTimestamp)(PyDateTimeAPI.DateType, args.as_ptr());
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyDateAccess for PyDate {
|
||||
fn get_year(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_month(&self) -> u8 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_day(&self) -> u8 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }
|
||||
}
|
||||
}
|
||||
|
||||
// datetime.datetime bindings
|
||||
pub struct PyDateTime(PyObject);
|
||||
pyobject_native_type!(PyDateTime, PyDateTime_DateTimeType, PyDateTime_Check);
|
||||
|
||||
impl PyDateTime {
|
||||
pub fn new(
|
||||
py: Python,
|
||||
year: i32,
|
||||
month: u8,
|
||||
day: u8,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
) -> PyResult<Py<PyDateTime>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.DateTime_FromDateAndTime)(
|
||||
year as c_int,
|
||||
month as c_int,
|
||||
day as c_int,
|
||||
hour as c_int,
|
||||
minute as c_int,
|
||||
second as c_int,
|
||||
microsecond as c_int,
|
||||
opt_to_pyobj(py, tzinfo),
|
||||
PyDateTimeAPI.DateTimeType,
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_timestamp(
|
||||
py: Python,
|
||||
args: &PyObject,
|
||||
kwargs: &PyObject,
|
||||
) -> PyResult<Py<PyDateTime>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.DateTime_FromTimestamp)(
|
||||
PyDateTimeAPI.DateTimeType,
|
||||
args.as_ptr(),
|
||||
kwargs.as_ptr(),
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyDateAccess for PyDateTime {
|
||||
fn get_year(&self) -> i32 {
|
||||
unsafe { PyDateTime_GET_YEAR(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_month(&self) -> u8 {
|
||||
unsafe { PyDateTime_GET_MONTH(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_day(&self) -> u8 {
|
||||
unsafe { PyDateTime_GET_DAY(self.as_ptr()) as u8 }
|
||||
}
|
||||
}
|
||||
|
||||
impl PyTimeAccess for PyDateTime {
|
||||
fn get_hour(&self) -> u8 {
|
||||
unsafe { PyDateTime_DATE_GET_HOUR(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_minute(&self) -> u8 {
|
||||
unsafe { PyDateTime_DATE_GET_MINUTE(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_second(&self) -> u8 {
|
||||
unsafe { PyDateTime_DATE_GET_SECOND(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_microsecond(&self) -> u32 {
|
||||
unsafe { PyDateTime_DATE_GET_MICROSECOND(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
fn get_fold(&self) -> u8 {
|
||||
unsafe { PyDateTime_DATE_GET_FOLD(self.as_ptr()) as u8 }
|
||||
}
|
||||
}
|
||||
|
||||
// datetime.time
|
||||
pub struct PyTime(PyObject);
|
||||
pyobject_native_type!(PyTime, PyDateTime_TimeType, PyTime_Check);
|
||||
|
||||
impl PyTime {
|
||||
pub fn new(
|
||||
py: Python,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Time_FromTime)(
|
||||
hour as c_int,
|
||||
minute as c_int,
|
||||
second as c_int,
|
||||
microsecond as c_int,
|
||||
opt_to_pyobj(py, tzinfo),
|
||||
PyDateTimeAPI.TimeType,
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
pub fn new_with_fold(
|
||||
py: Python,
|
||||
hour: u8,
|
||||
minute: u8,
|
||||
second: u8,
|
||||
microsecond: u32,
|
||||
tzinfo: Option<&PyObject>,
|
||||
fold: bool,
|
||||
) -> PyResult<Py<PyTime>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Time_FromTimeAndFold)(
|
||||
hour as c_int,
|
||||
minute as c_int,
|
||||
second as c_int,
|
||||
microsecond as c_int,
|
||||
opt_to_pyobj(py, tzinfo),
|
||||
fold as c_int,
|
||||
PyDateTimeAPI.TimeType,
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyTimeAccess for PyTime {
|
||||
fn get_hour(&self) -> u8 {
|
||||
unsafe { PyDateTime_TIME_GET_HOUR(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_minute(&self) -> u8 {
|
||||
unsafe { PyDateTime_TIME_GET_MINUTE(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_second(&self) -> u8 {
|
||||
unsafe { PyDateTime_TIME_GET_SECOND(self.as_ptr()) as u8 }
|
||||
}
|
||||
|
||||
fn get_microsecond(&self) -> u32 {
|
||||
unsafe { PyDateTime_TIME_GET_MICROSECOND(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
fn get_fold(&self) -> u8 {
|
||||
unsafe { PyDateTime_TIME_GET_FOLD(self.as_ptr()) as u8 }
|
||||
}
|
||||
}
|
||||
|
||||
// datetime.tzinfo bindings
|
||||
pub struct PyTzInfo(PyObject);
|
||||
pyobject_native_type!(PyTzInfo, PyDateTime_TZInfoType, PyTZInfo_Check);
|
||||
|
||||
// datetime.timedelta bindings
|
||||
pub struct PyDelta(PyObject);
|
||||
pyobject_native_type!(PyDelta, PyDateTime_DeltaType, PyDelta_Check);
|
||||
|
||||
impl PyDelta {
|
||||
pub fn new(
|
||||
py: Python,
|
||||
days: i32,
|
||||
seconds: i32,
|
||||
microseconds: i32,
|
||||
normalize: bool,
|
||||
) -> PyResult<Py<PyDelta>> {
|
||||
unsafe {
|
||||
let ptr = (PyDateTimeAPI.Delta_FromDelta)(
|
||||
days as c_int,
|
||||
seconds as c_int,
|
||||
microseconds as c_int,
|
||||
normalize as c_int,
|
||||
PyDateTimeAPI.DeltaType,
|
||||
);
|
||||
Py::from_owned_ptr_or_err(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyDeltaAccess for PyDelta {
|
||||
fn get_days(&self) -> i32 {
|
||||
unsafe { PyDateTime_DELTA_GET_DAYS(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_seconds(&self) -> i32 {
|
||||
unsafe { PyDateTime_DELTA_GET_SECONDS(self.as_ptr()) as i32 }
|
||||
}
|
||||
|
||||
fn get_microseconds(&self) -> i32 {
|
||||
unsafe { PyDateTime_DELTA_GET_MICROSECONDS(self.as_ptr()) as i32 }
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function
|
||||
unsafe fn opt_to_pyobj(py: Python, opt: Option<&PyObject>) -> *mut ffi::PyObject {
|
||||
// Convenience function for unpacking Options to either an Object or None
|
||||
match opt {
|
||||
Some(tzi) => tzi.as_ptr(),
|
||||
None => py.None().as_ptr(),
|
||||
}
|
||||
}
|
|
@ -68,7 +68,7 @@ macro_rules! import_exception {
|
|||
}
|
||||
|
||||
impl $crate::typeob::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn init_type() {}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
pub use self::boolobject::PyBool;
|
||||
pub use self::bytearray::PyByteArray;
|
||||
pub use self::datetime::PyDeltaAccess;
|
||||
pub use self::datetime::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo};
|
||||
pub use self::datetime::{PyDateAccess, PyTimeAccess};
|
||||
pub use self::dict::PyDict;
|
||||
pub use self::floatob::PyFloat;
|
||||
pub use self::iterator::PyIterator;
|
||||
|
@ -63,7 +66,7 @@ macro_rules! pyobject_native_type_named (
|
|||
}
|
||||
|
||||
impl<$($type_param,)*> $crate::PyObjectWithToken for $name {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn py(&self) -> $crate::Python {
|
||||
unsafe { $crate::Python::assume_gil_acquired() }
|
||||
}
|
||||
|
@ -123,7 +126,7 @@ macro_rules! pyobject_native_type_convert(
|
|||
}
|
||||
|
||||
impl<$($type_param,)*> $crate::typeob::PyTypeObject for $name {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn init_type() {}
|
||||
|
||||
#[inline]
|
||||
|
@ -180,6 +183,7 @@ pyobject_native_type_convert!(PyObjectRef, ffi::PyBaseObject_Type, ffi::PyObject
|
|||
|
||||
mod boolobject;
|
||||
mod bytearray;
|
||||
mod datetime;
|
||||
mod dict;
|
||||
pub mod exc;
|
||||
mod floatob;
|
||||
|
|
|
@ -204,7 +204,7 @@ impl IntoPyPointer for PyRawObject {
|
|||
}
|
||||
|
||||
impl PyObjectWithToken for PyRawObject {
|
||||
#[inline(always)]
|
||||
#[inline]
|
||||
fn py(&self) -> Python {
|
||||
unsafe { Python::assume_gil_acquired() }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
#![feature(concat_idents)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
use std::iter;
|
||||
|
||||
use pyo3::ffi::*;
|
||||
use pyo3::prelude::*;
|
||||
|
||||
fn _get_subclasses<'p>(
|
||||
py: &'p Python,
|
||||
py_type: &str,
|
||||
args: &str,
|
||||
) -> PyResult<(&'p PyObjectRef, &'p PyObjectRef, &'p PyObjectRef)> {
|
||||
// Import the class from Python and create some subclasses
|
||||
let datetime = py.import("datetime")?;
|
||||
|
||||
let locals = PyDict::new(*py);
|
||||
locals.set_item(py_type, datetime.get(py_type)?).unwrap();
|
||||
|
||||
let make_subclass_py = format!("class Subklass({}):\n pass", py_type);
|
||||
|
||||
let make_sub_subclass_py = "class SubSubklass(Subklass):\n pass";
|
||||
|
||||
py.run(&make_subclass_py, None, Some(&locals))?;
|
||||
py.run(&make_sub_subclass_py, None, Some(&locals))?;
|
||||
|
||||
// Construct an instance of the base class
|
||||
let obj = py.eval(&format!("{}({})", py_type, args), None, Some(&locals))?;
|
||||
|
||||
// Construct an instance of the subclass
|
||||
let sub_obj = py.eval(&format!("Subklass({})", args), None, Some(&locals))?;
|
||||
|
||||
// Construct an instance of the sub-subclass
|
||||
let sub_sub_obj = py.eval(&format!("SubSubklass({})", args), None, Some(&locals))?;
|
||||
|
||||
Ok((obj, sub_obj, sub_sub_obj))
|
||||
}
|
||||
|
||||
macro_rules! assert_check_exact {
|
||||
($check_func:ident, $obj: expr) => {
|
||||
unsafe {
|
||||
assert!($check_func(($obj).as_ptr()) != 0);
|
||||
assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) != 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! assert_check_only {
|
||||
($check_func:ident, $obj: expr) => {
|
||||
unsafe {
|
||||
assert!($check_func(($obj).as_ptr()) != 0);
|
||||
assert!(concat_idents!($check_func, Exact)(($obj).as_ptr()) == 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_date_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(&py, "date", "2018, 1, 1").unwrap();
|
||||
|
||||
assert_check_exact!(PyDate_Check, obj);
|
||||
assert_check_only!(PyDate_Check, sub_obj);
|
||||
assert_check_only!(PyDate_Check, sub_sub_obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_time_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(&py, "time", "12, 30, 15").unwrap();
|
||||
|
||||
assert_check_exact!(PyTime_Check, obj);
|
||||
assert_check_only!(PyTime_Check, sub_obj);
|
||||
assert_check_only!(PyTime_Check, sub_sub_obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_datetime_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) =
|
||||
_get_subclasses(&py, "datetime", "2018, 1, 1, 13, 30, 15").unwrap();
|
||||
|
||||
assert_check_only!(PyDate_Check, obj);
|
||||
assert_check_exact!(PyDateTime_Check, obj);
|
||||
assert_check_only!(PyDateTime_Check, sub_obj);
|
||||
assert_check_only!(PyDateTime_Check, sub_sub_obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delta_check() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let (obj, sub_obj, sub_sub_obj) = _get_subclasses(&py, "timedelta", "1, -3").unwrap();
|
||||
|
||||
assert_check_exact!(PyDelta_Check, obj);
|
||||
assert_check_only!(PyDelta_Check, sub_obj);
|
||||
assert_check_only!(PyDelta_Check, sub_sub_obj);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(Py_3)]
|
||||
fn test_datetime_utc() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let datetime = py.import("datetime").map_err(|e| e.print(py)).unwrap();
|
||||
let timezone = datetime.get("timezone").unwrap();
|
||||
let utc = timezone.getattr("utc").unwrap().to_object(py);
|
||||
|
||||
let dt = PyDateTime::new(py, 2018, 1, 1, 0, 0, 0, 0, Some(&utc)).unwrap();
|
||||
|
||||
let locals = PyDict::new(py);
|
||||
locals.set_item("dt", dt).unwrap();
|
||||
|
||||
let offset: f32 = py
|
||||
.eval("dt.utcoffset().total_seconds()", None, Some(locals))
|
||||
.unwrap()
|
||||
.extract()
|
||||
.unwrap();
|
||||
assert_eq!(offset, 0f32);
|
||||
}
|
||||
|
||||
static INVALID_DATES: &'static [(i32, u8, u8)] = &[
|
||||
(-1, 1, 1),
|
||||
(0, 1, 1),
|
||||
(10000, 1, 1),
|
||||
(2 << 30, 1, 1),
|
||||
(2018, 0, 1),
|
||||
(2018, 13, 1),
|
||||
(2018, 1, 0),
|
||||
(2017, 2, 29),
|
||||
(2018, 1, 32),
|
||||
];
|
||||
|
||||
static INVALID_TIMES: &'static [(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() {
|
||||
// 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.into_iter() {
|
||||
let (year, month, day) = val;
|
||||
let dt = PyDate::new(py, *year, *month, *day);
|
||||
let msg = format!("Should have raised an error: {:#?}", val);
|
||||
match dt {
|
||||
Ok(_) => assert!(false, msg),
|
||||
Err(_) => assert!(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[test]
|
||||
fn test_pytime_out_of_bounds() {
|
||||
// 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.into_iter() {
|
||||
let (hour, minute, second, microsecond) = val;
|
||||
let dt = PyTime::new(py, *hour, *minute, *second, *microsecond, None);
|
||||
let msg = format!("Should have raised an error: {:#?}", val);
|
||||
match dt {
|
||||
Ok(_) => assert!(false, msg),
|
||||
Err(_) => assert!(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
#[test]
|
||||
fn test_pydatetime_out_of_bounds() {
|
||||
// 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);
|
||||
let valid_date = (2018, 1, 1);
|
||||
|
||||
let invalid_dates = INVALID_DATES.into_iter().zip(iter::repeat(&valid_time));
|
||||
let invalid_times = iter::repeat(&valid_date).zip(INVALID_TIMES.into_iter());
|
||||
|
||||
let vals = invalid_dates.chain(invalid_times);
|
||||
|
||||
for val in vals {
|
||||
let (date, time) = val;
|
||||
let (year, month, day) = date;
|
||||
let (hour, minute, second, microsecond) = time;
|
||||
let dt = PyDateTime::new(
|
||||
py,
|
||||
*year,
|
||||
*month,
|
||||
*day,
|
||||
*hour,
|
||||
*minute,
|
||||
*second,
|
||||
*microsecond,
|
||||
None,
|
||||
);
|
||||
let msg = format!("Should have raised an error: {:#?}", val);
|
||||
match dt {
|
||||
Ok(_) => assert!(false, msg),
|
||||
Err(_) => assert!(true),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue