include py3 ffi info into crate

This commit is contained in:
Nikolay Kim 2017-05-12 22:05:00 -07:00
parent 3bb7a64db5
commit 8a295793a0
80 changed files with 752 additions and 3339 deletions

View File

@ -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 = []

View File

@ -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
View File

@ -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 { "" });
}

View File

@ -1,2 +0,0 @@
/target
/Cargo.lock

View File

@ -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 = []

View File

@ -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 { "" });
}

View File

@ -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()));
}
}

View File

@ -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
))

View File

@ -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),

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) -> ();

View File

@ -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)
}

View File

@ -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;

View File

@ -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)]

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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";

View File

@ -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;

View File

@ -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)]

View File

@ -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
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 {}

View File

@ -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;

View File

@ -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 =

View File

@ -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;

View File

@ -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, ...)

View File

@ -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;

View File

@ -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" {

View File

@ -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
}

View File

@ -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" {

View File

@ -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;

View File

@ -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;

View File

@ -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) -> ();

View File

@ -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" {

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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)]

View File

@ -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)]

View File

@ -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;

View File

@ -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;

View File

@ -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))]

View File

@ -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;

View File

@ -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,

View File

@ -1,5 +1,5 @@
use libc::c_int;
use object::*;
use std::os::raw::c_int;
use ffi::object::*;
pub enum PyWeakReference {}

View File

@ -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<()>

View File

@ -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 {

View File

@ -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};

View File

@ -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);

View File

@ -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;

View File

@ -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 {

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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",

View File

@ -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();