mirror of
https://github.com/facebook/sapling.git
synced 2024-12-27 06:52:23 +03:00
cpython-ext: add a PyPath type
Summary: This will be used as an argument to the Rust bindings when using paths. This type is either a PyBytes in Python2 and uses the various encoding function to convert into a String, or a PyUnicode in Python3 with no encoding change. Reviewed By: farnz Differential Revision: D19587890 fbshipit-source-id: 58903426585693193754691fe3c756b9097b35f6
This commit is contained in:
parent
e512c370fd
commit
33ea1763ce
@ -10,6 +10,7 @@ python3 = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.20"
|
||||
encoding = { path = "../encoding" }
|
||||
lazy_static = "1"
|
||||
parking_lot = "0.9"
|
||||
serde = "1"
|
||||
|
@ -10,6 +10,7 @@ mod bytes;
|
||||
mod bytesobject;
|
||||
pub mod error;
|
||||
mod io;
|
||||
mod path;
|
||||
mod pybuf;
|
||||
mod pyset;
|
||||
pub mod ser;
|
||||
@ -23,3 +24,4 @@ pub use crate::pybuf::SimplePyBuf;
|
||||
pub use crate::pyset::{pyset_add, pyset_new};
|
||||
pub use crate::str::Str;
|
||||
pub use bytes::Bytes;
|
||||
pub use path::PyPath;
|
||||
|
101
eden/scm/lib/cpython-ext/src/path.rs
Normal file
101
eden/scm/lib/cpython-ext/src/path.rs
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
#[cfg(feature = "python2")]
|
||||
use anyhow::format_err;
|
||||
use anyhow::Result;
|
||||
use cpython::*;
|
||||
|
||||
#[cfg(feature = "python2")]
|
||||
use encoding::{local_bytes_to_path, path_to_local_bytes};
|
||||
|
||||
#[cfg(feature = "python2")]
|
||||
use crate::ResultPyErrExt;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Default, Hash, Ord)]
|
||||
pub struct PyPath(String);
|
||||
|
||||
impl PyPath {
|
||||
pub fn to_path_buf(&self) -> PathBuf {
|
||||
Path::new(&self.0).to_path_buf()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToPyObject for PyPath {
|
||||
#[cfg(feature = "python3")]
|
||||
type ObjectType = PyUnicode;
|
||||
#[cfg(feature = "python2")]
|
||||
type ObjectType = PyBytes;
|
||||
|
||||
#[inline]
|
||||
fn to_py_object(&self, py: Python) -> Self::ObjectType {
|
||||
#[cfg(feature = "python3")]
|
||||
return self.0.to_py_object(py);
|
||||
|
||||
#[cfg(feature = "python2")]
|
||||
PyBytes::new(py, &path_to_local_bytes(self.0.as_ref()).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source> FromPyObject<'source> for PyPath {
|
||||
fn extract(py: Python, obj: &'source PyObject) -> PyResult<Self> {
|
||||
#[cfg(feature = "python3")]
|
||||
{
|
||||
let s = obj.cast_as::<PyUnicode>(py)?.data(py);
|
||||
Ok(Self(s.to_string(py)?.into()))
|
||||
}
|
||||
|
||||
#[cfg(feature = "python2")]
|
||||
{
|
||||
let s = obj.cast_as::<PyBytes>(py)?.data(py);
|
||||
let path = local_bytes_to_path(s).map_pyerr(py)?;
|
||||
Ok(Self(
|
||||
path.to_str()
|
||||
.ok_or_else(|| format_err!("{} is not a UTF-8 path", path.display()))
|
||||
.map_pyerr(py)?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for PyPath {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(path: PathBuf) -> Result<Self> {
|
||||
path.as_path().try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a Path> for PyPath {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(path: &'a Path) -> Result<Self> {
|
||||
Ok(Self(
|
||||
path.to_str()
|
||||
.ok_or_else(|| format_err!("{} is not a UTF-8 path", path.display()))?
|
||||
.into(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for PyPath {
|
||||
fn from(s: String) -> PyPath {
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Path> for PyPath {
|
||||
fn as_ref(&self) -> &Path {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user