Skip to content

Commit

Permalink
[stdlib] Implement os.remove and os.unlink (#2310)
Browse files Browse the repository at this point in the history
Add `os.remove` and `os.unlink` functions.

Fixes #2306

---------

Signed-off-by: Artemio Garza Reyna <artemiogr97@gmail.com>
  • Loading branch information
artemiogr97 committed Apr 19, 2024
1 parent facbb0a commit 20737dc
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 1 deletion.
2 changes: 1 addition & 1 deletion stdlib/src/os/__init__.mojo
Expand Up @@ -15,5 +15,5 @@
from .atomic import Atomic
from .env import setenv, getenv
from .fstat import lstat, stat, stat_result
from .os import abort, listdir
from .os import abort, listdir, remove, unlink
from .pathlike import PathLike
58 changes: 58 additions & 0 deletions stdlib/src/os/os.mojo
Expand Up @@ -247,3 +247,61 @@ fn abort[
print(message, flush=True)

return abort[result]()


# ===----------------------------------------------------------------------=== #
# remove/unlink
# ===----------------------------------------------------------------------=== #
fn remove(path: String) raises:
"""Removes the specified file.
If the path is a directory or it can not be deleted, an error is raised.
Absolute and relative paths are allowed, relative paths are resolved from cwd.
Args:
path: The path to the file.
"""
var error = external_call["unlink", Int](path._as_ptr())

if error != 0:
# TODO get error message, the following code prints it
# var error_str = String("Something went wrong")
# _ = external_call["perror", Pointer[NoneType]](error_str._as_ptr())
# _ = error_str
raise Error("Can not remove file: " + path)


fn remove[pathlike: os.PathLike](path: pathlike) raises:
"""Removes the specified file.
If the path is a directory or it can not be deleted, an error is raised.
Absolute and relative paths are allowed, relative paths are resolved from cwd.
Args:
path: The path to the file.
"""
remove(path.__fspath__())


fn unlink(path: String) raises:
"""Removes the specified file.
If the path is a directory or it can not be deleted, an error is raised.
Absolute and relative paths are allowed, relative paths are resolved from cwd.
Args:
path: The path to the file.
"""
remove(path)


fn unlink[pathlike: os.PathLike](path: pathlike) raises:
"""Removes the specified file.
If the path is a directory or it can not be deleted, an error is raised.
Absolute and relative paths are allowed, relative paths are resolved from cwd.
Args:
path: The path to the file.
"""
remove(path.__fspath__())
79 changes: 79 additions & 0 deletions stdlib/test/os/test_remove.mojo
@@ -0,0 +1,79 @@
# ===----------------------------------------------------------------------=== #
# Copyright (c) 2024, Modular Inc. All rights reserved.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions:
# https://llvm.org/LICENSE.txt
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===----------------------------------------------------------------------=== #
# RUN: %mojo-no-debug %s

from os import remove, unlink
from os.path import exists
from pathlib import Path

from testing import assert_true, assert_false, assert_raises


fn create_file_and_test_delete_string[
func: fn (String) raises -> None, name: StringLiteral
](filename: String) raises:
try:
with open(filename, "w"):
pass
except:
assert_true(False, "Failed to create file for test")

assert_true(exists(filename))
func(filename)
assert_false(exists(filename), "test with '" + name + "' failed")


fn create_file_and_test_delete_path[
func: fn[pathlike: PathLike] (pathlike) raises -> None,
name: StringLiteral,
](filepath: Path) raises:
try:
with open(filepath.__fspath__(), "w"):
pass
except:
assert_true(False, "Failed to create file for test")

assert_true(exists(filepath))
func(filepath)
assert_false(exists(filepath), "test with '" + name + "' failed")


fn test_remove() raises:
var cwd_path = Path()
var my_file_path = cwd_path / "my_file.test"
var my_file_name = str(my_file_path)

# verify that the test file does not exist before starting the test
assert_false(
exists(my_file_name),
"Unexpected file " + my_file_name + " it should not exist",
)

# tyring to delete non existing file
with assert_raises(contains="Can not remove file: "):
remove(my_file_name)
with assert_raises(contains="Can not remove file: "):
remove(my_file_path)

create_file_and_test_delete_string[remove, "remove"](my_file_name)
create_file_and_test_delete_string[unlink, "unlink"](my_file_name)
create_file_and_test_delete_path[remove, "remove"](my_file_path)
create_file_and_test_delete_path[unlink, "unlink"](my_file_path)

# test with relative path
my_file_name = Path("my_relative_file.test")
create_file_and_test_delete_string[remove, "remove"](my_file_name)


def main():
test_remove()

0 comments on commit 20737dc

Please sign in to comment.