include py3 ffi info into crate
This commit is contained in:
parent
3bb7a64db5
commit
8a295793a0
28
Cargo.toml
28
Cargo.toml
|
@ -1,43 +1,35 @@
|
|||
[package]
|
||||
|
||||
name = "cpython"
|
||||
name = "pyo3"
|
||||
version = "0.1.0"
|
||||
description = "Bindings to Python"
|
||||
authors = ["Daniel Grunwald <daniel@danielgrunwald.de>"]
|
||||
authors = ["PyO3 Project and Contributors <https://github.com/PyO3"]
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"python",
|
||||
"cpython",
|
||||
]
|
||||
homepage = "https://github.com/dgrunwald/rust-cpython"
|
||||
repository = "https://github.com/dgrunwald/rust-cpython.git"
|
||||
documentation = "http://dgrunwald.github.io/rust-cpython/doc/cpython/"
|
||||
homepage = "https://github.com/pyo3/pyo3"
|
||||
repository = "https://github.com/pyo3/pyo3.git"
|
||||
documentation = "http://pyo3.github.io/pyo3/doc/pyo3/"
|
||||
categories = ["api-bindings", "development-tools::ffi"]
|
||||
license = "MIT"
|
||||
license = "MIT/APACHE-2"
|
||||
exclude = [
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
"appveyor.yml",
|
||||
".cargo/config",
|
||||
"extensions"
|
||||
]
|
||||
build = "build.rs"
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "dgrunwald/rust-cpython" }
|
||||
appveyor = { repository = "dgrunwald/rust-cpython" }
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
num-traits = "0.1"
|
||||
|
||||
[dependencies.python3-sys]
|
||||
optional = true
|
||||
# version = "0.1.3"
|
||||
path = "./python3-sys/"
|
||||
[build-dependencies]
|
||||
regex = "0.1"
|
||||
|
||||
[features]
|
||||
default = ["python3-sys"]
|
||||
default = []
|
||||
|
||||
# Enable additional features that require nightly rust
|
||||
nightly = []
|
||||
|
@ -45,4 +37,4 @@ nightly = []
|
|||
# Use this feature when building an extension module.
|
||||
# It tells the linker to keep the python symbols unresolved,
|
||||
# so that the module can also be used with statically linked python interpreters.
|
||||
extension-module = [ "python3-sys/extension-module" ]
|
||||
extension-module = []
|
||||
|
|
13
Makefile
13
Makefile
|
@ -11,9 +11,6 @@ NIGHTLY := 0
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(PY),2)
|
||||
FEATURES := python27-sys
|
||||
endif
|
||||
ifeq ($(PY),3)
|
||||
FEATURES := python3-sys
|
||||
ifdef PEP384
|
||||
|
@ -29,16 +26,10 @@ CARGO_FLAGS := --features "$(FEATURES)" --no-default-features
|
|||
|
||||
default: test extensions
|
||||
|
||||
src/py_class/py_class_impl2.rs: src/py_class/py_class_impl.py
|
||||
PY=2 python $< >$@
|
||||
|
||||
src/py_class/py_class_impl3.rs: src/py_class/py_class_impl.py
|
||||
src/py_class/py_class_impl.rs: src/py_class/py_class_impl.py
|
||||
PY=3 python $< >$@
|
||||
|
||||
cog: python27-sys/build.rs .travis.yml
|
||||
cog.py -r $^
|
||||
|
||||
build: src/py_class/py_class_impl2.rs src/py_class/py_class_impl3.rs
|
||||
build: src/py_class/py_class_impl.rs
|
||||
cargo build $(CARGO_FLAGS)
|
||||
|
||||
test: build
|
||||
|
|
404
build.rs
404
build.rs
|
@ -1,41 +1,385 @@
|
|||
extern crate regex;
|
||||
|
||||
use std::process::Command;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::io::Write;
|
||||
use regex::Regex;
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct PythonVersion {
|
||||
major: u8,
|
||||
// minor == None means any minor version will do
|
||||
minor: Option<u8>
|
||||
}
|
||||
|
||||
impl fmt::Display for PythonVersion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
try!(self.major.fmt(f));
|
||||
try!(f.write_str("."));
|
||||
match self.minor {
|
||||
Some(minor) => try!(minor.fmt(f)),
|
||||
None => try!(f.write_str("*"))
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const MIN_MINOR: u8 = 4;
|
||||
|
||||
const CFG_KEY: &'static str = "py_sys_config";
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
const PYTHONSYS_ENV_VAR: &'static str = "DEP_PYTHON3_PYTHON_FLAGS";
|
||||
// windows' python writes out lines with the windows crlf sequence;
|
||||
// posix platforms and mac os should write out lines with just lf.
|
||||
#[cfg(target_os="windows")]
|
||||
static NEWLINE_SEQUENCE: &'static str = "\r\n";
|
||||
|
||||
fn main() {
|
||||
// python{27,3.x}-sys/build.rs passes python interpreter compile flags via
|
||||
// environment variable (using the 'links' mechanism in the cargo.toml).
|
||||
let flags = match env::var(PYTHONSYS_ENV_VAR) {
|
||||
Ok(flags) => flags,
|
||||
Err(_) => {
|
||||
writeln!(std::io::stderr(),
|
||||
"Environment variable {} not found - this is supposed to be \
|
||||
exported from the pythonXX-sys dependency, so the build chain is broken",
|
||||
PYTHONSYS_ENV_VAR).unwrap();
|
||||
std::process::exit(1);
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static NEWLINE_SEQUENCE: &'static str = "\n";
|
||||
|
||||
// A list of python interpreter compile-time preprocessor defines that
|
||||
// we will pick up and pass to rustc via --cfg=py_sys_config={varname};
|
||||
// this allows using them conditional cfg attributes in the .rs files, so
|
||||
//
|
||||
// #[cfg(py_sys_config="{varname}"]
|
||||
//
|
||||
// is the equivalent of #ifdef {varname} name in C.
|
||||
//
|
||||
// see Misc/SpecialBuilds.txt in the python source for what these mean.
|
||||
//
|
||||
// (hrm, this is sort of re-implementing what distutils does, except
|
||||
// by passing command line args instead of referring to a python.h)
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static SYSCONFIG_FLAGS: [&'static str; 7] = [
|
||||
"Py_USING_UNICODE",
|
||||
"Py_UNICODE_WIDE",
|
||||
"WITH_THREAD",
|
||||
"Py_DEBUG",
|
||||
"Py_REF_DEBUG",
|
||||
"Py_TRACE_REFS",
|
||||
"COUNT_ALLOCS",
|
||||
];
|
||||
|
||||
static SYSCONFIG_VALUES: [&'static str; 1] = [
|
||||
// cfg doesn't support flags with values, just bools - so flags
|
||||
// below are translated into bools as {varname}_{val}
|
||||
//
|
||||
// for example, Py_UNICODE_SIZE_2 or Py_UNICODE_SIZE_4
|
||||
"Py_UNICODE_SIZE" // note - not present on python 3.3+, which is always wide
|
||||
];
|
||||
|
||||
/// Examine python's compile flags to pass to cfg by launching
|
||||
/// the interpreter and printing variables of interest from
|
||||
/// sysconfig.get_config_vars.
|
||||
#[cfg(not(target_os="windows"))]
|
||||
fn get_config_vars(python_path: &String) -> Result<HashMap<String, String>, String> {
|
||||
let mut script = "import sysconfig; \
|
||||
config = sysconfig.get_config_vars();".to_owned();
|
||||
|
||||
for k in SYSCONFIG_FLAGS.iter().chain(SYSCONFIG_VALUES.iter()) {
|
||||
script.push_str(&format!("print(config.get('{}', {}))", k,
|
||||
if is_value(k) { "None" } else { "0" } ));
|
||||
script.push_str(";");
|
||||
}
|
||||
|
||||
let mut cmd = Command::new(python_path);
|
||||
cmd.arg("-c").arg(script);
|
||||
|
||||
let out = try!(cmd.output().map_err(|e| {
|
||||
format!("failed to run python interpreter `{:?}`: {}", cmd, e)
|
||||
}));
|
||||
|
||||
if !out.status.success() {
|
||||
let stderr = String::from_utf8(out.stderr).unwrap();
|
||||
let mut msg = format!("python script failed with stderr:\n\n");
|
||||
msg.push_str(&stderr);
|
||||
return Err(msg);
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8(out.stdout).unwrap();
|
||||
let split_stdout: Vec<&str> = stdout.trim_right().split(NEWLINE_SEQUENCE).collect();
|
||||
if split_stdout.len() != SYSCONFIG_VALUES.len() + SYSCONFIG_FLAGS.len() {
|
||||
return Err(
|
||||
format!("python stdout len didn't return expected number of lines:
|
||||
{}", split_stdout.len()).to_string());
|
||||
}
|
||||
let all_vars = SYSCONFIG_FLAGS.iter().chain(SYSCONFIG_VALUES.iter());
|
||||
// let var_map: HashMap<String, String> = HashMap::new();
|
||||
let mut all_vars = all_vars.zip(split_stdout.iter())
|
||||
.fold(HashMap::new(), |mut memo: HashMap<String, String>, (&k, &v)| {
|
||||
if !(v.to_owned() == "None" && is_value(k)) {
|
||||
memo.insert(k.to_owned(), v.to_owned());
|
||||
}
|
||||
memo
|
||||
});
|
||||
|
||||
let debug = if let Some(val) = all_vars.get("Py_DEBUG") { val == "1" } else { false };
|
||||
if debug {
|
||||
all_vars.insert("Py_REF_DEBUG".to_owned(), "1".to_owned());
|
||||
all_vars.insert("Py_TRACE_REFS".to_owned(), "1".to_owned());
|
||||
all_vars.insert("COUNT_ALLOCS".to_owned(), "1".to_owned());
|
||||
}
|
||||
|
||||
Ok(all_vars)
|
||||
}
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
fn get_config_vars(_: &String) -> Result<HashMap<String, String>, String> {
|
||||
// sysconfig is missing all the flags on windows, so we can't actually
|
||||
// query the interpreter directly for its build flags.
|
||||
//
|
||||
// For the time being, this is the flags as defined in the python source's
|
||||
// PC\pyconfig.h. This won't work correctly if someone has built their
|
||||
// python with a modified pyconfig.h - sorry if that is you, you will have
|
||||
// to comment/uncomment the lines below.
|
||||
let mut map: HashMap<String, String> = HashMap::new();
|
||||
map.insert("Py_USING_UNICODE".to_owned(), "1".to_owned());
|
||||
map.insert("Py_UNICODE_WIDE".to_owned(), "0".to_owned());
|
||||
map.insert("WITH_THREAD".to_owned(), "1".to_owned());
|
||||
map.insert("Py_UNICODE_SIZE".to_owned(), "2".to_owned());
|
||||
|
||||
// This is defined #ifdef _DEBUG. The visual studio build seems to produce
|
||||
// a specially named pythonXX_d.exe and pythonXX_d.dll when you build the
|
||||
// Debug configuration, which this script doesn't currently support anyway.
|
||||
// map.insert("Py_DEBUG", "1");
|
||||
|
||||
// Uncomment these manually if your python was built with these and you want
|
||||
// the cfg flags to be set in rust.
|
||||
//
|
||||
// map.insert("Py_REF_DEBUG", "1");
|
||||
// map.insert("Py_TRACE_REFS", "1");
|
||||
// map.insert("COUNT_ALLOCS", 1");
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
fn is_value(key: &str) -> bool {
|
||||
SYSCONFIG_VALUES.iter().find(|x| **x == key).is_some()
|
||||
}
|
||||
|
||||
fn cfg_line_for_var(key: &str, val: &str) -> Option<String> {
|
||||
if is_value(key) {
|
||||
// is a value; suffix the key name with the value
|
||||
Some(format!("cargo:rustc-cfg={}=\"{}_{}\"\n", CFG_KEY, key, val))
|
||||
} else if val != "0" {
|
||||
// is a flag that isn't zero
|
||||
Some(format!("cargo:rustc-cfg={}=\"{}\"", CFG_KEY, key))
|
||||
} else {
|
||||
// is a flag that is zero
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a python script using the specified interpreter binary.
|
||||
fn run_python_script(interpreter: &str, script: &str) -> Result<String, String> {
|
||||
let mut cmd = Command::new(interpreter);
|
||||
cmd.arg("-c").arg(script);
|
||||
|
||||
let out = try!(cmd.output().map_err(|e| {
|
||||
format!("failed to run python interpreter `{:?}`: {}", cmd, e)
|
||||
}));
|
||||
|
||||
if !out.status.success() {
|
||||
let stderr = String::from_utf8(out.stderr).unwrap();
|
||||
let mut msg = format!("python script failed with stderr:\n\n");
|
||||
msg.push_str(&stderr);
|
||||
return Err(msg);
|
||||
}
|
||||
|
||||
let out = String::from_utf8(out.stdout).unwrap();
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os="macos"))]
|
||||
#[cfg(not(target_os="windows"))]
|
||||
fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, enable_shared: bool) -> Result<String, String> {
|
||||
if enable_shared {
|
||||
Ok(format!("cargo:rustc-link-lib=python{}", ld_version))
|
||||
} else {
|
||||
Ok(format!("cargo:rustc-link-lib=static=python{}", ld_version))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
fn get_macos_linkmodel() -> Result<String, String> {
|
||||
let script = "import sysconfig; print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));";
|
||||
let out = run_python_script("python", script).unwrap();
|
||||
Ok(out.trim_right().to_owned())
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, _: bool) -> Result<String, String> {
|
||||
// os x can be linked to a framework or static or dynamic, and
|
||||
// Py_ENABLE_SHARED is wrong; framework means shared library
|
||||
match get_macos_linkmodel().unwrap().as_ref() {
|
||||
"static" => Ok(format!("cargo:rustc-link-lib=static=python{}",
|
||||
ld_version)),
|
||||
"shared" => Ok(format!("cargo:rustc-link-lib=python{}",
|
||||
ld_version)),
|
||||
"framework" => Ok(format!("cargo:rustc-link-lib=python{}",
|
||||
ld_version)),
|
||||
other => Err(format!("unknown linkmodel {}", other))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse string as interpreter version.
|
||||
fn get_interpreter_version(line: &str) -> Result<PythonVersion, String> {
|
||||
let version_re = Regex::new(r"\((\d+), (\d+)\)").unwrap();
|
||||
match version_re.captures(&line) {
|
||||
Some(cap) => Ok(PythonVersion {
|
||||
major: cap.at(1).unwrap().parse().unwrap(),
|
||||
minor: Some(cap.at(2).unwrap().parse().unwrap())
|
||||
}),
|
||||
None => Err(
|
||||
format!("Unexpected response to version query {}", line))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
fn get_rustc_link_lib(version: &PythonVersion, _: &str, _: bool) -> Result<String, String> {
|
||||
// Py_ENABLE_SHARED doesn't seem to be present on windows.
|
||||
Ok(format!("cargo:rustc-link-lib=pythonXY:python{}{}", version.major,
|
||||
match version.minor {
|
||||
Some(minor) => minor.to_string(),
|
||||
None => "".to_owned()
|
||||
}))
|
||||
}
|
||||
|
||||
/// Locate a suitable python interpreter and extract config from it.
|
||||
/// If the environment variable `PYTHON_SYS_EXECUTABLE`, use the provided
|
||||
/// path a Python executable, and raises an error if the version doesn't match.
|
||||
/// Else tries to execute the interpreter as "python", "python{major version}",
|
||||
/// "python{major version}.{minor version}" in order until one
|
||||
/// is of the version we are expecting.
|
||||
fn find_interpreter_and_get_config() -> Result<(PythonVersion, String, Vec<String>), String>
|
||||
{
|
||||
if let Some(sys_executable) = env::var_os("PYTHON_SYS_EXECUTABLE") {
|
||||
println!("1111");
|
||||
let interpreter_path = sys_executable.to_str()
|
||||
.expect("Unable to get PYTHON_SYS_EXECUTABLE value");
|
||||
let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path));
|
||||
|
||||
if MIN_MINOR > interpreter_version.minor.unwrap_or(0) {
|
||||
return Err(format!("Unsupported python version in PYTHON_SYS_EXECUTABLE={}\n\
|
||||
\tmin version 3.4 != found {}",
|
||||
interpreter_path,
|
||||
interpreter_version));
|
||||
} else {
|
||||
return Ok((interpreter_version, interpreter_path.to_owned(), lines));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if flags.len() > 0 {
|
||||
for f in flags.split(",") {
|
||||
// write out flags as --cfg so that the same #cfg blocks can be used
|
||||
// in rust-cpython as in the -sys libs
|
||||
if f.starts_with("CFG") {
|
||||
println!("cargo:rustc-cfg={}", &f[4..])
|
||||
} else {
|
||||
let key_and_val: Vec<&str> = f.split("=").collect();
|
||||
let key = key_and_val[0];
|
||||
let val = key_and_val[1];
|
||||
if key.starts_with("FLAG") {
|
||||
println!("cargo:rustc-cfg={}=\"{}\"", CFG_KEY, &key[5..]);
|
||||
} else {
|
||||
println!("cargo:rustc-cfg={}=\"{}_{}\"", CFG_KEY, &key[4..], val);
|
||||
}
|
||||
{
|
||||
let interpreter_path = "python";
|
||||
let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path));
|
||||
if MIN_MINOR < interpreter_version.minor.unwrap_or(0) {
|
||||
return Ok((interpreter_version, interpreter_path.to_owned(), lines));
|
||||
}
|
||||
}
|
||||
|
||||
Err(format!("No python interpreter found"))
|
||||
}
|
||||
|
||||
/// Extract compilation vars from the specified interpreter.
|
||||
fn get_config_from_interpreter(interpreter: &str) -> Result<(PythonVersion, Vec<String>), String> {
|
||||
let script = "import sys; import sysconfig; print(sys.version_info[0:2]); \
|
||||
print(sysconfig.get_config_var('LIBDIR')); \
|
||||
print(sysconfig.get_config_var('Py_ENABLE_SHARED')); \
|
||||
print(sysconfig.get_config_var('LDVERSION') or sysconfig.get_config_var('py_version_short')); \
|
||||
print(sys.exec_prefix);";
|
||||
let out = try!(run_python_script(interpreter, script));
|
||||
let lines: Vec<String> = out.split(NEWLINE_SEQUENCE).map(|line| line.to_owned()).collect();
|
||||
let interpreter_version = try!(get_interpreter_version(&lines[0]));
|
||||
Ok((interpreter_version, lines))
|
||||
}
|
||||
|
||||
/// Deduce configuration from the 'python' in the current PATH and print
|
||||
/// cargo vars to stdout.
|
||||
///
|
||||
/// Note that if the python doesn't satisfy expected_version, this will error.
|
||||
fn configure_from_path() -> Result<(String, String), String> {
|
||||
|
||||
let (interpreter_version, interpreter_path, lines) = try!(
|
||||
find_interpreter_and_get_config());
|
||||
|
||||
let libpath: &str = &lines[1];
|
||||
let enable_shared: &str = &lines[2];
|
||||
let ld_version: &str = &lines[3];
|
||||
let exec_prefix: &str = &lines[4];
|
||||
|
||||
let is_extension_module = env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some();
|
||||
if !is_extension_module || cfg!(target_os="windows") {
|
||||
println!("{}", get_rustc_link_lib(&interpreter_version,
|
||||
ld_version, enable_shared == "1").unwrap());
|
||||
if libpath != "None" {
|
||||
println!("cargo:rustc-link-search=native={}", libpath);
|
||||
} else if cfg!(target_os="windows") {
|
||||
println!("cargo:rustc-link-search=native={}\\libs", exec_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
let mut flags = String::new();
|
||||
|
||||
println!("test: {:?}", interpreter_version);
|
||||
if let PythonVersion { major: 3, minor: some_minor} = interpreter_version {
|
||||
if env::var_os("CARGO_FEATURE_PEP_384").is_some() {
|
||||
println!("cargo:rustc-cfg=Py_LIMITED_API");
|
||||
}
|
||||
if let Some(minor) = some_minor {
|
||||
for i in 4..(minor+1) {
|
||||
println!("cargo:rustc-cfg=Py_3_{}", i);
|
||||
flags += format!("CFG_Py_3_{},", i).as_ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok((interpreter_path, flags));
|
||||
}
|
||||
|
||||
|
||||
fn main() {
|
||||
// 1. Setup cfg variables so we can do conditional compilation in this
|
||||
// library based on the python interpeter's compilation flags. This is
|
||||
// necessary for e.g. matching the right unicode and threading interfaces.
|
||||
//
|
||||
// This locates the python interpreter based on the PATH, which should
|
||||
// work smoothly with an activated virtualenv.
|
||||
//
|
||||
// If you have troubles with your shell accepting '.' in a var name,
|
||||
// try using 'env' (sorry but this isn't our fault - it just has to
|
||||
// match the pkg-config package name, which is going to have a . in it).
|
||||
let (python_interpreter_path, flags) = configure_from_path().unwrap();
|
||||
println!('3');
|
||||
let config_map = get_config_vars(&python_interpreter_path).unwrap();
|
||||
for (key, val) in &config_map {
|
||||
match cfg_line_for_var(key, val) {
|
||||
Some(line) => println!("{}", line),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Export python interpreter compilation flags as cargo variables that
|
||||
// will be visible to dependents. All flags will be available to dependent
|
||||
// build scripts in the environment variable DEP_PYTHON27_PYTHON_FLAGS as
|
||||
// comma separated list; each item in the list looks like
|
||||
//
|
||||
// {VAL,FLAG}_{flag_name}=val;
|
||||
//
|
||||
// FLAG indicates the variable is always 0 or 1
|
||||
// VAL indicates it can take on any value
|
||||
//
|
||||
// rust-cypthon/build.rs contains an example of how to unpack this data
|
||||
// into cfg flags that replicate the ones present in this library, so
|
||||
// you can use the same cfg syntax.
|
||||
//let mut flags = flags;
|
||||
let flags: String = config_map.iter().fold("".to_owned(), |memo, (key, val)| {
|
||||
if is_value(key) {
|
||||
memo + format!("VAL_{}={},", key, val).as_ref()
|
||||
} else if val != "0" {
|
||||
memo + format!("FLAG_{}={},", key, val).as_ref()
|
||||
} else {
|
||||
memo
|
||||
}
|
||||
}) + flags.as_str();
|
||||
|
||||
println!("cargo:python_flags={}",
|
||||
if flags.len() > 0 { &flags[..flags.len()-1] } else { "" });
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/target
|
||||
/Cargo.lock
|
|
@ -1,50 +0,0 @@
|
|||
[package]
|
||||
name = "python3-sys"
|
||||
version = "0.1.3"
|
||||
description = "FFI Declarations for Python 3"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"python",
|
||||
"cpython",
|
||||
"libpython3",
|
||||
]
|
||||
homepage = "https://github.com/dgrunwald/rust-cpython/tree/master/python3-sys"
|
||||
repository = "https://github.com/dgrunwald/rust-cpython/tree/master/python3-sys"
|
||||
categories = ["external-ffi-bindings"]
|
||||
license = "Python-2.0"
|
||||
authors = ["Daniel Grunwald <daniel@danielgrunwald.de>"]
|
||||
links = "python3"
|
||||
build = "build.rs"
|
||||
exclude = [
|
||||
".gitignore",
|
||||
".travis.yml",
|
||||
]
|
||||
workspace = ".."
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
regex = "0.1"
|
||||
|
||||
[features]
|
||||
# This is examined by ./build.rs to determine which python version
|
||||
# to try to bind to.
|
||||
default = ["python-3"]
|
||||
|
||||
# Use this feature when building an extension module.
|
||||
# It tells the linker to keep the python symbols unresolved,
|
||||
# so that the module can also be used with statically linked python interpreters.
|
||||
extension-module = [ ]
|
||||
|
||||
# Bind to any python 3.x.
|
||||
python-3 = []
|
||||
|
||||
# Or, bind to a particular minor version.
|
||||
python-3-4 = []
|
||||
python-3-5 = []
|
||||
python-3-6 = []
|
||||
|
||||
# Restrict to PEP-384 stable ABI
|
||||
pep-384 = []
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
extern crate regex;
|
||||
|
||||
use std::process::Command;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use regex::Regex;
|
||||
use std::fmt;
|
||||
|
||||
struct PythonVersion {
|
||||
major: u8,
|
||||
// minor == None means any minor version will do
|
||||
minor: Option<u8>
|
||||
}
|
||||
|
||||
impl fmt::Display for PythonVersion {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
try!(self.major.fmt(f));
|
||||
try!(f.write_str("."));
|
||||
match self.minor {
|
||||
Some(minor) => try!(minor.fmt(f)),
|
||||
None => try!(f.write_str("*"))
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
const CFG_KEY: &'static str = "py_sys_config";
|
||||
|
||||
// windows' python writes out lines with the windows crlf sequence;
|
||||
// posix platforms and mac os should write out lines with just lf.
|
||||
#[cfg(target_os="windows")]
|
||||
static NEWLINE_SEQUENCE: &'static str = "\r\n";
|
||||
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static NEWLINE_SEQUENCE: &'static str = "\n";
|
||||
|
||||
// A list of python interpreter compile-time preprocessor defines that
|
||||
// we will pick up and pass to rustc via --cfg=py_sys_config={varname};
|
||||
// this allows using them conditional cfg attributes in the .rs files, so
|
||||
//
|
||||
// #[cfg(py_sys_config="{varname}"]
|
||||
//
|
||||
// is the equivalent of #ifdef {varname} name in C.
|
||||
//
|
||||
// see Misc/SpecialBuilds.txt in the python source for what these mean.
|
||||
//
|
||||
// (hrm, this is sort of re-implementing what distutils does, except
|
||||
// by passing command line args instead of referring to a python.h)
|
||||
#[cfg(not(target_os="windows"))]
|
||||
static SYSCONFIG_FLAGS: [&'static str; 7] = [
|
||||
"Py_USING_UNICODE",
|
||||
"Py_UNICODE_WIDE",
|
||||
"WITH_THREAD",
|
||||
"Py_DEBUG",
|
||||
"Py_REF_DEBUG",
|
||||
"Py_TRACE_REFS",
|
||||
"COUNT_ALLOCS",
|
||||
];
|
||||
|
||||
static SYSCONFIG_VALUES: [&'static str; 1] = [
|
||||
// cfg doesn't support flags with values, just bools - so flags
|
||||
// below are translated into bools as {varname}_{val}
|
||||
//
|
||||
// for example, Py_UNICODE_SIZE_2 or Py_UNICODE_SIZE_4
|
||||
"Py_UNICODE_SIZE" // note - not present on python 3.3+, which is always wide
|
||||
];
|
||||
|
||||
/// Examine python's compile flags to pass to cfg by launching
|
||||
/// the interpreter and printing variables of interest from
|
||||
/// sysconfig.get_config_vars.
|
||||
#[cfg(not(target_os="windows"))]
|
||||
fn get_config_vars(python_path: &String) -> Result<HashMap<String, String>, String> {
|
||||
let mut script = "import sysconfig; \
|
||||
config = sysconfig.get_config_vars();".to_owned();
|
||||
|
||||
for k in SYSCONFIG_FLAGS.iter().chain(SYSCONFIG_VALUES.iter()) {
|
||||
script.push_str(&format!("print(config.get('{}', {}))", k,
|
||||
if is_value(k) { "None" } else { "0" } ));
|
||||
script.push_str(";");
|
||||
}
|
||||
|
||||
let mut cmd = Command::new(python_path);
|
||||
cmd.arg("-c").arg(script);
|
||||
|
||||
let out = try!(cmd.output().map_err(|e| {
|
||||
format!("failed to run python interpreter `{:?}`: {}", cmd, e)
|
||||
}));
|
||||
|
||||
if !out.status.success() {
|
||||
let stderr = String::from_utf8(out.stderr).unwrap();
|
||||
let mut msg = format!("python script failed with stderr:\n\n");
|
||||
msg.push_str(&stderr);
|
||||
return Err(msg);
|
||||
}
|
||||
|
||||
let stdout = String::from_utf8(out.stdout).unwrap();
|
||||
let split_stdout: Vec<&str> = stdout.trim_right().split(NEWLINE_SEQUENCE).collect();
|
||||
if split_stdout.len() != SYSCONFIG_VALUES.len() + SYSCONFIG_FLAGS.len() {
|
||||
return Err(
|
||||
format!("python stdout len didn't return expected number of lines:
|
||||
{}", split_stdout.len()).to_string());
|
||||
}
|
||||
let all_vars = SYSCONFIG_FLAGS.iter().chain(SYSCONFIG_VALUES.iter());
|
||||
// let var_map: HashMap<String, String> = HashMap::new();
|
||||
let mut all_vars = all_vars.zip(split_stdout.iter())
|
||||
.fold(HashMap::new(), |mut memo: HashMap<String, String>, (&k, &v)| {
|
||||
if !(v.to_owned() == "None" && is_value(k)) {
|
||||
memo.insert(k.to_owned(), v.to_owned());
|
||||
}
|
||||
memo
|
||||
});
|
||||
|
||||
let debug = if let Some(val) = all_vars.get("Py_DEBUG") { val == "1" } else { false };
|
||||
if debug {
|
||||
all_vars.insert("Py_REF_DEBUG".to_owned(), "1".to_owned());
|
||||
all_vars.insert("Py_TRACE_REFS".to_owned(), "1".to_owned());
|
||||
all_vars.insert("COUNT_ALLOCS".to_owned(), "1".to_owned());
|
||||
}
|
||||
|
||||
Ok(all_vars)
|
||||
}
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
fn get_config_vars(_: &String) -> Result<HashMap<String, String>, String> {
|
||||
// sysconfig is missing all the flags on windows, so we can't actually
|
||||
// query the interpreter directly for its build flags.
|
||||
//
|
||||
// For the time being, this is the flags as defined in the python source's
|
||||
// PC\pyconfig.h. This won't work correctly if someone has built their
|
||||
// python with a modified pyconfig.h - sorry if that is you, you will have
|
||||
// to comment/uncomment the lines below.
|
||||
let mut map: HashMap<String, String> = HashMap::new();
|
||||
map.insert("Py_USING_UNICODE".to_owned(), "1".to_owned());
|
||||
map.insert("Py_UNICODE_WIDE".to_owned(), "0".to_owned());
|
||||
map.insert("WITH_THREAD".to_owned(), "1".to_owned());
|
||||
map.insert("Py_UNICODE_SIZE".to_owned(), "2".to_owned());
|
||||
|
||||
// This is defined #ifdef _DEBUG. The visual studio build seems to produce
|
||||
// a specially named pythonXX_d.exe and pythonXX_d.dll when you build the
|
||||
// Debug configuration, which this script doesn't currently support anyway.
|
||||
// map.insert("Py_DEBUG", "1");
|
||||
|
||||
// Uncomment these manually if your python was built with these and you want
|
||||
// the cfg flags to be set in rust.
|
||||
//
|
||||
// map.insert("Py_REF_DEBUG", "1");
|
||||
// map.insert("Py_TRACE_REFS", "1");
|
||||
// map.insert("COUNT_ALLOCS", 1");
|
||||
Ok(map)
|
||||
}
|
||||
|
||||
fn is_value(key: &str) -> bool {
|
||||
SYSCONFIG_VALUES.iter().find(|x| **x == key).is_some()
|
||||
}
|
||||
|
||||
fn cfg_line_for_var(key: &str, val: &str) -> Option<String> {
|
||||
if is_value(key) {
|
||||
// is a value; suffix the key name with the value
|
||||
Some(format!("cargo:rustc-cfg={}=\"{}_{}\"\n", CFG_KEY, key, val))
|
||||
} else if val != "0" {
|
||||
// is a flag that isn't zero
|
||||
Some(format!("cargo:rustc-cfg={}=\"{}\"", CFG_KEY, key))
|
||||
} else {
|
||||
// is a flag that is zero
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Run a python script using the specified interpreter binary.
|
||||
fn run_python_script(interpreter: &str, script: &str) -> Result<String, String> {
|
||||
let mut cmd = Command::new(interpreter);
|
||||
cmd.arg("-c").arg(script);
|
||||
|
||||
let out = try!(cmd.output().map_err(|e| {
|
||||
format!("failed to run python interpreter `{:?}`: {}", cmd, e)
|
||||
}));
|
||||
|
||||
if !out.status.success() {
|
||||
let stderr = String::from_utf8(out.stderr).unwrap();
|
||||
let mut msg = format!("python script failed with stderr:\n\n");
|
||||
msg.push_str(&stderr);
|
||||
return Err(msg);
|
||||
}
|
||||
|
||||
let out = String::from_utf8(out.stdout).unwrap();
|
||||
return Ok(out);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os="macos"))]
|
||||
#[cfg(not(target_os="windows"))]
|
||||
fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, enable_shared: bool) -> Result<String, String> {
|
||||
if enable_shared {
|
||||
Ok(format!("cargo:rustc-link-lib=python{}", ld_version))
|
||||
} else {
|
||||
Ok(format!("cargo:rustc-link-lib=static=python{}", ld_version))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
fn get_macos_linkmodel() -> Result<String, String> {
|
||||
let script = "import sysconfig; print('framework' if sysconfig.get_config_var('PYTHONFRAMEWORK') else ('shared' if sysconfig.get_config_var('Py_ENABLE_SHARED') else 'static'));";
|
||||
let out = run_python_script("python", script).unwrap();
|
||||
Ok(out.trim_right().to_owned())
|
||||
}
|
||||
|
||||
#[cfg(target_os="macos")]
|
||||
fn get_rustc_link_lib(_: &PythonVersion, ld_version: &str, _: bool) -> Result<String, String> {
|
||||
// os x can be linked to a framework or static or dynamic, and
|
||||
// Py_ENABLE_SHARED is wrong; framework means shared library
|
||||
match get_macos_linkmodel().unwrap().as_ref() {
|
||||
"static" => Ok(format!("cargo:rustc-link-lib=static=python{}",
|
||||
ld_version)),
|
||||
"shared" => Ok(format!("cargo:rustc-link-lib=python{}",
|
||||
ld_version)),
|
||||
"framework" => Ok(format!("cargo:rustc-link-lib=python{}",
|
||||
ld_version)),
|
||||
other => Err(format!("unknown linkmodel {}", other))
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse string as interpreter version.
|
||||
fn get_interpreter_version(line: &str) -> Result<PythonVersion, String> {
|
||||
let version_re = Regex::new(r"\((\d+), (\d+)\)").unwrap();
|
||||
match version_re.captures(&line) {
|
||||
Some(cap) => Ok(PythonVersion {
|
||||
major: cap.at(1).unwrap().parse().unwrap(),
|
||||
minor: Some(cap.at(2).unwrap().parse().unwrap())
|
||||
}),
|
||||
None => Err(
|
||||
format!("Unexpected response to version query {}", line))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os="windows")]
|
||||
fn get_rustc_link_lib(version: &PythonVersion, _: &str, _: bool) -> Result<String, String> {
|
||||
// Py_ENABLE_SHARED doesn't seem to be present on windows.
|
||||
Ok(format!("cargo:rustc-link-lib=pythonXY:python{}{}", version.major,
|
||||
match version.minor {
|
||||
Some(minor) => minor.to_string(),
|
||||
None => "".to_owned()
|
||||
}))
|
||||
}
|
||||
|
||||
fn matching_version(expected_version: &PythonVersion, actual_version: &PythonVersion) -> bool {
|
||||
actual_version.major == expected_version.major &&
|
||||
(expected_version.minor.is_none() ||
|
||||
actual_version.minor == expected_version.minor)
|
||||
}
|
||||
|
||||
/// Locate a suitable python interpreter and extract config from it.
|
||||
/// If the environment variable `PYTHON_SYS_EXECUTABLE`, use the provided
|
||||
/// path a Python executable, and raises an error if the version doesn't match.
|
||||
/// Else tries to execute the interpreter as "python", "python{major version}",
|
||||
/// "python{major version}.{minor version}" in order until one
|
||||
/// is of the version we are expecting.
|
||||
fn find_interpreter_and_get_config(expected_version: &PythonVersion) ->
|
||||
Result<(PythonVersion, String, Vec<String>), String> {
|
||||
if let Some(sys_executable) = env::var_os("PYTHON_SYS_EXECUTABLE") {
|
||||
let interpreter_path = sys_executable.to_str()
|
||||
.expect("Unable to get PYTHON_SYS_EXECUTABLE value");
|
||||
let (interpreter_version, lines) = try!(get_config_from_interpreter(interpreter_path));
|
||||
if matching_version(expected_version, &interpreter_version) {
|
||||
return Ok((interpreter_version, interpreter_path.to_owned(), lines));
|
||||
} else {
|
||||
return Err(format!("Wrong python version in PYTHON_SYS_EXECUTABLE={}\n\
|
||||
\texpected {} != found {}",
|
||||
interpreter_path,
|
||||
expected_version,
|
||||
interpreter_version));
|
||||
}
|
||||
}
|
||||
{
|
||||
let interpreter_path = "python";
|
||||
let (interpreter_version, lines) =
|
||||
try!(get_config_from_interpreter(interpreter_path));
|
||||
if matching_version(expected_version, &interpreter_version) {
|
||||
return Ok((interpreter_version, interpreter_path.to_owned(), lines));
|
||||
}
|
||||
}
|
||||
{
|
||||
let major_interpreter_path = &format!("python{}", expected_version.major);
|
||||
let (interpreter_version, lines) = try!(get_config_from_interpreter(
|
||||
major_interpreter_path));
|
||||
if matching_version(expected_version, &interpreter_version) {
|
||||
return Ok((interpreter_version, major_interpreter_path.to_owned(), lines));
|
||||
}
|
||||
}
|
||||
if let Some(minor) = expected_version.minor {
|
||||
let minor_interpreter_path = &format!("python{}.{}",
|
||||
expected_version.major, minor);
|
||||
let (interpreter_version, lines) = try!(get_config_from_interpreter(
|
||||
minor_interpreter_path));
|
||||
if matching_version(expected_version, &interpreter_version) {
|
||||
return Ok((interpreter_version, minor_interpreter_path.to_owned(), lines));
|
||||
}
|
||||
}
|
||||
Err(format!("No python interpreter found of version {}",
|
||||
expected_version))
|
||||
}
|
||||
|
||||
/// Extract compilation vars from the specified interpreter.
|
||||
fn get_config_from_interpreter(interpreter: &str) -> Result<(PythonVersion, Vec<String>), String> {
|
||||
let script = "import sys; import sysconfig; print(sys.version_info[0:2]); \
|
||||
print(sysconfig.get_config_var('LIBDIR')); \
|
||||
print(sysconfig.get_config_var('Py_ENABLE_SHARED')); \
|
||||
print(sysconfig.get_config_var('LDVERSION') or sysconfig.get_config_var('py_version_short')); \
|
||||
print(sys.exec_prefix);";
|
||||
let out = try!(run_python_script(interpreter, script));
|
||||
let lines: Vec<String> = out.split(NEWLINE_SEQUENCE).map(|line| line.to_owned()).collect();
|
||||
let interpreter_version = try!(get_interpreter_version(&lines[0]));
|
||||
Ok((interpreter_version, lines))
|
||||
}
|
||||
|
||||
/// Deduce configuration from the 'python' in the current PATH and print
|
||||
/// cargo vars to stdout.
|
||||
///
|
||||
/// Note that if the python doesn't satisfy expected_version, this will error.
|
||||
fn configure_from_path(expected_version: &PythonVersion) -> Result<(String, String), String> {
|
||||
let (interpreter_version, interpreter_path, lines) =
|
||||
try!(find_interpreter_and_get_config(expected_version));
|
||||
let libpath: &str = &lines[1];
|
||||
let enable_shared: &str = &lines[2];
|
||||
let ld_version: &str = &lines[3];
|
||||
let exec_prefix: &str = &lines[4];
|
||||
|
||||
let is_extension_module = env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some();
|
||||
if !is_extension_module || cfg!(target_os="windows") {
|
||||
println!("{}", get_rustc_link_lib(&interpreter_version,
|
||||
ld_version, enable_shared == "1").unwrap());
|
||||
if libpath != "None" {
|
||||
println!("cargo:rustc-link-search=native={}", libpath);
|
||||
} else if cfg!(target_os="windows") {
|
||||
println!("cargo:rustc-link-search=native={}\\libs", exec_prefix);
|
||||
}
|
||||
}
|
||||
|
||||
let mut flags = String::new();
|
||||
|
||||
if let PythonVersion { major: 3, minor: some_minor} = interpreter_version {
|
||||
if env::var_os("CARGO_FEATURE_PEP_384").is_some() {
|
||||
println!("cargo:rustc-cfg=Py_LIMITED_API");
|
||||
}
|
||||
if let Some(minor) = some_minor {
|
||||
for i in 4..(minor+1) {
|
||||
println!("cargo:rustc-cfg=Py_3_{}", i);
|
||||
flags += format!("CFG_Py_3_{},", i).as_ref();
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok((interpreter_path, flags));
|
||||
}
|
||||
|
||||
/// Determine the python version we're supposed to be building
|
||||
/// from the features passed via the environment.
|
||||
///
|
||||
/// The environment variable can choose to omit a minor
|
||||
/// version if the user doesn't care.
|
||||
fn version_from_env() -> Result<PythonVersion, String> {
|
||||
let re = Regex::new(r"CARGO_FEATURE_PYTHON_(\d+)(_(\d+))?").unwrap();
|
||||
// sort env::vars so we get more explicit version specifiers first
|
||||
// so if the user passes e.g. the python-3 feature and the python-3-5
|
||||
// feature, python-3-5 takes priority.
|
||||
let mut vars = env::vars().collect::<Vec<_>>();
|
||||
vars.sort_by(|a, b| b.cmp(a));
|
||||
for (key, _) in vars {
|
||||
match re.captures(&key) {
|
||||
Some(cap) => return Ok(PythonVersion {
|
||||
major: cap.at(1).unwrap().parse().unwrap(),
|
||||
minor: match cap.at(3) {
|
||||
Some(s) => Some(s.parse().unwrap()),
|
||||
None => None
|
||||
}
|
||||
}),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
Err("Python version feature was not found. At least one python version \
|
||||
feature must be enabled.".to_owned())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// 1. Setup cfg variables so we can do conditional compilation in this
|
||||
// library based on the python interpeter's compilation flags. This is
|
||||
// necessary for e.g. matching the right unicode and threading interfaces.
|
||||
//
|
||||
// This locates the python interpreter based on the PATH, which should
|
||||
// work smoothly with an activated virtualenv.
|
||||
//
|
||||
// If you have troubles with your shell accepting '.' in a var name,
|
||||
// try using 'env' (sorry but this isn't our fault - it just has to
|
||||
// match the pkg-config package name, which is going to have a . in it).
|
||||
let version = version_from_env().unwrap();
|
||||
let (python_interpreter_path, flags) = configure_from_path(&version).unwrap();
|
||||
let config_map = get_config_vars(&python_interpreter_path).unwrap();
|
||||
for (key, val) in &config_map {
|
||||
match cfg_line_for_var(key, val) {
|
||||
Some(line) => println!("{}", line),
|
||||
None => ()
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Export python interpreter compilation flags as cargo variables that
|
||||
// will be visible to dependents. All flags will be available to dependent
|
||||
// build scripts in the environment variable DEP_PYTHON27_PYTHON_FLAGS as
|
||||
// comma separated list; each item in the list looks like
|
||||
//
|
||||
// {VAL,FLAG}_{flag_name}=val;
|
||||
//
|
||||
// FLAG indicates the variable is always 0 or 1
|
||||
// VAL indicates it can take on any value
|
||||
//
|
||||
// rust-cypthon/build.rs contains an example of how to unpack this data
|
||||
// into cfg flags that replicate the ones present in this library, so
|
||||
// you can use the same cfg syntax.
|
||||
//let mut flags = flags;
|
||||
let flags: String = config_map.iter().fold("".to_owned(), |memo, (key, val)| {
|
||||
if is_value(key) {
|
||||
memo + format!("VAL_{}={},", key, val).as_ref()
|
||||
} else if val != "0" {
|
||||
memo + format!("FLAG_{}={},", key, val).as_ref()
|
||||
} else {
|
||||
memo
|
||||
}
|
||||
}) + flags.as_str();
|
||||
|
||||
println!("cargo:python_flags={}",
|
||||
if flags.len() > 0 { &flags[..flags.len()-1] } else { "" });
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
extern crate libc;
|
||||
extern crate python3_sys;
|
||||
|
||||
unsafe fn get_str<'a>(s: *const libc::c_char) -> &'a str {
|
||||
let bytes = std::ffi::CStr::from_ptr(s).to_bytes();
|
||||
std::str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
python3_sys::Py_Initialize();
|
||||
println!("{}", get_str(python3_sys::Py_GetVersion()));
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use std::os::raw;
|
||||
use std::{mem, slice, cell};
|
||||
use std::ffi::CStr;
|
||||
use ffi;
|
||||
|
@ -62,18 +63,18 @@ impl ElementType {
|
|||
fn native_element_type_from_type_char(type_char: u8) -> ElementType {
|
||||
use self::ElementType::*;
|
||||
match type_char {
|
||||
b'c' => UnsignedInteger { bytes: mem::size_of::<libc::c_char>() },
|
||||
b'b' => SignedInteger { bytes: mem::size_of::<libc::c_schar>() },
|
||||
b'B' => UnsignedInteger { bytes: mem::size_of::<libc::c_uchar>() },
|
||||
b'c' => UnsignedInteger { bytes: mem::size_of::<raw::c_char>() },
|
||||
b'b' => SignedInteger { bytes: mem::size_of::<raw::c_schar>() },
|
||||
b'B' => UnsignedInteger { bytes: mem::size_of::<raw::c_uchar>() },
|
||||
b'?' => Bool,
|
||||
b'h' => SignedInteger { bytes: mem::size_of::<libc::c_short>() },
|
||||
b'H' => UnsignedInteger { bytes: mem::size_of::<libc::c_ushort>() },
|
||||
b'i' => SignedInteger { bytes: mem::size_of::<libc::c_int>() },
|
||||
b'I' => UnsignedInteger { bytes: mem::size_of::<libc::c_uint>() },
|
||||
b'l' => SignedInteger { bytes: mem::size_of::<libc::c_long>() },
|
||||
b'L' => UnsignedInteger { bytes: mem::size_of::<libc::c_ulong>() },
|
||||
b'q' => SignedInteger { bytes: mem::size_of::<libc::c_longlong>() },
|
||||
b'Q' => UnsignedInteger { bytes: mem::size_of::<libc::c_ulonglong>() },
|
||||
b'h' => SignedInteger { bytes: mem::size_of::<raw::c_short>() },
|
||||
b'H' => UnsignedInteger { bytes: mem::size_of::<raw::c_ushort>() },
|
||||
b'i' => SignedInteger { bytes: mem::size_of::<raw::c_int>() },
|
||||
b'I' => UnsignedInteger { bytes: mem::size_of::<raw::c_uint>() },
|
||||
b'l' => SignedInteger { bytes: mem::size_of::<raw::c_long>() },
|
||||
b'L' => UnsignedInteger { bytes: mem::size_of::<raw::c_ulong>() },
|
||||
b'q' => SignedInteger { bytes: mem::size_of::<raw::c_longlong>() },
|
||||
b'Q' => UnsignedInteger { bytes: mem::size_of::<raw::c_ulonglong>() },
|
||||
b'n' => SignedInteger { bytes: mem::size_of::<libc::ssize_t>() },
|
||||
b'N' => UnsignedInteger { bytes: mem::size_of::<libc::size_t>() },
|
||||
b'e' => Float { bytes: 2 },
|
||||
|
@ -150,14 +151,14 @@ impl PyBuffer {
|
|||
/// Warning: the buffer memory might be mutated by other Python functions,
|
||||
/// and thus may only be accessed while the GIL is held.
|
||||
#[inline]
|
||||
pub fn buf_ptr(&self) -> *mut libc::c_void {
|
||||
pub fn buf_ptr(&self) -> *mut raw::c_void {
|
||||
self.0.buf
|
||||
}
|
||||
|
||||
/// Gets a pointer to the specified item.
|
||||
///
|
||||
/// If `indices.len() < self.dimensions()`, returns the start address of the sub-array at the specified dimension.
|
||||
pub fn get_ptr(&self, indices: &[usize]) -> *mut libc::c_void {
|
||||
pub fn get_ptr(&self, indices: &[usize]) -> *mut raw::c_void {
|
||||
let shape = &self.shape()[..indices.len()];
|
||||
for i in 0..indices.len() {
|
||||
assert!(indices[i] < shape[i]);
|
||||
|
@ -397,7 +398,7 @@ impl PyBuffer {
|
|||
}
|
||||
unsafe {
|
||||
err::error_on_minusone(py, ffi::PyBuffer_ToContiguous(
|
||||
target.as_ptr() as *mut libc::c_void,
|
||||
target.as_ptr() as *mut raw::c_void,
|
||||
&*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer,
|
||||
self.0.len,
|
||||
fort as libc::c_char
|
||||
|
@ -432,7 +433,7 @@ impl PyBuffer {
|
|||
// Copy the buffer into the uninitialized space in the vector.
|
||||
// Due to T:Copy, we don't need to be concerned with Drop impls.
|
||||
err::error_on_minusone(py, ffi::PyBuffer_ToContiguous(
|
||||
vec.as_mut_ptr() as *mut libc::c_void,
|
||||
vec.as_mut_ptr() as *mut raw::c_void,
|
||||
&*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer,
|
||||
self.0.len,
|
||||
fort as libc::c_char
|
||||
|
@ -484,7 +485,7 @@ impl PyBuffer {
|
|||
unsafe {
|
||||
err::error_on_minusone(py, ffi::PyBuffer_FromContiguous(
|
||||
&*self.0 as *const ffi::Py_buffer as *mut ffi::Py_buffer,
|
||||
source.as_ptr() as *mut libc::c_void,
|
||||
source.as_ptr() as *mut raw::c_void,
|
||||
self.0.len,
|
||||
fort as libc::c_char
|
||||
))
|
||||
|
|
18
src/err.rs
18
src/err.rs
|
@ -20,8 +20,6 @@ use std;
|
|||
use python::{PythonObject, ToPythonPointer, Python, PythonObjectDowncastError,
|
||||
PythonObjectWithTypeObject, PyClone, PyDrop};
|
||||
use objects::{PyObject, PyType, ToPyTuple, exc};
|
||||
#[cfg(feature="python27-sys")]
|
||||
use objects::oldstyle::PyClass;
|
||||
use ffi;
|
||||
use libc;
|
||||
use std::ptr;
|
||||
|
@ -330,22 +328,6 @@ impl PyErr {
|
|||
}
|
||||
|
||||
/// Retrieves the exception type.
|
||||
///
|
||||
/// If the exception type is an old-style class, returns `oldstyle::PyClass`.
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
match self.ptype.cast_as::<PyType>(py) {
|
||||
Ok(t) => t.clone_ref(py),
|
||||
Err(_) =>
|
||||
match self.ptype.cast_as::<PyClass>(py) {
|
||||
Ok(_) => py.get_type::<PyClass>(),
|
||||
Err(_) => py.None().get_type(py)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the exception type.
|
||||
#[cfg(not(feature="python27-sys"))]
|
||||
pub fn get_type(&self, py: Python) -> PyType {
|
||||
match self.ptype.cast_as::<PyType>(py) {
|
||||
Ok(t) => t.clone_ref(py),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use object::PyTypeObject;
|
||||
use ffi::object::PyTypeObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyFilter_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_int, c_long};
|
||||
use object::*;
|
||||
use longobject::PyLongObject;
|
||||
use std::os::raw::{c_int, c_long};
|
||||
use ffi::object::*;
|
||||
use ffi::longobject::PyLongObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyBool_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::*;
|
||||
use pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::*;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyByteArray_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::*;
|
||||
use pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::*;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyBytes_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_void, c_char, c_int};
|
||||
use object::PyObject;
|
||||
use pystate::PyThreadState;
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::object::PyObject;
|
||||
use ffi::pystate::PyThreadState;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyEval_CallObjectWithKeywords(func: *mut PyObject,
|
||||
|
@ -11,7 +11,7 @@ use pystate::PyThreadState;
|
|||
|
||||
#[inline]
|
||||
pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut PyObject {
|
||||
PyEval_CallObjectWithKeywords(func, arg, ::core::ptr::null_mut())
|
||||
PyEval_CallObjectWithKeywords(func, arg, ::std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
|
@ -25,7 +25,7 @@ pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut
|
|||
pub fn PyEval_GetBuiltins() -> *mut PyObject;
|
||||
pub fn PyEval_GetGlobals() -> *mut PyObject;
|
||||
pub fn PyEval_GetLocals() -> *mut PyObject;
|
||||
pub fn PyEval_GetFrame() -> *mut ::PyFrameObject;
|
||||
pub fn PyEval_GetFrame() -> *mut ::ffi::PyFrameObject;
|
||||
pub fn Py_AddPendingCall(func: Option<extern "C" fn(arg1: *mut c_void) -> c_int>,
|
||||
arg: *mut c_void) -> c_int;
|
||||
pub fn Py_MakePendingCalls() -> c_int;
|
||||
|
@ -43,8 +43,8 @@ pub unsafe fn PyEval_CallObject(func: *mut PyObject, arg: *mut PyObject) -> *mut
|
|||
pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char;
|
||||
pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char;
|
||||
pub fn PyEval_GetCallStats(arg1: *mut PyObject) -> *mut PyObject;
|
||||
pub fn PyEval_EvalFrame(arg1: *mut ::PyFrameObject) -> *mut PyObject;
|
||||
pub fn PyEval_EvalFrameEx(f: *mut ::PyFrameObject, exc: c_int)
|
||||
pub fn PyEval_EvalFrame(arg1: *mut ::ffi::PyFrameObject) -> *mut PyObject;
|
||||
pub fn PyEval_EvalFrameEx(f: *mut ::ffi::PyFrameObject, exc: c_int)
|
||||
-> *mut PyObject;
|
||||
pub fn PyEval_SaveThread() -> *mut PyThreadState;
|
||||
pub fn PyEval_RestoreThread(arg1: *mut PyThreadState) -> ();
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_void, c_uchar, c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::{c_void, c_uchar, c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
|
@ -34,7 +34,7 @@ impl Clone for PyCodeObject {
|
|||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyCodeObject {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
/* Masks for co_flags */
|
||||
|
@ -98,6 +98,6 @@ pub unsafe fn PyCode_Check(op : *mut PyObject) -> c_int {
|
|||
|
||||
#[inline]
|
||||
pub unsafe fn PyCode_GetNumFree(op : *mut PyCodeObject) -> Py_ssize_t {
|
||||
::tupleobject::PyTuple_GET_SIZE((*op).co_freevars)
|
||||
::ffi::tupleobject::PyTuple_GET_SIZE((*op).co_freevars)
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyCodec_Register(search_function: *mut PyObject) -> c_int;
|
|
@ -1,8 +1,8 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::PyObject;
|
||||
use pythonrun::*;
|
||||
use code::*;
|
||||
use pyarena::*;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::PyObject;
|
||||
use ffi::pythonrun::*;
|
||||
use ffi::code::*;
|
||||
use ffi::pyarena::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_double, c_int};
|
||||
use object::*;
|
||||
use std::os::raw::{c_double, c_int};
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyComplex_Type: PyTypeObject;
|
|
@ -1,7 +1,7 @@
|
|||
use libc::{c_void, c_char, c_int};
|
||||
use object::{PyObject, PyTypeObject};
|
||||
use structmember::PyMemberDef;
|
||||
use methodobject::PyMethodDef;
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::object::{PyObject, PyTypeObject};
|
||||
use ffi::structmember::PyMemberDef;
|
||||
use ffi::methodobject::PyMethodDef;
|
||||
|
||||
pub type getter =
|
||||
unsafe extern "C" fn
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyDict_Type: PyTypeObject;
|
|
@ -1,4 +1,4 @@
|
|||
use object::PyTypeObject;
|
||||
use ffi::object::PyTypeObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyEnum_Type: PyTypeObject;
|
|
@ -1,5 +1,5 @@
|
|||
use libc::c_int;
|
||||
use object::PyObject;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyEval_EvalCode(arg1: *mut PyObject, arg2: *mut PyObject,
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::PyObject;
|
||||
|
||||
pub const PY_STDIOTEXTMODE : &'static str = "b";
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_int, c_double};
|
||||
use object::*;
|
||||
use std::os::raw::{c_int, c_double};
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyFloat_Type: PyTypeObject;
|
|
@ -1,7 +1,7 @@
|
|||
use libc::{c_char, c_int};
|
||||
use object::*;
|
||||
use code::{PyCodeObject, CO_MAXBLOCKS};
|
||||
use pystate::PyThreadState;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::object::*;
|
||||
use ffi::code::{PyCodeObject, CO_MAXBLOCKS};
|
||||
use ffi::pystate::PyThreadState;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
|
@ -1,7 +1,7 @@
|
|||
use libc::c_int;
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use frameobject::PyFrameObject;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
use ffi::frameobject::PyFrameObject;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -49,7 +49,7 @@ pub unsafe fn PyCoro_Check(op: *mut PyObject) -> c_int {
|
|||
}
|
||||
#[cfg(not(Py_3_5))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyCoro_Check(op: *mut PyObject) -> c_int {
|
||||
pub unsafe fn PyCoro_Check(_op: *mut PyObject) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ pub unsafe fn PyCoroWrapper_Check(op: *mut PyObject) -> c_int {
|
|||
}
|
||||
#[cfg(not(Py_3_5))]
|
||||
#[inline(always)]
|
||||
pub unsafe fn PyCoroWrapper_Check(op: *mut PyObject) -> c_int {
|
||||
pub unsafe fn PyCoroWrapper_Check(_op: *mut PyObject) -> c_int {
|
||||
0
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int, c_long};
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int, c_long};
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyImport_GetMagicNumber() -> c_long;
|
|
@ -1,5 +1,5 @@
|
|||
use libc::c_int;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PySeqIter_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::c_int;
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyList_Type: PyTypeObject;
|
|
@ -1,6 +1,7 @@
|
|||
use libc::{c_void, c_char, c_int, c_long, c_ulong, c_longlong, c_ulonglong, c_double, size_t};
|
||||
use object::*;
|
||||
use pyport::Py_ssize_t;
|
||||
use libc::size_t;
|
||||
use std::os::raw::{c_void, c_char, c_int, c_long, c_ulong, c_longlong, c_ulonglong, c_double};
|
||||
use ffi::object::*;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
pub enum PyLongObject {}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_int, c_char};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::{c_int, c_char};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyMemoryView_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use core::{mem, ptr};
|
||||
use object::{PyObject, PyTypeObject, Py_TYPE};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::{mem, ptr};
|
||||
use ffi::object::{PyObject, PyTypeObject, Py_TYPE};
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyCFunction_Type: PyTypeObject;
|
||||
|
@ -20,7 +20,7 @@ pub type PyCFunction =
|
|||
pub type _PyCFunctionFast =
|
||||
unsafe extern "C" fn
|
||||
(slf: *mut PyObject, args: *mut *mut PyObject,
|
||||
nargs: ::pyport::Py_ssize_t, kwnames: *mut PyObject)
|
||||
nargs: ::ffi::pyport::Py_ssize_t, kwnames: *mut PyObject)
|
||||
-> *mut PyObject;
|
||||
|
||||
pub type PyCFunctionWithKeywords =
|
|
@ -1,4 +1,3 @@
|
|||
#![no_std]
|
||||
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||
#![cfg_attr(Py_LIMITED_API, allow(unused_imports))]
|
||||
|
||||
|
@ -9,68 +8,66 @@
|
|||
// new:
|
||||
// Based on the headers of Python 3.3.0, 3.4.0 and 3.5.0.
|
||||
|
||||
extern crate libc;
|
||||
pub use self::pyport::*;
|
||||
pub use self::pymem::*;
|
||||
|
||||
pub use pyport::*;
|
||||
pub use pymem::*;
|
||||
pub use self::object::*;
|
||||
pub use self::objimpl::*;
|
||||
pub use self::typeslots::*;
|
||||
pub use self::pyhash::*;
|
||||
|
||||
pub use object::*;
|
||||
pub use objimpl::*;
|
||||
pub use typeslots::*;
|
||||
#[cfg(Py_3_4)] pub use pyhash::*;
|
||||
pub use self::pydebug::*;
|
||||
|
||||
pub use pydebug::*;
|
||||
pub use self::bytearrayobject::*;
|
||||
pub use self::bytesobject::*;
|
||||
pub use self::unicodeobject::*;
|
||||
pub use self::longobject::*;
|
||||
pub use self::boolobject::*;
|
||||
pub use self::floatobject::*;
|
||||
pub use self::complexobject::*;
|
||||
pub use self::rangeobject::*;
|
||||
pub use self::memoryobject::*;
|
||||
pub use self::tupleobject::*;
|
||||
pub use self::listobject::*;
|
||||
pub use self::dictobject::*;
|
||||
pub use self::enumobject::*;
|
||||
pub use self::setobject::*;
|
||||
pub use self::methodobject::*;
|
||||
pub use self::moduleobject::*;
|
||||
pub use self::fileobject::*;
|
||||
pub use self::pycapsule::*;
|
||||
pub use self::traceback::*;
|
||||
pub use self::sliceobject::*;
|
||||
pub use self::iterobject::*;
|
||||
pub use self::descrobject::*;
|
||||
pub use self::warnings::*;
|
||||
pub use self::weakrefobject::*;
|
||||
pub use self::structseq::*;
|
||||
pub use self::genobject::*;
|
||||
|
||||
pub use bytearrayobject::*;
|
||||
pub use bytesobject::*;
|
||||
pub use unicodeobject::*;
|
||||
pub use longobject::*;
|
||||
pub use boolobject::*;
|
||||
pub use floatobject::*;
|
||||
pub use complexobject::*;
|
||||
pub use rangeobject::*;
|
||||
pub use memoryobject::*;
|
||||
pub use tupleobject::*;
|
||||
pub use listobject::*;
|
||||
pub use dictobject::*;
|
||||
pub use enumobject::*;
|
||||
pub use setobject::*;
|
||||
pub use methodobject::*;
|
||||
pub use moduleobject::*;
|
||||
pub use fileobject::*;
|
||||
pub use pycapsule::*;
|
||||
pub use traceback::*;
|
||||
pub use sliceobject::*;
|
||||
pub use iterobject::*;
|
||||
pub use descrobject::*;
|
||||
pub use warnings::*;
|
||||
pub use weakrefobject::*;
|
||||
pub use structseq::*;
|
||||
pub use genobject::*;
|
||||
pub use self::codecs::*;
|
||||
pub use self::pyerrors::*;
|
||||
|
||||
pub use codecs::*;
|
||||
pub use pyerrors::*;
|
||||
pub use self::pystate::*;
|
||||
|
||||
pub use pystate::*;
|
||||
pub use self::pyarena::*;
|
||||
pub use self::modsupport::*;
|
||||
pub use self::pythonrun::*;
|
||||
pub use self::ceval::*;
|
||||
pub use self::sysmodule::*;
|
||||
#[cfg(Py_3_6)] pub use self::osmodule::*;
|
||||
pub use self::intrcheck::*;
|
||||
pub use self::import::*;
|
||||
|
||||
pub use pyarena::*;
|
||||
pub use modsupport::*;
|
||||
pub use pythonrun::*;
|
||||
pub use ceval::*;
|
||||
pub use sysmodule::*;
|
||||
#[cfg(Py_3_6)] pub use osmodule::*;
|
||||
pub use intrcheck::*;
|
||||
pub use import::*;
|
||||
pub use self::objectabstract::*;
|
||||
pub use self::bltinmodule::*;
|
||||
|
||||
pub use objectabstract::*;
|
||||
pub use bltinmodule::*;
|
||||
pub use self::code::*;
|
||||
pub use self::compile::*;
|
||||
pub use self::eval::*;
|
||||
|
||||
pub use code::*;
|
||||
pub use compile::*;
|
||||
pub use eval::*;
|
||||
|
||||
pub use pystrtod::*;
|
||||
pub use frameobject::PyFrameObject;
|
||||
pub use self::pystrtod::*;
|
||||
pub use self::frameobject::PyFrameObject;
|
||||
|
||||
mod pyport;
|
||||
// mod pymacro; contains nothing of interest for Rust
|
||||
|
@ -87,7 +84,7 @@ mod pymem;
|
|||
mod object;
|
||||
mod objimpl;
|
||||
mod typeslots;
|
||||
#[cfg(Py_3_4)] mod pyhash;
|
||||
mod pyhash;
|
||||
|
||||
mod pydebug;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
use libc::{c_char, c_int, c_long};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::PyObject;
|
||||
use moduleobject::PyModuleDef;
|
||||
use std::os::raw::{c_char, c_int, c_long};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::PyObject;
|
||||
use ffi::moduleobject::PyModuleDef;
|
||||
#[cfg(Py_3_5)]
|
||||
use methodobject::PyMethodDef;
|
||||
use ffi::methodobject::PyMethodDef;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyArg_Parse(arg1: *mut PyObject, arg2: *const c_char, ...)
|
|
@ -1,7 +1,7 @@
|
|||
use libc::{c_char, c_int, c_void};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use methodobject::PyMethodDef;
|
||||
use std::os::raw::{c_char, c_int, c_void};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
use ffi::methodobject::PyMethodDef;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyModule_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use core::ptr;
|
||||
use libc::{c_void, c_int, c_uint, c_ulong, c_char};
|
||||
use pyport::{Py_ssize_t, Py_hash_t};
|
||||
use std::ptr;
|
||||
use std::os::raw::{c_void, c_int, c_uint, c_ulong, c_char};
|
||||
use ffi::pyport::{Py_ssize_t, Py_hash_t};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -88,14 +88,14 @@ pub type objobjargproc =
|
|||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
mod bufferinfo {
|
||||
use libc::{c_void, c_int, c_char};
|
||||
use pyport::Py_ssize_t;
|
||||
use std::os::raw::{c_void, c_int, c_char};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct Py_buffer {
|
||||
pub buf: *mut c_void,
|
||||
pub obj: *mut ::object::PyObject,
|
||||
pub obj: *mut ::PyObject,
|
||||
pub len: Py_ssize_t,
|
||||
pub itemsize: Py_ssize_t,
|
||||
pub readonly: c_int,
|
||||
|
@ -110,17 +110,17 @@ mod bufferinfo {
|
|||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for Py_buffer {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
pub type getbufferproc =
|
||||
unsafe extern "C" fn(arg1: *mut ::object::PyObject,
|
||||
arg2: *mut Py_buffer,
|
||||
arg3: c_int)
|
||||
-> c_int;
|
||||
unsafe extern "C" fn(arg1: *mut ::PyObject,
|
||||
arg2: *mut Py_buffer,
|
||||
arg3: c_int)
|
||||
-> c_int;
|
||||
pub type releasebufferproc =
|
||||
unsafe extern "C" fn(arg1: *mut ::object::PyObject,
|
||||
arg2: *mut Py_buffer) -> ();
|
||||
unsafe extern "C" fn(arg1: *mut ::PyObject,
|
||||
arg2: *mut Py_buffer) -> ();
|
||||
|
||||
/// Maximum number of dimensions
|
||||
pub const PyBUF_MAX_NDIM : c_int = 64;
|
||||
|
@ -236,56 +236,57 @@ pub enum PyTypeObject { }
|
|||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
mod typeobject {
|
||||
use libc::{c_void, c_char, c_ulong, c_uint};
|
||||
use pyport::Py_ssize_t;
|
||||
use ffi::{self, object};
|
||||
use std::os::raw::{c_void, c_char, c_ulong, c_uint};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct PyNumberMethods {
|
||||
pub nb_add: Option<::object::binaryfunc>,
|
||||
pub nb_subtract: Option<::object::binaryfunc>,
|
||||
pub nb_multiply: Option<::object::binaryfunc>,
|
||||
pub nb_remainder: Option<::object::binaryfunc>,
|
||||
pub nb_divmod: Option<::object::binaryfunc>,
|
||||
pub nb_power: Option<::object::ternaryfunc>,
|
||||
pub nb_negative: Option<::object::unaryfunc>,
|
||||
pub nb_positive: Option<::object::unaryfunc>,
|
||||
pub nb_absolute: Option<::object::unaryfunc>,
|
||||
pub nb_bool: Option<::object::inquiry>,
|
||||
pub nb_invert: Option<::object::unaryfunc>,
|
||||
pub nb_lshift: Option<::object::binaryfunc>,
|
||||
pub nb_rshift: Option<::object::binaryfunc>,
|
||||
pub nb_and: Option<::object::binaryfunc>,
|
||||
pub nb_xor: Option<::object::binaryfunc>,
|
||||
pub nb_or: Option<::object::binaryfunc>,
|
||||
pub nb_int: Option<::object::unaryfunc>,
|
||||
pub nb_add: Option<object::binaryfunc>,
|
||||
pub nb_subtract: Option<object::binaryfunc>,
|
||||
pub nb_multiply: Option<object::binaryfunc>,
|
||||
pub nb_remainder: Option<object::binaryfunc>,
|
||||
pub nb_divmod: Option<object::binaryfunc>,
|
||||
pub nb_power: Option<object::ternaryfunc>,
|
||||
pub nb_negative: Option<object::unaryfunc>,
|
||||
pub nb_positive: Option<object::unaryfunc>,
|
||||
pub nb_absolute: Option<object::unaryfunc>,
|
||||
pub nb_bool: Option<object::inquiry>,
|
||||
pub nb_invert: Option<object::unaryfunc>,
|
||||
pub nb_lshift: Option<object::binaryfunc>,
|
||||
pub nb_rshift: Option<object::binaryfunc>,
|
||||
pub nb_and: Option<object::binaryfunc>,
|
||||
pub nb_xor: Option<object::binaryfunc>,
|
||||
pub nb_or: Option<object::binaryfunc>,
|
||||
pub nb_int: Option<object::unaryfunc>,
|
||||
pub nb_reserved: *mut c_void,
|
||||
pub nb_float: Option<::object::unaryfunc>,
|
||||
pub nb_inplace_add: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_subtract: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_multiply: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_remainder: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_power: Option<::object::ternaryfunc>,
|
||||
pub nb_inplace_lshift: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_rshift: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_and: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_xor: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_or: Option<::object::binaryfunc>,
|
||||
pub nb_floor_divide: Option<::object::binaryfunc>,
|
||||
pub nb_true_divide: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_floor_divide: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_true_divide: Option<::object::binaryfunc>,
|
||||
pub nb_index: Option<::object::unaryfunc>,
|
||||
pub nb_float: Option<object::unaryfunc>,
|
||||
pub nb_inplace_add: Option<object::binaryfunc>,
|
||||
pub nb_inplace_subtract: Option<object::binaryfunc>,
|
||||
pub nb_inplace_multiply: Option<object::binaryfunc>,
|
||||
pub nb_inplace_remainder: Option<object::binaryfunc>,
|
||||
pub nb_inplace_power: Option<object::ternaryfunc>,
|
||||
pub nb_inplace_lshift: Option<object::binaryfunc>,
|
||||
pub nb_inplace_rshift: Option<object::binaryfunc>,
|
||||
pub nb_inplace_and: Option<object::binaryfunc>,
|
||||
pub nb_inplace_xor: Option<object::binaryfunc>,
|
||||
pub nb_inplace_or: Option<object::binaryfunc>,
|
||||
pub nb_floor_divide: Option<object::binaryfunc>,
|
||||
pub nb_true_divide: Option<object::binaryfunc>,
|
||||
pub nb_inplace_floor_divide: Option<object::binaryfunc>,
|
||||
pub nb_inplace_true_divide: Option<object::binaryfunc>,
|
||||
pub nb_index: Option<object::unaryfunc>,
|
||||
#[cfg(Py_3_5)]
|
||||
pub nb_matrix_multiply: Option<::object::binaryfunc>,
|
||||
pub nb_matrix_multiply: Option<object::binaryfunc>,
|
||||
#[cfg(Py_3_5)]
|
||||
pub nb_inplace_matrix_multiply: Option<::object::binaryfunc>,
|
||||
pub nb_inplace_matrix_multiply: Option<object::binaryfunc>,
|
||||
}
|
||||
impl Clone for PyNumberMethods {
|
||||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyNumberMethods {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
macro_rules! as_expr { ($e:expr) => {$e} }
|
||||
|
||||
|
@ -346,22 +347,22 @@ mod typeobject {
|
|||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct PySequenceMethods {
|
||||
pub sq_length: Option<::object::lenfunc>,
|
||||
pub sq_concat: Option<::object::binaryfunc>,
|
||||
pub sq_repeat: Option<::object::ssizeargfunc>,
|
||||
pub sq_item: Option<::object::ssizeargfunc>,
|
||||
pub sq_length: Option<object::lenfunc>,
|
||||
pub sq_concat: Option<object::binaryfunc>,
|
||||
pub sq_repeat: Option<object::ssizeargfunc>,
|
||||
pub sq_item: Option<object::ssizeargfunc>,
|
||||
pub was_sq_slice: *mut c_void,
|
||||
pub sq_ass_item: Option<::object::ssizeobjargproc>,
|
||||
pub sq_ass_item: Option<object::ssizeobjargproc>,
|
||||
pub was_sq_ass_slice: *mut c_void,
|
||||
pub sq_contains: Option<::object::objobjproc>,
|
||||
pub sq_inplace_concat: Option<::object::binaryfunc>,
|
||||
pub sq_inplace_repeat: Option<::object::ssizeargfunc>,
|
||||
pub sq_contains: Option<object::objobjproc>,
|
||||
pub sq_inplace_concat: Option<object::binaryfunc>,
|
||||
pub sq_inplace_repeat: Option<object::ssizeargfunc>,
|
||||
}
|
||||
impl Clone for PySequenceMethods {
|
||||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PySequenceMethods {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
pub const PySequenceMethods_INIT : PySequenceMethods = PySequenceMethods {
|
||||
sq_length: None,
|
||||
|
@ -378,15 +379,15 @@ mod typeobject {
|
|||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct PyMappingMethods {
|
||||
pub mp_length: Option<::object::lenfunc>,
|
||||
pub mp_subscript: Option<::object::binaryfunc>,
|
||||
pub mp_ass_subscript: Option<::object::objobjargproc>,
|
||||
pub mp_length: Option<object::lenfunc>,
|
||||
pub mp_subscript: Option<object::binaryfunc>,
|
||||
pub mp_ass_subscript: Option<object::objobjargproc>,
|
||||
}
|
||||
impl Clone for PyMappingMethods {
|
||||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyMappingMethods {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
pub const PyMappingMethods_INIT : PyMappingMethods = PyMappingMethods {
|
||||
mp_length: None,
|
||||
|
@ -397,9 +398,9 @@ mod typeobject {
|
|||
#[derive(Copy)]
|
||||
#[cfg(Py_3_5)]
|
||||
pub struct PyAsyncMethods {
|
||||
pub am_await: Option<::object::unaryfunc>,
|
||||
pub am_aiter: Option<::object::unaryfunc>,
|
||||
pub am_anext: Option<::object::unaryfunc>,
|
||||
pub am_await: Option<object::unaryfunc>,
|
||||
pub am_aiter: Option<object::unaryfunc>,
|
||||
pub am_anext: Option<object::unaryfunc>,
|
||||
}
|
||||
#[cfg(Py_3_5)]
|
||||
impl Clone for PyAsyncMethods {
|
||||
|
@ -407,7 +408,7 @@ mod typeobject {
|
|||
}
|
||||
#[cfg(Py_3_5)]
|
||||
impl Default for PyAsyncMethods {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[cfg(Py_3_5)]
|
||||
pub const PyAsyncMethods_INIT : PyAsyncMethods = PyAsyncMethods {
|
||||
|
@ -418,14 +419,14 @@ mod typeobject {
|
|||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct PyBufferProcs {
|
||||
pub bf_getbuffer: Option<::object::getbufferproc>,
|
||||
pub bf_releasebuffer: Option<::object::releasebufferproc>,
|
||||
pub bf_getbuffer: Option<object::getbufferproc>,
|
||||
pub bf_releasebuffer: Option<object::releasebufferproc>,
|
||||
}
|
||||
impl Clone for PyBufferProcs {
|
||||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyBufferProcs {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
pub const PyBufferProcs_INIT : PyBufferProcs = PyBufferProcs {
|
||||
bf_getbuffer: None,
|
||||
|
@ -435,58 +436,58 @@ mod typeobject {
|
|||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
pub struct PyTypeObject {
|
||||
pub ob_base: ::object::PyVarObject,
|
||||
pub ob_base: object::PyVarObject,
|
||||
pub tp_name: *const c_char,
|
||||
pub tp_basicsize: Py_ssize_t,
|
||||
pub tp_itemsize: Py_ssize_t,
|
||||
pub tp_dealloc: Option<::object::destructor>,
|
||||
pub tp_print: Option<::object::printfunc>,
|
||||
pub tp_getattr: Option<::object::getattrfunc>,
|
||||
pub tp_setattr: Option<::object::setattrfunc>,
|
||||
pub tp_dealloc: Option<object::destructor>,
|
||||
pub tp_print: Option<object::printfunc>,
|
||||
pub tp_getattr: Option<object::getattrfunc>,
|
||||
pub tp_setattr: Option<object::setattrfunc>,
|
||||
#[cfg(Py_3_5)]
|
||||
pub tp_as_async: *mut PyAsyncMethods,
|
||||
#[cfg(not(Py_3_5))]
|
||||
pub tp_reserved: *mut c_void,
|
||||
pub tp_repr: Option<::object::reprfunc>,
|
||||
pub tp_repr: Option<object::reprfunc>,
|
||||
pub tp_as_number: *mut PyNumberMethods,
|
||||
pub tp_as_sequence: *mut PySequenceMethods,
|
||||
pub tp_as_mapping: *mut PyMappingMethods,
|
||||
pub tp_hash: Option<::object::hashfunc>,
|
||||
pub tp_call: Option<::object::ternaryfunc>,
|
||||
pub tp_str: Option<::object::reprfunc>,
|
||||
pub tp_getattro: Option<::object::getattrofunc>,
|
||||
pub tp_setattro: Option<::object::setattrofunc>,
|
||||
pub tp_hash: Option<object::hashfunc>,
|
||||
pub tp_call: Option<object::ternaryfunc>,
|
||||
pub tp_str: Option<object::reprfunc>,
|
||||
pub tp_getattro: Option<object::getattrofunc>,
|
||||
pub tp_setattro: Option<object::setattrofunc>,
|
||||
pub tp_as_buffer: *mut PyBufferProcs,
|
||||
pub tp_flags: c_ulong,
|
||||
pub tp_doc: *const c_char,
|
||||
pub tp_traverse: Option<::object::traverseproc>,
|
||||
pub tp_clear: Option<::object::inquiry>,
|
||||
pub tp_richcompare: Option<::object::richcmpfunc>,
|
||||
pub tp_traverse: Option<object::traverseproc>,
|
||||
pub tp_clear: Option<object::inquiry>,
|
||||
pub tp_richcompare: Option<object::richcmpfunc>,
|
||||
pub tp_weaklistoffset: Py_ssize_t,
|
||||
pub tp_iter: Option<::object::getiterfunc>,
|
||||
pub tp_iternext: Option<::object::iternextfunc>,
|
||||
pub tp_methods: *mut ::methodobject::PyMethodDef,
|
||||
pub tp_members: *mut ::structmember::PyMemberDef,
|
||||
pub tp_getset: *mut ::descrobject::PyGetSetDef,
|
||||
pub tp_iter: Option<object::getiterfunc>,
|
||||
pub tp_iternext: Option<object::iternextfunc>,
|
||||
pub tp_methods: *mut ffi::methodobject::PyMethodDef,
|
||||
pub tp_members: *mut ffi::structmember::PyMemberDef,
|
||||
pub tp_getset: *mut ffi::descrobject::PyGetSetDef,
|
||||
pub tp_base: *mut PyTypeObject,
|
||||
pub tp_dict: *mut ::object::PyObject,
|
||||
pub tp_descr_get: Option<::object::descrgetfunc>,
|
||||
pub tp_descr_set: Option<::object::descrsetfunc>,
|
||||
pub tp_dict: *mut ffi::object::PyObject,
|
||||
pub tp_descr_get: Option<ffi::object::descrgetfunc>,
|
||||
pub tp_descr_set: Option<ffi::object::descrsetfunc>,
|
||||
pub tp_dictoffset: Py_ssize_t,
|
||||
pub tp_init: Option<::object::initproc>,
|
||||
pub tp_alloc: Option<::object::allocfunc>,
|
||||
pub tp_new: Option<::object::newfunc>,
|
||||
pub tp_free: Option<::object::freefunc>,
|
||||
pub tp_is_gc: Option<::object::inquiry>,
|
||||
pub tp_bases: *mut ::object::PyObject,
|
||||
pub tp_mro: *mut ::object::PyObject,
|
||||
pub tp_cache: *mut ::object::PyObject,
|
||||
pub tp_subclasses: *mut ::object::PyObject,
|
||||
pub tp_weaklist: *mut ::object::PyObject,
|
||||
pub tp_del: Option<::object::destructor>,
|
||||
pub tp_init: Option<ffi::object::initproc>,
|
||||
pub tp_alloc: Option<ffi::object::allocfunc>,
|
||||
pub tp_new: Option<ffi::object::newfunc>,
|
||||
pub tp_free: Option<ffi::object::freefunc>,
|
||||
pub tp_is_gc: Option<ffi::object::inquiry>,
|
||||
pub tp_bases: *mut ffi::object::PyObject,
|
||||
pub tp_mro: *mut ffi::object::PyObject,
|
||||
pub tp_cache: *mut ffi::object::PyObject,
|
||||
pub tp_subclasses: *mut ffi::object::PyObject,
|
||||
pub tp_weaklist: *mut ffi::object::PyObject,
|
||||
pub tp_del: Option<ffi::object::destructor>,
|
||||
pub tp_version_tag: c_uint,
|
||||
#[cfg(Py_3_4)]
|
||||
pub tp_finalize: Option<::object::destructor>,
|
||||
pub tp_finalize: Option<ffi::object::destructor>,
|
||||
#[cfg(py_sys_config="COUNT_ALLOCS")]
|
||||
pub tp_allocs: Py_ssize_t,
|
||||
#[cfg(py_sys_config="COUNT_ALLOCS")]
|
||||
|
@ -506,8 +507,8 @@ mod typeobject {
|
|||
($tp_as_async:ident, $($tail:tt)*) => {
|
||||
as_expr! {
|
||||
PyTypeObject {
|
||||
ob_base: ::object::PyVarObject {
|
||||
ob_base: ::object::PyObject_HEAD_INIT,
|
||||
ob_base: ffi::object::PyVarObject {
|
||||
ob_base: ffi::object::PyObject_HEAD_INIT,
|
||||
ob_size: 0
|
||||
},
|
||||
tp_name: 0 as *const c_char,
|
||||
|
@ -528,7 +529,7 @@ mod typeobject {
|
|||
tp_getattro: None,
|
||||
tp_setattro: None,
|
||||
tp_as_buffer: 0 as *mut PyBufferProcs,
|
||||
tp_flags: ::object::Py_TPFLAGS_DEFAULT,
|
||||
tp_flags: ffi::object::Py_TPFLAGS_DEFAULT,
|
||||
tp_doc: 0 as *const c_char,
|
||||
tp_traverse: None,
|
||||
tp_clear: None,
|
||||
|
@ -536,11 +537,11 @@ mod typeobject {
|
|||
tp_weaklistoffset: 0,
|
||||
tp_iter: None,
|
||||
tp_iternext: None,
|
||||
tp_methods: 0 as *mut ::methodobject::PyMethodDef,
|
||||
tp_members: 0 as *mut ::structmember::PyMemberDef,
|
||||
tp_getset: 0 as *mut ::descrobject::PyGetSetDef,
|
||||
tp_methods: 0 as *mut ffi::methodobject::PyMethodDef,
|
||||
tp_members: 0 as *mut ffi::structmember::PyMemberDef,
|
||||
tp_getset: 0 as *mut ffi::descrobject::PyGetSetDef,
|
||||
tp_base: 0 as *mut PyTypeObject,
|
||||
tp_dict: 0 as *mut ::object::PyObject,
|
||||
tp_dict: 0 as *mut ffi::object::PyObject,
|
||||
tp_descr_get: None,
|
||||
tp_descr_set: None,
|
||||
tp_dictoffset: 0,
|
||||
|
@ -549,11 +550,11 @@ mod typeobject {
|
|||
tp_new: None,
|
||||
tp_free: None,
|
||||
tp_is_gc: None,
|
||||
tp_bases: 0 as *mut ::object::PyObject,
|
||||
tp_mro: 0 as *mut ::object::PyObject,
|
||||
tp_cache: 0 as *mut ::object::PyObject,
|
||||
tp_subclasses: 0 as *mut ::object::PyObject,
|
||||
tp_weaklist: 0 as *mut ::object::PyObject,
|
||||
tp_bases: 0 as *mut ffi::object::PyObject,
|
||||
tp_mro: 0 as *mut ffi::object::PyObject,
|
||||
tp_cache: 0 as *mut ffi::object::PyObject,
|
||||
tp_subclasses: 0 as *mut ffi::object::PyObject,
|
||||
tp_weaklist: 0 as *mut ffi::object::PyObject,
|
||||
tp_del: None,
|
||||
tp_version_tag: 0,
|
||||
$($tail)*
|
||||
|
@ -610,23 +611,23 @@ mod typeobject {
|
|||
pub as_mapping: PyMappingMethods,
|
||||
pub as_sequence: PySequenceMethods,
|
||||
pub as_buffer: PyBufferProcs,
|
||||
pub ht_name: *mut ::object::PyObject,
|
||||
pub ht_slots: *mut ::object::PyObject,
|
||||
pub ht_qualname: *mut ::object::PyObject,
|
||||
pub ht_name: *mut ffi::object::PyObject,
|
||||
pub ht_slots: *mut ffi::object::PyObject,
|
||||
pub ht_qualname: *mut ffi::object::PyObject,
|
||||
pub ht_cached_keys: *mut c_void,
|
||||
}
|
||||
impl Clone for PyHeapTypeObject {
|
||||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyHeapTypeObject {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut ::structmember::PyMemberDef {
|
||||
pub unsafe fn PyHeapType_GET_MEMBERS(etype: *mut PyHeapTypeObject) -> *mut ffi::structmember::PyMemberDef {
|
||||
(etype as *mut c_char).offset(
|
||||
(*::object::Py_TYPE(etype as *mut ::object::PyObject)).tp_basicsize as isize
|
||||
) as *mut ::structmember::PyMemberDef
|
||||
(*ffi::object::Py_TYPE(etype as *mut ffi::object::PyObject)).tp_basicsize as isize
|
||||
) as *mut ffi::structmember::PyMemberDef
|
||||
}
|
||||
}
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
|
@ -642,7 +643,7 @@ impl Clone for PyType_Slot {
|
|||
fn clone(&self) -> PyType_Slot { *self }
|
||||
}
|
||||
impl Default for PyType_Slot {
|
||||
fn default() -> PyType_Slot { unsafe { ::core::mem::zeroed() } }
|
||||
fn default() -> PyType_Slot { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
|
@ -658,7 +659,7 @@ impl Clone for PyType_Spec {
|
|||
fn clone(&self) -> PyType_Spec { *self }
|
||||
}
|
||||
impl Default for PyType_Spec {
|
||||
fn default() -> PyType_Spec { unsafe { ::core::mem::zeroed() } }
|
||||
fn default() -> PyType_Spec { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
|
@ -1,7 +1,7 @@
|
|||
use libc::{c_void, c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use core::ptr;
|
||||
use object::*;
|
||||
use std::ptr;
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn PyObject_DelAttrString(o: *mut PyObject, attr_name: *const c_char) -> c_int {
|
||||
|
@ -115,7 +115,7 @@ pub unsafe fn PyObject_CheckBuffer(o: *mut PyObject) -> c_int {
|
|||
#[inline]
|
||||
pub unsafe fn PyIter_Check(o: *mut PyObject) -> c_int {
|
||||
(match (*(*o).ob_type).tp_iternext {
|
||||
Some(tp_iternext) => tp_iternext as *const c_void != ::object::_PyObject_NextNotImplemented as *const c_void,
|
||||
Some(tp_iternext) => tp_iternext as *const c_void != ::ffi::object::_PyObject_NextNotImplemented as *const c_void,
|
||||
None => false
|
||||
}) as c_int
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use libc::{c_void, c_int, size_t};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use libc::size_t;
|
||||
use std::os::raw::{c_void, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyObject_Malloc(size: size_t) -> *mut c_void;
|
||||
|
@ -41,7 +42,7 @@ impl Clone for PyObjectArenaAllocator {
|
|||
}
|
||||
#[cfg(all(not(Py_LIMITED_API), Py_3_4))]
|
||||
impl Default for PyObjectArenaAllocator {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
#[cfg(all(not(Py_LIMITED_API), Py_3_4))]
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
|
@ -1,5 +1,5 @@
|
|||
// This header is new in Python 3.6
|
||||
use object::PyObject;
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyOS_FSPath(path: *mut PyObject) -> *mut PyObject;
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_void, c_char, c_int};
|
||||
use object::*;
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyCapsule_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyErr_SetNone(arg1: *mut PyObject) -> ();
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_void, c_char, c_int};
|
||||
use pyport::{Py_ssize_t, Py_hash_t};
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::pyport::{Py_ssize_t, Py_hash_t};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
||||
|
@ -15,7 +15,7 @@ impl Clone for PyHash_FuncDef {
|
|||
#[inline] fn clone(&self) -> Self { *self }
|
||||
}
|
||||
impl Default for PyHash_FuncDef {
|
||||
#[inline] fn default() -> Self { unsafe { ::core::mem::zeroed() } }
|
||||
#[inline] fn default() -> Self { unsafe { ::std::mem::zeroed() } }
|
||||
}
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
|
@ -6,6 +6,5 @@ pub type Py_ssize_t = ::libc::ssize_t;
|
|||
pub type Py_hash_t = Py_ssize_t;
|
||||
pub type Py_uhash_t = ::libc::size_t;
|
||||
|
||||
pub const PY_SSIZE_T_MIN : Py_ssize_t = ::core::isize::MIN as Py_ssize_t;
|
||||
pub const PY_SSIZE_T_MAX : Py_ssize_t = ::core::isize::MAX as Py_ssize_t;
|
||||
|
||||
pub const PY_SSIZE_T_MIN : Py_ssize_t = ::std::isize::MIN as Py_ssize_t;
|
||||
pub const PY_SSIZE_T_MAX : Py_ssize_t = ::std::isize::MAX as Py_ssize_t;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_int, c_long};
|
||||
use object::PyObject;
|
||||
use moduleobject::PyModuleDef;
|
||||
use std::os::raw::{c_int, c_long};
|
||||
use ffi::object::PyObject;
|
||||
use ffi::moduleobject::PyModuleDef;
|
||||
|
||||
#[cfg(Py_3_6)]
|
||||
pub const MAX_CO_EXTRA_USERS: c_int = 255;
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int, c_double};
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int, c_double};
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyOS_string_to_double(str: *const c_char,
|
|
@ -1,9 +1,10 @@
|
|||
use libc::{c_char, c_int, wchar_t, FILE};
|
||||
use core::ptr;
|
||||
use object::*;
|
||||
use pystate::PyThreadState;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use std::ptr;
|
||||
use libc::{wchar_t, FILE};
|
||||
use ffi::object::*;
|
||||
use ffi::pystate::PyThreadState;
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
use pyarena::PyArena;
|
||||
use ffi::pyarena::PyArena;
|
||||
|
||||
// TODO: PyCF_MASK etc. constants
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
use libc::c_int;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PyRange_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::c_int;
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub static mut PySet_Type: PyTypeObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::c_int;
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
static mut _Py_EllipsisObject: PyObject;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::{PyObject, PyTypeObject};
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::{PyObject, PyTypeObject};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy)]
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int, wchar_t};
|
||||
use object::PyObject;
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PySys_GetObject(arg1: *const c_char) -> *mut PyObject;
|
|
@ -1,8 +1,8 @@
|
|||
use libc::c_int;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::object::*;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyTraceBack_Here(arg1: *mut ::PyFrameObject) -> c_int;
|
||||
pub fn PyTraceBack_Here(arg1: *mut ::ffi::PyFrameObject) -> c_int;
|
||||
pub fn PyTraceBack_Print(arg1: *mut PyObject, arg2: *mut PyObject)
|
||||
-> c_int;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
use libc::c_int;
|
||||
use pyport::Py_ssize_t;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(not(Py_LIMITED_API))]
|
|
@ -1,6 +1,7 @@
|
|||
use libc::{c_void, c_char, c_int, wchar_t};
|
||||
use object::*;
|
||||
use pyport::Py_ssize_t;
|
||||
use libc::wchar_t;
|
||||
use std::os::raw::{c_void, c_char, c_int};
|
||||
use ffi::object::*;
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
|
||||
#[cfg(not(Py_LIMITED_API))]
|
||||
pub type Py_UNICODE = wchar_t;
|
|
@ -1,6 +1,6 @@
|
|||
use libc::{c_char, c_int};
|
||||
use pyport::Py_ssize_t;
|
||||
use object::PyObject;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
use ffi::pyport::Py_ssize_t;
|
||||
use ffi::object::PyObject;
|
||||
|
||||
#[cfg_attr(windows, link(name="pythonXY"))] extern "C" {
|
||||
pub fn PyErr_WarnEx(category: *mut PyObject,
|
|
@ -1,5 +1,5 @@
|
|||
use libc::c_int;
|
||||
use object::*;
|
||||
use std::os::raw::c_int;
|
||||
use ffi::object::*;
|
||||
|
||||
pub enum PyWeakReference {}
|
||||
|
71
src/lib.rs
71
src/lib.rs
|
@ -80,12 +80,7 @@
|
|||
|
||||
extern crate libc;
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
extern crate python27_sys as ffi;
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
extern crate python3_sys as ffi;
|
||||
|
||||
pub mod ffi;
|
||||
pub use ffi::Py_ssize_t;
|
||||
pub use err::{PyErr, PyResult};
|
||||
pub use objects::*;
|
||||
|
@ -95,11 +90,6 @@ pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject};
|
|||
pub use py_class::{CompareOp};
|
||||
pub use objectprotocol::{ObjectProtocol};
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type Py_hash_t = libc::c_long;
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type Py_hash_t = ffi::Py_hash_t;
|
||||
|
||||
|
@ -193,7 +183,7 @@ pub mod _detail {
|
|||
pub use ::ffi::*;
|
||||
}
|
||||
pub mod libc {
|
||||
pub use ::libc::{c_char, c_void, c_int};
|
||||
pub use std::os::raw::{c_char, c_void, c_int};
|
||||
}
|
||||
pub use err::{from_owned_ptr_or_panic, result_from_owned_ptr};
|
||||
pub use function::{handle_callback, py_fn_impl, AbortOnDrop,
|
||||
|
@ -256,66 +246,16 @@ pub mod _detail {
|
|||
/// ```
|
||||
///
|
||||
#[macro_export]
|
||||
#[cfg(feature="python27-sys")]
|
||||
macro_rules! py_module_initializer {
|
||||
($name: ident, $py2: ident, $py3: ident, |$py_id: ident, $m_id: ident| $body: expr) => {
|
||||
($name: ident, $py3: ident, |$py_id: ident, $m_id: ident| $body: expr) => {
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe extern "C" fn $py2() {
|
||||
pub unsafe extern "C" fn $py3() -> *mut $crate::ffi::PyObject {
|
||||
// Nest init function so that $body isn't in unsafe context
|
||||
fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
|
||||
$body
|
||||
}
|
||||
let name = concat!(stringify!($name), "\0").as_ptr() as *const _;
|
||||
$crate::py_module_initializer_impl(name, init)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub unsafe fn py_module_initializer_impl(
|
||||
name: *const libc::c_char,
|
||||
init: fn(Python, &PyModule) -> PyResult<()>
|
||||
) {
|
||||
let guard = function::AbortOnDrop("py_module_initializer");
|
||||
let py = Python::assume_gil_acquired();
|
||||
ffi::PyEval_InitThreads();
|
||||
let module = ffi::Py_InitModule(name, ptr::null_mut());
|
||||
if module.is_null() {
|
||||
mem::forget(guard);
|
||||
return;
|
||||
}
|
||||
|
||||
let module = match PyObject::from_borrowed_ptr(py, module).cast_into::<PyModule>(py) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
PyErr::from(e).restore(py);
|
||||
mem::forget(guard);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let ret = match init(py, &module) {
|
||||
Ok(()) => (),
|
||||
Err(e) => e.restore(py)
|
||||
};
|
||||
mem::forget(guard);
|
||||
ret
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[cfg(feature="python3-sys")]
|
||||
macro_rules! py_module_initializer {
|
||||
($name: ident, $py2: ident, $py3: ident, |$py_id: ident, $m_id: ident| $body: expr) => {
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe extern "C" fn $py3() -> *mut $crate::_detail::ffi::PyObject {
|
||||
// Nest init function so that $body isn't in unsafe context
|
||||
fn init($py_id: $crate::Python, $m_id: &$crate::PyModule) -> $crate::PyResult<()> {
|
||||
$body
|
||||
}
|
||||
static mut MODULE_DEF: $crate::_detail::ffi::PyModuleDef = $crate::_detail::ffi::PyModuleDef_INIT;
|
||||
static mut MODULE_DEF: $crate::ffi::PyModuleDef = $crate::_detail::ffi::PyModuleDef_INIT;
|
||||
// We can't convert &'static str to *const c_char within a static initializer,
|
||||
// so we'll do it here in the module initialization:
|
||||
MODULE_DEF.m_name = concat!(stringify!($name), "\0").as_ptr() as *const _;
|
||||
|
@ -325,7 +265,6 @@ macro_rules! py_module_initializer {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub unsafe fn py_module_initializer_impl(
|
||||
def: *mut ffi::PyModuleDef,
|
||||
init: fn(Python, &PyModule) -> PyResult<()>
|
||||
|
|
|
@ -85,21 +85,6 @@ pub trait ObjectProtocol : PythonObject {
|
|||
/// raise TypeError("ObjectProtocol::compare(): All comparisons returned false")
|
||||
/// ```
|
||||
fn compare<O>(&self, py: Python, other: O) -> PyResult<Ordering> where O: ToPyObject {
|
||||
#[cfg(feature="python27-sys")]
|
||||
unsafe fn do_compare(py: Python, a: *mut ffi::PyObject, b: *mut ffi::PyObject) -> PyResult<Ordering> {
|
||||
let mut result = -1;
|
||||
try!(err::error_on_minusone(py,
|
||||
ffi::PyObject_Cmp(a, b, &mut result)));
|
||||
Ok(if result < 0 {
|
||||
Ordering::Less
|
||||
} else if result > 0 {
|
||||
Ordering::Greater
|
||||
} else {
|
||||
Ordering::Equal
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
unsafe fn do_compare(py: Python, a: *mut ffi::PyObject, b: *mut ffi::PyObject) -> PyResult<Ordering> {
|
||||
let result = ffi::PyObject_RichCompareBool(a, b, ffi::Py_EQ);
|
||||
if result == 1 {
|
||||
|
@ -160,16 +145,6 @@ pub trait ObjectProtocol : PythonObject {
|
|||
}
|
||||
}
|
||||
|
||||
/// Compute the unicode string representation of self.
|
||||
/// This is equivalent to the Python expression 'unistr(self)'.
|
||||
#[inline]
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn unistr(&self, py: Python) -> PyResult<::objects::PyUnicode> {
|
||||
unsafe {
|
||||
err::result_cast_from_owned_ptr(py, ffi::PyObject_Unicode(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines whether this object is callable.
|
||||
#[inline]
|
||||
fn is_callable(&self, _py: Python) -> bool {
|
||||
|
|
|
@ -1,20 +1,4 @@
|
|||
// Copyright (c) 2017 Nikolay Kim
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
use std::{mem, str, char, ptr};
|
||||
|
|
|
@ -73,8 +73,6 @@ macro_rules! exc_type(
|
|||
|
||||
exc_type!(BaseException, PyExc_BaseException);
|
||||
exc_type!(Exception, PyExc_Exception);
|
||||
#[cfg(feature="python27-sys")]
|
||||
exc_type!(StandardError, PyExc_StandardError);
|
||||
exc_type!(LookupError, PyExc_LookupError);
|
||||
exc_type!(AssertionError, PyExc_AssertionError);
|
||||
exc_type!(AttributeError, PyExc_AttributeError);
|
||||
|
@ -104,36 +102,20 @@ exc_type!(WindowsError, PyExc_WindowsError);
|
|||
exc_type!(ZeroDivisionError, PyExc_ZeroDivisionError);
|
||||
|
||||
exc_type!(BufferError, PyExc_BufferError);
|
||||
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(BlockingIOError, PyExc_BlockingIOError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(BrokenPipeError, PyExc_BrokenPipeError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ChildProcessError, PyExc_ChildProcessError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ConnectionError, PyExc_ConnectionError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ConnectionAbortedError, PyExc_ConnectionAbortedError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ConnectionRefusedError, PyExc_ConnectionRefusedError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ConnectionResetError, PyExc_ConnectionResetError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(FileExistsError, PyExc_FileExistsError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(FileNotFoundError, PyExc_FileNotFoundError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(InterruptedError, PyExc_InterruptedError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(IsADirectoryError, PyExc_IsADirectoryError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(NotADirectoryError, PyExc_NotADirectoryError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(PermissionError, PyExc_PermissionError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(ProcessLookupError, PyExc_ProcessLookupError);
|
||||
#[cfg(Py_3_4)]
|
||||
exc_type!(TimeoutError, PyExc_TimeoutError);
|
||||
|
||||
exc_type!(UnicodeDecodeError, PyExc_UnicodeDecodeError);
|
||||
|
|
|
@ -19,23 +19,13 @@
|
|||
pub use self::object::PyObject;
|
||||
pub use self::typeobject::PyType;
|
||||
pub use self::module::PyModule;
|
||||
|
||||
pub use self::string::{PyBytes, PyString, PyStringData};
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub use self::string::PyUnicode;
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub use self::string::PyString as PyUnicode;
|
||||
|
||||
pub use self::iterator::PyIterator;
|
||||
pub use self::boolobject::PyBool;
|
||||
pub use self::bytearray::PyByteArray;
|
||||
pub use self::tuple::{PyTuple, NoArgs, ToPyTuple};
|
||||
pub use self::dict::PyDict;
|
||||
pub use self::list::PyList;
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub use self::num::PyInt;
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub use self::num::PyLong as PyInt;
|
||||
pub use self::num::{PyLong, PyFloat};
|
||||
pub use self::sequence::PySequence;
|
||||
pub use self::slice::PySlice;
|
||||
|
@ -137,9 +127,5 @@ mod num;
|
|||
mod sequence;
|
||||
mod slice;
|
||||
pub mod exc;
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub mod oldstyle;
|
||||
|
||||
mod tests;
|
||||
|
||||
|
|
|
@ -29,24 +29,6 @@ use conversion::{ToPyObject, FromPyObject};
|
|||
|
||||
/// Represents a Python `int` object.
|
||||
///
|
||||
/// Note that in Python 2.x, `int` and `long` are different types.
|
||||
/// When rust-cpython is compiled for Python 3.x,
|
||||
/// `PyInt` and `PyLong` are aliases for the same type, which
|
||||
/// corresponds to a Python `int`.
|
||||
///
|
||||
/// You can usually avoid directly working with this type
|
||||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub struct PyInt(PyObject);
|
||||
#[cfg(feature="python27-sys")]
|
||||
pyobject_newtype!(PyInt, PyInt_Check, PyInt_Type);
|
||||
|
||||
/// In Python 2.x, represents a Python `long` object.
|
||||
/// In Python 3.x, represents a Python `int` object.
|
||||
/// Both `PyInt` and `PyLong` refer to the same type on Python 3.x.
|
||||
///
|
||||
/// You can usually avoid directly working with this type
|
||||
/// by using [ToPyObject](trait.ToPyObject.html)
|
||||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
|
@ -63,30 +45,6 @@ pyobject_newtype!(PyLong, PyLong_Check, PyLong_Type);
|
|||
pub struct PyFloat(PyObject);
|
||||
pyobject_newtype!(PyFloat, PyFloat_Check, PyFloat_Type);
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
impl PyInt {
|
||||
/// Creates a new Python 2.7 `int` object.
|
||||
///
|
||||
/// Note: you might want to call `val.to_py_object(py)` instead
|
||||
/// to avoid truncation if the value does not fit into a `c_long`,
|
||||
/// and to make your code compatible with Python 3.x.
|
||||
pub fn new(py: Python, val: c_long) -> PyInt {
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py, ffi::PyInt_FromLong(val))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the value of this integer.
|
||||
///
|
||||
/// Warning: `PyInt::value()` is only supported for Python 2.7 `int` objects,
|
||||
/// but not for `long` objects.
|
||||
/// In almost all cases, you can avoid the distinction between these types
|
||||
/// by simply calling `obj.extract::<i32>(py)`.
|
||||
pub fn value(&self, _py: Python) -> c_long {
|
||||
unsafe { ffi::PyInt_AS_LONG(self.0.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PyFloat {
|
||||
/// Creates a new Python `float` object.
|
||||
|
@ -104,19 +62,6 @@ impl PyFloat {
|
|||
|
||||
macro_rules! int_fits_c_long(
|
||||
($rust_type:ty) => (
|
||||
#[cfg(feature="python27-sys")]
|
||||
impl ToPyObject for $rust_type {
|
||||
type ObjectType = PyInt;
|
||||
|
||||
fn to_py_object(&self, py: Python) -> PyInt {
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py,
|
||||
ffi::PyInt_FromLong(*self as c_long))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
impl ToPyObject for $rust_type {
|
||||
type ObjectType = PyLong;
|
||||
|
||||
|
@ -177,24 +122,8 @@ fn err_if_invalid_value<'p, T: PartialEq>
|
|||
macro_rules! int_convert_u64_or_i64 (
|
||||
($rust_type:ty, $pylong_from_ll_or_ull:expr, $pylong_as_ull_or_ull:expr) => (
|
||||
impl <'p> ToPyObject for $rust_type {
|
||||
#[cfg(feature="python27-sys")]
|
||||
type ObjectType = PyObject;
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
type ObjectType = PyLong;
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn to_py_object(&self, py: Python) -> PyObject {
|
||||
unsafe {
|
||||
let ptr = match cast::<$rust_type, c_long>(*self) {
|
||||
Some(v) => ffi::PyInt_FromLong(v),
|
||||
None => $pylong_from_ll_or_ull(*self)
|
||||
};
|
||||
err::from_owned_ptr_or_panic(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
fn to_py_object(&self, py: Python) -> PyLong {
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py, $pylong_from_ll_or_ull(*self))
|
||||
|
@ -203,26 +132,6 @@ macro_rules! int_convert_u64_or_i64 (
|
|||
}
|
||||
|
||||
impl <'source> FromPyObject<'source> for $rust_type {
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<$rust_type> {
|
||||
let ptr = obj.as_ptr();
|
||||
|
||||
unsafe {
|
||||
if ffi::PyLong_Check(ptr) != 0 {
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(ptr))
|
||||
} else if ffi::PyInt_Check(ptr) != 0 {
|
||||
match cast::<c_long, $rust_type>(ffi::PyInt_AS_LONG(ptr)) {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(overflow_error(py))
|
||||
}
|
||||
} else {
|
||||
let num = try!(err::result_from_owned_ptr(py, ffi::PyNumber_Long(ptr)));
|
||||
err_if_invalid_value(py, !0, $pylong_as_ull_or_ull(num.as_ptr()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<$rust_type> {
|
||||
let ptr = obj.as_ptr();
|
||||
unsafe {
|
||||
|
|
|
@ -1,20 +1,4 @@
|
|||
// Copyright (c) 2017 Nikolay Kim
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
// software and associated documentation files (the "Software"), to deal in the Software
|
||||
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
// to whom the Software is furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all copies or
|
||||
// substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std::mem;
|
||||
use libc::c_long;
|
||||
|
|
|
@ -28,72 +28,15 @@ use err::{self, PyResult, PyErr};
|
|||
use conversion::{FromPyObject, RefFromPyObject, ToPyObject};
|
||||
|
||||
/// Represents a Python string.
|
||||
/// Corresponds to `basestring` in Python 2, and `str` in Python 3.
|
||||
pub struct PyString(PyObject);
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
pyobject_newtype!(PyString);
|
||||
#[cfg(feature="python3-sys")]
|
||||
pyobject_newtype!(PyString, PyUnicode_Check, PyUnicode_Type);
|
||||
|
||||
/// Represents a Python byte string.
|
||||
/// Corresponds to `str` in Python 2, and `bytes` in Python 3.
|
||||
pub struct PyBytes(PyObject);
|
||||
|
||||
pyobject_newtype!(PyBytes, PyBytes_Check, PyBytes_Type);
|
||||
|
||||
/// Represents a Python unicode string.
|
||||
/// Corresponds to `unicode` in Python 2, and `str` in Python 3.
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub struct PyUnicode(PyObject);
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
pyobject_newtype!(PyUnicode, PyUnicode_Check, PyUnicode_Type);
|
||||
|
||||
/// Represents a Python unicode string.
|
||||
/// Corresponds to `unicode` in Python 2, and `str` in Python 3.
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub use PyString as PyUnicode;
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
impl ::python::PythonObjectWithCheckedDowncast for PyString {
|
||||
#[inline]
|
||||
fn downcast_from<'p>(py: Python<'p>, obj: PyObject) -> Result<PyString, PythonObjectDowncastError<'p>> {
|
||||
if is_base_string(&obj) {
|
||||
Ok(PyString(obj))
|
||||
} else {
|
||||
Err(PythonObjectDowncastError(py))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn downcast_borrow_from<'a, 'p>(py: Python<'p>, obj: &'a PyObject) -> Result<&'a PyString, PythonObjectDowncastError<'p>> {
|
||||
unsafe {
|
||||
if is_base_string(obj) {
|
||||
Ok(::std::mem::transmute(obj))
|
||||
} else {
|
||||
Err(::python::PythonObjectDowncastError(py))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
#[inline]
|
||||
fn is_base_string(obj: &PyObject) -> bool {
|
||||
unsafe {
|
||||
ffi::PyType_FastSubclass(ffi::Py_TYPE(obj.as_ptr()),
|
||||
ffi::Py_TPFLAGS_STRING_SUBCLASS | ffi::Py_TPFLAGS_UNICODE_SUBCLASS) != 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
impl ::python::PythonObjectWithTypeObject for PyString {
|
||||
#[inline]
|
||||
fn type_object(py: Python) -> super::PyType {
|
||||
unsafe { ::objects::typeobject::PyType::from_type_ptr(py, &mut ::ffi::PyBaseString_Type) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Enum of possible Python string representations.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
@ -211,24 +154,12 @@ impl PyString {
|
|||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(py: Python, s: &str) -> PyString {
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn new_impl(py: Python, s: &str) -> PyString {
|
||||
if s.is_ascii() {
|
||||
PyBytes::new(py, s.as_bytes()).into_basestring()
|
||||
} else {
|
||||
PyUnicode::new(py, s).into_basestring()
|
||||
}
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py,
|
||||
ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
}
|
||||
#[cfg(feature="python3-sys")]
|
||||
fn new_impl(py: Python, s: &str) -> PyString {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py,
|
||||
ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
new_impl(py, s)
|
||||
}
|
||||
|
||||
pub fn from_object(py: Python, src: &PyObject, encoding: &str, errors: &str) -> PyResult<PyString> {
|
||||
|
@ -240,27 +171,7 @@ impl PyString {
|
|||
}
|
||||
|
||||
/// Gets the python string data in its underlying representation.
|
||||
///
|
||||
/// For Python 2 byte strings, this function always returns `PyStringData::Utf8`,
|
||||
/// even if the bytes are not valid UTF-8.
|
||||
/// For unicode strings, returns the underlying representation used by Python.
|
||||
pub fn data(&self, py: Python) -> PyStringData {
|
||||
self.data_impl(py)
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn data_impl(&self, py: Python) -> PyStringData {
|
||||
if let Ok(bytes) = self.0.cast_as::<PyBytes>(py) {
|
||||
PyStringData::Utf8(bytes.data(py))
|
||||
} else if let Ok(unicode) = self.0.cast_as::<PyUnicode>(py) {
|
||||
unicode.data(py)
|
||||
} else {
|
||||
panic!("PyString is neither `str` nor `unicode`")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
fn data_impl(&self, py: Python) -> PyStringData {
|
||||
// TODO: return the original representation instead
|
||||
// of forcing the UTF-8 representation to be created.
|
||||
unsafe {
|
||||
|
@ -276,22 +187,15 @@ impl PyString {
|
|||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
///
|
||||
/// On Python 2.7, if the `PyString` refers to a byte string,
|
||||
/// it will be decoded using UTF-8.
|
||||
///
|
||||
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates, or a Python 2.7 byte string that is
|
||||
/// not valid UTF-8).
|
||||
/// (containing unpaired surrogates).
|
||||
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
|
||||
self.data(py).to_string(py)
|
||||
}
|
||||
|
||||
/// Convert the `PyString` into a Rust string.
|
||||
///
|
||||
/// On Python 2.7, if the `PyString` refers to a byte string,
|
||||
/// it will be decoded using UTF-8.
|
||||
///
|
||||
/// Unpaired surrogates and (on Python 2.7) invalid UTF-8 sequences are
|
||||
/// Unpaired surrogates invalid UTF-8 sequences are
|
||||
/// replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self, py: Python) -> Cow<str> {
|
||||
self.data(py).to_string_lossy()
|
||||
|
@ -320,77 +224,6 @@ impl PyBytes {
|
|||
std::slice::from_raw_parts(buffer, length)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyBytes` to `PyString`.
|
||||
/// This method is only available on Python 2.
|
||||
#[cfg(feature="python27-sys")]
|
||||
#[inline]
|
||||
pub fn as_basestring(&self) -> &PyString {
|
||||
unsafe { self.0.unchecked_cast_as() }
|
||||
}
|
||||
|
||||
/// Converts from `PyBytes` to `PyString`.
|
||||
/// This method is only available on Python 2.
|
||||
#[cfg(feature="python27-sys")]
|
||||
#[inline]
|
||||
pub fn into_basestring(self) -> PyString {
|
||||
unsafe { self.0.unchecked_cast_into() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
impl PyUnicode {
|
||||
/// Creates a new Python unicode string object.
|
||||
///
|
||||
/// Panics if out of memory.
|
||||
pub fn new(py: Python, s: &str) -> PyUnicode {
|
||||
let ptr = s.as_ptr() as *const c_char;
|
||||
let len = s.len() as ffi::Py_ssize_t;
|
||||
unsafe {
|
||||
err::cast_from_owned_ptr_or_panic(py,
|
||||
ffi::PyUnicode_FromStringAndSize(ptr, len))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts from `PyUnicode` to `PyString`.
|
||||
/// This method is only available on Python 2.
|
||||
/// (note: on Python 3, `PyUnicode` is a type alias for `PyString`)
|
||||
#[inline]
|
||||
pub fn as_basestring(&self) -> &PyString {
|
||||
unsafe { self.0.unchecked_cast_as() }
|
||||
}
|
||||
|
||||
/// Converts from `PyUnicode` to `PyString`.
|
||||
/// This method is only available on Python 2.
|
||||
/// (note: on Python 3, `PyUnicode` is a type alias for `PyString`)
|
||||
#[inline]
|
||||
pub fn into_basestring(self) -> PyString {
|
||||
unsafe { self.0.unchecked_cast_into() }
|
||||
}
|
||||
|
||||
/// Gets the python string data in its underlying representation.
|
||||
pub fn data(&self, _py: Python) -> PyStringData {
|
||||
unsafe {
|
||||
let buffer = ffi::PyUnicode_AS_UNICODE(self.as_ptr());
|
||||
let length = ffi::PyUnicode_GET_SIZE(self.as_ptr()) as usize;
|
||||
std::slice::from_raw_parts(buffer, length).into()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the `PyUnicode` into a Rust string.
|
||||
///
|
||||
/// Returns a `UnicodeDecodeError` if the input is not valid unicode
|
||||
/// (containing unpaired surrogates).
|
||||
pub fn to_string(&self, py: Python) -> PyResult<Cow<str>> {
|
||||
self.data(py).to_string(py)
|
||||
}
|
||||
|
||||
/// Convert the `PyUnicode` into a Rust string.
|
||||
///
|
||||
/// Unpaired surrogates are replaced with U+FFFD REPLACEMENT CHARACTER.
|
||||
pub fn to_string_lossy(&self, py: Python) -> Cow<str> {
|
||||
self.data(py).to_string_lossy()
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts Rust `str` to Python object.
|
||||
|
@ -428,7 +261,6 @@ impl ToPyObject for String {
|
|||
|
||||
/// Allows extracting strings from Python objects.
|
||||
/// Accepts Python `str` and `unicode` objects.
|
||||
/// In Python 2.7, `str` is expected to be UTF-8 encoded.
|
||||
impl <'source> FromPyObject<'source> for Cow<'source, str> {
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
try!(obj.cast_as::<PyString>(py)).to_string(py)
|
||||
|
@ -437,7 +269,6 @@ impl <'source> FromPyObject<'source> for Cow<'source, str> {
|
|||
|
||||
/// Allows extracting strings from Python objects.
|
||||
/// Accepts Python `str` and `unicode` objects.
|
||||
/// In Python 2.7, `str` is expected to be UTF-8 encoded.
|
||||
impl <'source> FromPyObject<'source> for String {
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
obj.extract::<Cow<str>>(py).map(Cow::into_owned)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use {Python, PyDict, ToPyObject, PyInt};
|
||||
use {Python, PyDict, ToPyObject, PyLong};
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
|
||||
// TODO: move these tests into the dict module
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use libc;
|
||||
use std::os::raw::{c_void, c_int};
|
||||
use ffi;
|
||||
use std::mem;
|
||||
use python::{Python, PythonObject, PyDrop, ToPythonPointer};
|
||||
|
@ -25,12 +25,12 @@ use function::AbortOnDrop;
|
|||
|
||||
// TODO: what's the semantics of the traverse return code?
|
||||
// If it's just a normal python exception, we might want to use PyErr instead.
|
||||
pub struct TraverseError(libc::c_int);
|
||||
pub struct TraverseError(c_int);
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct VisitProc<'a> {
|
||||
visit: ffi::visitproc,
|
||||
arg: *mut libc::c_void,
|
||||
arg: *mut c_void,
|
||||
/// VisitProc contains a Python instance to ensure that
|
||||
/// 1) it is cannot be moved out of the traverse() call
|
||||
/// 2) it cannot be sent to other threads
|
||||
|
@ -88,9 +88,8 @@ pub unsafe fn tp_traverse<C, F>(
|
|||
location: &str,
|
||||
slf: *mut ffi::PyObject,
|
||||
visit: ffi::visitproc,
|
||||
arg: *mut libc::c_void,
|
||||
callback: F
|
||||
) -> libc::c_int
|
||||
arg: *mut c_void,
|
||||
callback: F) -> c_int
|
||||
where C: PythonObject,
|
||||
F: FnOnce(&C, Python, VisitProc) -> Result<(), TraverseError>
|
||||
{
|
||||
|
@ -127,8 +126,7 @@ macro_rules! py_class_tp_clear {
|
|||
pub unsafe fn tp_clear<C, F>(
|
||||
location: &str,
|
||||
slf: *mut ffi::PyObject,
|
||||
callback: F
|
||||
) -> libc::c_int
|
||||
callback: F) -> c_int
|
||||
where C: PythonObject,
|
||||
F: FnOnce(&C, Python)
|
||||
{
|
||||
|
|
|
@ -17,16 +17,13 @@
|
|||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
mod py_class;
|
||||
#[cfg(feature="python27-sys")]
|
||||
mod py_class_impl2;
|
||||
#[cfg(feature="python3-sys")]
|
||||
mod py_class_impl3;
|
||||
mod py_class_impl;
|
||||
#[doc(hidden)] pub mod slots;
|
||||
#[doc(hidden)] pub mod members;
|
||||
#[doc(hidden)] pub mod properties;
|
||||
pub mod gc;
|
||||
|
||||
use libc;
|
||||
use std::os::raw::c_void;
|
||||
use std::{mem, ptr, cell};
|
||||
use python::{self, Python, PythonObject};
|
||||
use objects::{PyObject, PyType, PyModule};
|
||||
|
@ -139,9 +136,9 @@ impl BaseObject for PyObject {
|
|||
// we have to manually un-do the work of PyType_GenericAlloc:
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
if ffi::PyType_IS_GC(ty) != 0 {
|
||||
ffi::PyObject_GC_Del(obj as *mut libc::c_void);
|
||||
ffi::PyObject_GC_Del(obj as *mut c_void);
|
||||
} else {
|
||||
ffi::PyObject_Free(obj as *mut libc::c_void);
|
||||
ffi::PyObject_Free(obj as *mut c_void);
|
||||
}
|
||||
// For heap types, PyType_GenericAlloc calls INCREF on the type objects,
|
||||
// so we need to call DECREF here:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -72,10 +72,6 @@ macro_rules! py_class_type_object_flags {
|
|||
};
|
||||
}
|
||||
|
||||
#[cfg(feature="python27-sys")]
|
||||
pub const TPFLAGS_DEFAULT : ::libc::c_long = ffi::Py_TPFLAGS_DEFAULT
|
||||
| ffi::Py_TPFLAGS_CHECKTYPES;
|
||||
|
||||
#[cfg(feature="python3-sys")]
|
||||
pub const TPFLAGS_DEFAULT : ::libc::c_ulong = ffi::Py_TPFLAGS_DEFAULT;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ if sys.version_info.major == 3:
|
|||
for i in range(4, sys.version_info.minor+1):
|
||||
cfgs += ['--cfg', 'Py_3_{}'.format(i)]
|
||||
else:
|
||||
sys_lib = 'python27-sys'
|
||||
raise RuntimeError("Unsupported version: %s" % sys.version_info)
|
||||
|
||||
interesting_config_flags = [
|
||||
"Py_USING_UNICODE",
|
||||
|
|
|
@ -390,17 +390,6 @@ fn string_methods() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="python27-sys")]
|
||||
fn python2_string_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let obj = StringMethods::create_instance(py).unwrap();
|
||||
py_assert!(py, obj, "unicode(obj) == u'unicode'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature="python3-sys")]
|
||||
fn python3_string_methods() {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
|
Loading…
Reference in New Issue