Skip to content

Commit eaf19d4

Browse files
authoredJun 17, 2024
Python api improvements (#132)
1 parent 16f6feb commit eaf19d4

File tree

4 files changed

+49
-23
lines changed

4 files changed

+49
-23
lines changed
 

‎python/hdfs_native/__init__.py

+22-6
Original file line numberDiff line numberDiff line change
@@ -88,46 +88,62 @@ def __exit__(self, *_args):
8888

8989
class Client:
9090

91-
def __init__(self, url: str, config: Optional[Dict[str, str]] = None):
91+
def __init__(
92+
self,
93+
url: Optional[str] = None,
94+
config: Optional[Dict[str, str]] = None,
95+
):
9296
self.inner = RawClient(url, config)
9397

9498
def get_file_info(self, path: str) -> "FileStatus":
9599
"""Gets the file status for the file at `path`"""
96100
return self.inner.get_file_info(path)
97101

98-
def list_status(self, path: str, recursive: bool) -> Iterator["FileStatus"]:
102+
def list_status(self, path: str, recursive: bool = False) -> Iterator["FileStatus"]:
99103
"""Gets the status of files rooted at `path`. If `recursive` is true, lists all files recursively."""
100104
return self.inner.list_status(path, recursive)
101105

102106
def read(self, path: str) -> FileReader:
103107
"""Opens a file for reading at `path`"""
104108
return FileReader(self.inner.read(path))
105109

106-
def create(self, path: str, write_options: WriteOptions) -> FileWriter:
110+
def create(
111+
self,
112+
path: str,
113+
write_options: Optional[WriteOptions] = None,
114+
) -> FileWriter:
107115
"""Creates a new file and opens it for writing at `path`"""
116+
if not write_options:
117+
write_options = WriteOptions()
118+
108119
return FileWriter(self.inner.create(path, write_options))
109120

110121
def append(self, path: str) -> FileWriter:
111122
"""Opens an existing file to append to at `path`"""
112123
return FileWriter(self.inner.append(path))
113124

114-
def mkdirs(self, path: str, permission: int, create_parent: bool) -> None:
125+
def mkdirs(
126+
self,
127+
path: str,
128+
permission: int = 0o0755,
129+
create_parent: bool = False,
130+
) -> None:
115131
"""
116132
Creates a directory at `path` with unix permissions `permission`. If `create_parent` is true,
117133
any parent directories that don't exist will also be created. Otherwise this will fail if
118134
all parent directories don't already exist.
119135
"""
120136
return self.inner.mkdirs(path, permission, create_parent)
121137

122-
def rename(self, src: str, dst: str, overwrite: bool) -> None:
138+
def rename(self, src: str, dst: str, overwrite: bool = False) -> None:
123139
"""
124140
Moves a file or directory from `src` to `dst`. If `overwrite` is True, the destination will be
125141
overriden if it already exists, otherwise the operation will fail if the destination
126142
exists.
127143
"""
128144
return self.inner.rename(src, dst, overwrite)
129145

130-
def delete(self, path: str, recursive: bool) -> bool:
146+
def delete(self, path: str, recursive: bool = False) -> bool:
131147
"""
132148
Deletes a file or directory at `path`. If `recursive` is True and the target is a directory,
133149
this will delete all contents underneath the directory. If `recursive` is False and the target

‎python/hdfs_native/_internal.pyi

+5-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ class RawFileWriter:
5454
"""Closes the file and saves the final metadata to the NameNode"""
5555

5656
class RawClient:
57-
def __init__(self, url: str, config: Optional[Dict[str, str]]) -> None: ...
57+
def __init__(
58+
self,
59+
url: Optional[str],
60+
config: Optional[Dict[str, str]],
61+
) -> None: ...
5862
def get_file_info(self, path: str) -> FileStatus: ...
5963
def list_status(self, path: str, recursive: bool) -> Iterator[FileStatus]: ...
6064
def read(self, path: str) -> RawFileReader: ...

‎python/src/lib.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,20 @@ struct RawClient {
206206
impl RawClient {
207207
#[new]
208208
#[pyo3(signature = (url, config))]
209-
pub fn new(url: &str, config: Option<HashMap<String, String>>) -> PyResult<Self> {
209+
pub fn new(url: Option<&str>, config: Option<HashMap<String, String>>) -> PyResult<Self> {
210210
// Initialize logging, ignore errors if this is called multiple times
211211
let _ = env_logger::try_init();
212212

213+
let config = config.unwrap_or_default();
214+
215+
let inner = if let Some(url) = url {
216+
Client::new_with_config(url, config).map_err(PythonHdfsError::from)?
217+
} else {
218+
Client::default_with_config(config).map_err(PythonHdfsError::from)?
219+
};
220+
213221
Ok(RawClient {
214-
inner: Client::new_with_config(url, config.unwrap_or_default())
215-
.map_err(PythonHdfsError::from)?,
222+
inner,
216223
rt: Arc::new(
217224
tokio::runtime::Runtime::new()
218225
.map_err(|err| PyRuntimeError::new_err(err.to_string()))?,

‎rust/src/client.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,17 @@ impl Client {
161161
Self::with_config(&parsed_url, Configuration::new_with_config(config)?)
162162
}
163163

164+
pub fn default_with_config(config: HashMap<String, String>) -> Result<Self> {
165+
let config = Configuration::new_with_config(config)?;
166+
let url = config
167+
.get(config::DEFAULT_FS)
168+
.ok_or(HdfsError::InvalidArgument(format!(
169+
"No {} setting found",
170+
config::DEFAULT_FS
171+
)))?;
172+
Self::with_config(&Url::parse(&url)?, config)
173+
}
174+
164175
fn with_config(url: &Url, config: Configuration) -> Result<Self> {
165176
if !url.has_host() {
166177
return Err(HdfsError::InvalidArgument(
@@ -493,19 +504,7 @@ impl Default for Client {
493504
/// Creates a new HDFS Client based on the fs.defaultFS setting. Panics if the config files fail to load,
494505
/// no defaultFS is defined, or the defaultFS is invalid.
495506
fn default() -> Self {
496-
let config = Configuration::new().expect("Failed to load configuration");
497-
let url = config
498-
.get(config::DEFAULT_FS)
499-
.ok_or(HdfsError::InvalidArgument(format!(
500-
"No {} setting found",
501-
config::DEFAULT_FS
502-
)))
503-
.expect("No fs.defaultFS config defined");
504-
Self::with_config(
505-
&Url::parse(&url).expect("Failed to parse fs.defaultFS"),
506-
config,
507-
)
508-
.expect("Failed to create default client")
507+
Self::default_with_config(Default::default()).expect("Failed to create default client")
509508
}
510509
}
511510

0 commit comments

Comments
 (0)
Failed to load comments.