Skip to content

Commit

Permalink
feat: pathlib: filesystem-relative methods
Browse files Browse the repository at this point in the history
  • Loading branch information
litlighilit committed Jun 26, 2024
1 parent 4150d3d commit bb4a148
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 1 deletion.
81 changes: 80 additions & 1 deletion src/pylib/Lib/pathlib.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import ../builtins/list

import ./n_pathlib

macro wrapStr(aString: untyped, strings: untyped) =
macro wrapStr(aString: untyped, strings: untyped; excludes: untyped) =
let nlib = ident "n_pathlib"
result = newStmtList()
var exp = nnkExportExceptStmt.newTree nlib
Expand All @@ -32,12 +32,15 @@ macro wrapStr(aString: untyped, strings: untyped) =
result = newPyList[PyStr]()
for i in `nlib`.`a` self:
result.append str i
for i in excludes: exp.add i
result.add exp

wrapStr [
name, suffix, stem
], [
parts, suffixes
], [
read_nstring, write_nstring
]

using self: Path
Expand Down Expand Up @@ -76,3 +79,79 @@ proc write_text*(self; data: PyStr, encoding=DefEncoding, errors=DefErrors
proc read_bytes*(self): PyBytes = bytes readFile $self
proc write_bytes*(self; b: PyBytes) = writeFile $self, $b

proc readlink*(self): Path = Path os.readlink $self

proc symlink_to*(self; target: string|Path; target_is_directory=false) =
os.symlink($self, $target, target_is_directory)

proc hardlink_to*(self; target: string|Path) =
## Added in version 3.10.
os.link($self, $target)

proc unlink*(self) =
## for missing_ok==False
os.unlink $self

proc unlink*(self; missing_ok: bool) =
if not missing_ok:
self.unlink
return
try:
os.unlink $self
except FileNotFoundError:
discard

template reXX(rename){.dirty.} =
proc rename*(self; target: Path): Path{.discardable.} =
os.rename($self, $target)
target

proc rename*(self; target: string): Path{.discardable.} =
rename(self, Path(target))

reXX rename
reXX replace

proc mkdirParents(self; exist_ok=false) =
## for parents==False
if not exist_ok and existsOrCreateDir $self:
raiseExcWithPath $self

proc mkdir*(self; mode = 0o777, parents: bool, exist_ok=false) =
if parents:
self.mkdirParents exist_ok
else:
if not exist_ok:
os.mkdir($self, mode=mode)
return
try:
os.mkdir($self, mode=mode)
except FileExistsError:
discard

proc rmdir*(self) = os.rmdir $self

proc touch*(self; mode=0o666, exist_ok=true) =
## Create this file with the given access mode, if it doesn't exist.

let s = $self
if exist_ok:
# First try to bump modification time
# Implementation note: GNU touch uses the UTIME_NOW option of
# the utimensat() / futimens() functions.
try:
os.utime(s)
return
except OSError:
# Avoid exception chaining
discard
var flags = os.O_CREAT | os.O_WRONLY
if not exist_ok:
flags |= os.O_EXCL
let fd = os.open(s, flags, mode)
os.close(fd)

proc stat*(self): stat_result = os.stat($self)

# TODO: stat(..., follow_symlinks), see os
# and exists
18 changes: 18 additions & 0 deletions src/pylib/Lib/pathlib_impl/meth.nim
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,21 @@ proc read_nstring*(self): string =
proc write_nstring*(self, s: string) =
## EXT.
writeFile $self, s


iterator iterdir*(self): Path =
for i in walkDir($self, relative=true, checkDir=true):
yield self / Path(i.path)

type IterDirGenerator = ref object
iter: iterator(): Path
proc iterdir*(self): IterDirGenerator =
result = IterDirGenerator(iter: iterator (): Path =
for i in self.iterdir():
yield i
)

proc mkdirParentsExistsOk*(self) =
## EXT. equal to `path.mkdir(parents=True, exists_ok=True)`
createDir $self

0 comments on commit bb4a148

Please sign in to comment.