API Reference (PathOps)¶
Facade¶
sciwork.fs.pathops.PathOps(base_dir=None, *, dry_run=False, input_func=None)
¶
Bases: Paths, Dirs, Create, Delete, Transfer, GetContents, Open, Select, Load, TreeOps, Archives
One-stop helper combining path utilities, listing, selection, transfers, deletion, loading, archiving and simple OS openers.
Examples¶
fs = PathOps.from_cwd() p = fs.resolve_path("data", "file.csv") choice = fs.select_paths("data", path_type="files")
Source code in src/sciwork/fs/pathops.py
38 39 40 41 42 43 44 45 46 47 48 49 50 | |
__repr__()
¶
Source code in src/sciwork/fs/pathops.py
52 53 | |
Core building blocks¶
PathOpsBase¶
sciwork.fs.base.PathOpsBase(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Shared state and core helpers for filesystem operations.
This base keeps a root directory for resolving relative paths, a global dry-run flag (log actions instead of touching the disk), and an injectable input function useful for confirmations and tests. Higher-level modules (delete, listdir, transfer, archives, ...) can subclass or accept an instance of this base to reuse the same context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_dir
|
Optional[PathLike]
|
Base directory used to resolve relative paths. Defaults to |
None
|
dry_run
|
bool
|
When True, operations that would modify the filesystem only log the intended action and return early. |
False
|
input_func
|
Optional[Callable[[str], str]]
|
Function used for interactive prompts. Defaults to :func: |
None
|
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
base_dir = Path(base_dir).resolve() if base_dir else Path.cwd()
instance-attribute
¶
dry_run = bool(dry_run)
instance-attribute
¶
input_func = input_func or input
instance-attribute
¶
__repr__()
¶
Source code in src/sciwork/fs/base.py
155 156 157 158 159 160 | |
__str__()
¶
Source code in src/sciwork/fs/base.py
152 153 | |
_abs(p)
¶
Resolve p relative to :attr:base_dir if it's not absolute.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
PathLike
|
Absolute or relative file system path. |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Absolute path. |
Source code in src/sciwork/fs/base.py
87 88 89 90 91 92 93 94 95 | |
_apply_mode(target, mode)
staticmethod
¶
Best-effort chmod; log, do not propagate errors.
Source code in src/sciwork/fs/base.py
97 98 99 100 101 102 103 104 105 | |
_pick_prompt(override=None, confirm=False)
¶
Choose a (str)→str prompter.
1) explicit override
2) lazy import sciwork.console.Prompter().prompt
3) self.input_func (if present)
4) builtin input
Source code in src/sciwork/fs/base.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
at(base, *, dry_run=False, input_func=input, **kwargs)
classmethod
¶
Create an instance rooted at a given base directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base
|
PathLike
|
Base directory to anchor relative paths. |
required |
dry_run
|
bool
|
If True, do not modify the filesystem (log-only). |
False
|
input_func
|
Optional[Callable[[str], str]]
|
Function used for interactive confirmations. |
input
|
Returns:
| Type | Description |
|---|---|
'PathOpsBase'
|
PathOpsBase: A new instance with base_dir = Path.cwd(). |
Source code in src/sciwork/fs/base.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
coerce_file_path(path)
¶
Return an absolute path to a file. Rejects trailing path separators that make the path look like a directory.
Source code in src/sciwork/fs/base.py
133 134 135 136 137 138 139 140 141 142 | |
coerce_folder_path(path)
¶
Return an absolute path to a folder.
Source code in src/sciwork/fs/base.py
144 145 146 147 148 149 | |
from_cwd(*, dry_run=False, input_func=input, **kwargs)
classmethod
¶
Create an instance rooted at the current working directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dry_run
|
bool
|
If True, do not modify the filesystem (log-only). |
False
|
input_func
|
Optional[Callable[[str], str]]
|
Function used for interactive confirmations. |
input
|
Returns:
| Type | Description |
|---|---|
'PathOpsBase'
|
PathOpsBase: A new instance with base_dir = Path.cwd(). |
Source code in src/sciwork/fs/base.py
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | |
Paths¶
sciwork.fs.paths.Paths(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Small helper layer with user-facing path utilities.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_default_prompt(*, kind, has_default)
staticmethod
¶
Create a readable prompt message.
Source code in src/sciwork/fs/paths.py
33 34 35 36 37 38 39 | |
_looks_like_dir(raw)
staticmethod
¶
Heuristic for directory-like input (trailing slash).
Source code in src/sciwork/fs/paths.py
41 42 43 44 | |
_normalize_exts(exts)
staticmethod
¶
Normalize an extension list to lower-case with a leading dot.
Source code in src/sciwork/fs/paths.py
20 21 22 23 24 25 26 27 28 29 30 31 | |
_type_guard(path, *, kind)
staticmethod
¶
Ensure the existing path matches the requested kind, else raise.
Source code in src/sciwork/fs/paths.py
46 47 48 49 50 51 52 | |
prompt_path(*, kind='any', must_exist=True, allowed_exts=None, default=None, prompt=None, prompter=None)
¶
Prompt the user for a file or folder path and validate it.
The prompter selection processes in this order:
1) explicit prompter argument if provided,
2) method self.prompt (from :class:sciwork.console.Prompter, if available),
3) attribute self.input_func (if present),
4) builtin :func:input.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
kind
|
Literal['file', 'folder', 'any']
|
Either |
'any'
|
must_exist
|
bool
|
When |
True
|
allowed_exts
|
Optional[Iterable[str]]
|
Optional iterable of allowed file extensions (e.g., |
None
|
default
|
Optional[PathLike]
|
Optional default value returned when the user submits an empty input. |
None
|
prompt
|
Optional[str]
|
Optional custom prompt text. If |
None
|
prompter
|
Optional[PrompterProtocol]
|
Optional callable to ask the user. If omitted, it tries to use |
None
|
Returns:
| Type | Description |
|---|---|
Optional[Path]
|
Absolute, resolved path. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
NotADirectoryError
|
When |
IsADirectoryError
|
When |
Source code in src/sciwork/fs/paths.py
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
rename_path(old_path, new_path, *, overwrite=False, create_parents=True)
¶
Rename (or move within the same filesystem) a path to a new path.
If new_path is an existing directory, the entry will be moved into it under its original name.
This prefers :py:meth:Path.rename (atomic on the same FS). If it fails
with EXDEV (cross-device), it falls back to :func:shutil.move.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
old_path
|
PathLike
|
Existing file or directory. |
required |
new_path
|
PathLike
|
The target file or directory path or existing directory. |
required |
overwrite
|
bool
|
If True, remove an existing target before renaming. |
False
|
create_parents
|
bool
|
Ensure the parent directory for the target exists. |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
Absolute resolved target path. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Old path does not exist. |
FileExistsError
|
Target exists and the |
PermissionError
|
On OS-level errors. |
OSError
|
On OS-level errors. |
Source code in src/sciwork/fs/paths.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | |
resolve_path(*parts)
¶
Join one or more path parts relative to base_dir (unless the first
part is absolute) and return an absolute, resolved path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parts
|
PathLike
|
Path segments ( |
()
|
Returns:
| Type | Description |
|---|---|
Path
|
Absolute, resolved path. |
Source code in src/sciwork/fs/paths.py
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | |
Dirs¶
sciwork.fs.dirs.Dirs(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Directory-centric helpers built on top of :class:~sciwork.fs.base.PathOpsBase.
Provides quick checks for emptiness and a simple polling utility to wait until a directory contains at least one matching entry.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
is_folder_empty(folder_path=None, *, include_hidden=True, pattern=None, antipattern=None, shell_pattern=None, files_only=False)
¶
Return True if the folder contains no entries passing the filters.
If no filters are provided, all direct children are considered. Scanning is non-recursive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Directory to inspect (absolute or relative to |
None
|
include_hidden
|
bool
|
If |
True
|
pattern
|
Optional[str]
|
Include only entries whose name contains this substring. |
None
|
antipattern
|
Optional[str]
|
Exclude entries whose name contains this substring. |
None
|
shell_pattern
|
Optional[str]
|
Shell-like pattern matched against the name (e.g., |
None
|
files_only
|
bool
|
If True, consider files only (no subdirectories). |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
True when no entries match the filters; False otherwise. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Folder does not exist. |
NotADirectoryError
|
Path exists but is not a directory. |
Source code in src/sciwork/fs/dirs.py
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | |
require_dir(p, *, create=False)
¶
Ensure p exists and is a directory; optionally create it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
p
|
PathLike
|
Directory path (absolute or relative). |
required |
create
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Path
|
Resolved an absolute directory path. |
Raises:
| Type | Description |
|---|---|
NotADirectoryError
|
When the path exists and is not a directory. |
FileNotFoundError
|
When the directory does not exist and |
Source code in src/sciwork/fs/dirs.py
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | |
temp_dir(folder_path=None, *, prefix='sciwork-', suffix='', cleanup=True)
¶
Create a temporary directory and yield its path.
In :attr:dry_run mode, a hypothetical path is yielded and no filesystem
changes are performed. When cleanup is True, the directory is removed
on context exit; otherwise, it is kept on disk.
Usage¶
with self.temp_dir() as td: # do some stuff with td
:yields: :class:pathlib.Path pointing to the (real or hypothetical) temporary directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Parent directory for the temp directory. |
None
|
prefix
|
str
|
Prefix for the temp directory name. |
'sciwork-'
|
suffix
|
str
|
Suffix for the temp directory name. |
''
|
cleanup
|
bool
|
Remove the directory when leaving the context. |
True
|
Source code in src/sciwork/fs/dirs.py
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | |
try_get_dir(folder_path, *, missing_ok=False)
¶
Resolve folder_path relative to :attr:base_dir, ensure it is a directory,
and return the resolved :class:pathlib.Path.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
PathLike
|
Target folder (absolute or relative to |
required |
missing_ok
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Optional[Path]
|
Resolved directory path, or |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
When missing and |
NotADirectoryError
|
Whe the path exists but is not a directory. |
Source code in src/sciwork/fs/dirs.py
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
wait_until_not_empty(folder_path=None, *, timeout=30.0, poll_interval=0.5, include_hidden=True, pattern=None, antipattern=None, shell_pattern=None, files_only=False)
¶
Poll a folder until at least one entry matches the filters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Folder to watch. If |
None
|
timeout
|
float
|
Maximum time to wait in seconds. Use 0 for a single check. |
30.0
|
poll_interval
|
float
|
Delay between checks in seconds. |
0.5
|
include_hidden
|
bool
|
If False, ignore dot-files. |
True
|
pattern
|
Optional[str]
|
Include only names containing this substring. |
None
|
antipattern
|
Optional[str]
|
Exclude names containing this substring. |
None
|
shell_pattern
|
Optional[str]
|
Shell-like pattern for names (e.g., "*.csv"). |
None
|
files_only
|
bool
|
If True, consider files only (no subdirectories). |
False
|
Returns:
| Type | Description |
|---|---|
int
|
Number of matching entries when the condition is met (> 0). |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Folder does not exist. |
NotADirectoryError
|
Path exists but is not a directory. |
TimeoutError
|
If the folder stays empty past timeout. |
Source code in src/sciwork/fs/dirs.py
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | |
Create¶
sciwork.fs.create.Create(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Creation helpers: folders, files, temp dirs, parents.
Expects PathOpsBase fields+helpers: base_dir, dry_run, _abs(...).
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
create_file(path, *, op='a', create_parents=True, permissions=None, encoding='utf-8')
¶
Create an empty file using the given open mode.
Modes:
-'a': creation if missing, open for appending (do not truncate if exists).
- 'w': creation or truncate to zero lengths.
- 'x': exclusive creation; fail if the file already exists.
Respects base_dir and dry_run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
File path (absolute or relative to |
required |
op
|
str
|
One of {'a', 'w', 'x'}. |
'a'
|
create_parents
|
bool
|
If True, ensure the parent directory exists first. |
True
|
permissions
|
Optional[int]
|
Optional permission bits to apply after creation/update. |
None
|
encoding
|
str
|
Text encoding that is used when creating the file handle. |
'utf-8'
|
Returns:
| Type | Description |
|---|---|
Path
|
Resolved the absolute file path. |
Raises:
| Type | Description |
|---|---|
ValueError
|
Invalid operation. |
FileExistsError
|
With |
PermissionError
|
When permission is denied. |
OSError
|
Other OS-level errors. |
Source code in src/sciwork/fs/create.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 | |
ensure_parent(path, *, mode=511)
¶
Ensure the parent directory of a file path exists.
Resolves path relative to base_dir (if not absolute) and ensures
that path.parent exists (creating it if needed). Honors dry_run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
File path whose parent directory will be ensured. |
required |
mode
|
int
|
Permission bits for newly created directories (ignored on Windows). |
511
|
Returns:
| Type | Description |
|---|---|
Path
|
Resolved the absolute parent directory path. |
Source code in src/sciwork/fs/create.py
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
make_folder(path, *, exist_ok=True, mode=511)
¶
Create a directory (and parents) at path.
The path is resolved relative to self.base_dir if it is not absolute.
Honors dry_run: when True, the action is only logged and no filesystem
changes are performed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
Target directory path (absolute or relative to |
required |
exist_ok
|
bool
|
If True, do not raise if the directory already exists. If False, raise: class: |
True
|
mode
|
int
|
Permission bits for newly created directories (ignored on Windows). |
511
|
Returns:
| Type | Description |
|---|---|
Path
|
Resolved an absolute path to the directory (existing or created). |
Raises:
| Type | Description |
|---|---|
NotADirectoryError
|
When a non-directory exists at the given path. |
FileExistsError
|
When the directory exists and |
PermissionError
|
When permission is denied. |
OSError
|
For other OS-level errors. |
Source code in src/sciwork/fs/create.py
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | |
touch_file(path, *, create_parents=True, exist_ok=True, mode=None)
¶
Create a file if it does not exist or update its modification time.
Respects base_dir and dry_run. When create_parents is True,
missing parent directories are created.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
File path (absolute or relative to |
required |
create_parents
|
bool
|
If True, ensure parent directories exist. |
True
|
exist_ok
|
bool
|
If False and file exist, raise class: |
True
|
mode
|
Optional[int]
|
Optional permission bits to apply after creation/update. |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
Resolved the absolute file path. |
Raises:
| Type | Description |
|---|---|
IsADirectoryError
|
When the path is not a file. |
FileExistsError
|
When the file exists and |
PermissionError
|
When permission is denied. |
OSError
|
Other OS-level errors. |
Source code in src/sciwork/fs/create.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
Delete¶
sciwork.fs.delete.Delete(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Deletion utilities: remove files/dirs, move to trash, and clear folder contents.
The class respects :attr:dry_run from :class:~sciwork.fs.base.PathOpsBase and
uses :class:~sciwork.console.Prompter for interactive confirmations (when available).
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_confirm_removal(action)
¶
Confirms the removal of a file by prompting the user with a confirmation message.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
action
|
str
|
The action is described in the confirmation message. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the user confirms the action, otherwise False. |
Source code in src/sciwork/fs/delete.py
32 33 34 35 36 37 38 39 40 41 | |
_delete_one(entry, *, trash, recursive, follow_symlinks)
¶
Delete or trash a single entry (file/dir/symlink).
Obeys :attr:dry_run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entry
|
Path
|
Path to remove. |
required |
trash
|
bool
|
If True, move to OS trash (Send2Trash). |
required |
recursive
|
bool
|
For directories, delete contents recursively when not trashing. |
required |
follow_symlinks
|
bool
|
Follow symlinks to directories when not trashing. |
required |
Source code in src/sciwork/fs/delete.py
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
_preflight_confirm(root, *, trash, recursive, include_hidden, pattern, antipattern, shell_pattern, threshold)
¶
Estimate the number of candidates and ask for confirmation if count ≥ threshold.
Uses :meth:Prompter.confirm when available; otherwise falls back to a plain prompt.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root
|
Path
|
The root path. |
required |
trash
|
bool
|
If True, moves files to trash. |
required |
recursive
|
bool
|
If True, recursively traverses the directory tree. |
required |
include_hidden
|
bool
|
If True, includes hidden files. |
required |
pattern
|
Optional[str]
|
Include only names containing this substring. |
required |
antipattern
|
Optional[str]
|
Exclude names containing this substring. |
required |
shell_pattern
|
Optional[str]
|
Shell-like pattern for names (e.g., "*.jpg"). |
required |
threshold
|
int
|
Maximal number of items to be removed without confirmation. |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if confirmed or count<threshold; False if the user declined. |
Source code in src/sciwork/fs/delete.py
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | |
clear_folder(folder, *, recursive=True, include_hidden=True, pattern=None, antipattern=None, shell_pattern=None, trash=False, follow_symlinks=False, missing_ok=False, ignore_errors=False, confirm_if_over=None)
¶
Remove all entries from a folder while keeping the folder itself.
This method requires the optional dependency sciwork.fs.Dirs.
By default, removes files and subdirectories recursively (like rm -rf on
the folder contents). When trash is True, entries are moved to the OS
recycle bin (requires mod:Send2Trash) instead of being permanently deleted.
Filtering can be applied using a simple substring pattern and/or
antipattern (both tested against the entry name), or a shell-like
glob (e.g., "*.tmp"). Hidden files/dirs (names starting with .)
can be excluded with include_hidden=False.
Safety rail:
If confirm_is_over is set (e.g., 200), a pre-flight pass estimates the
number of matching entries. If it meets/exceeds the threshold, the user
is prompted once via input_func to confirm. On decline, no deletions
are performed and the method returns 0.
Respects dry_run (logs intended actions without touching the filesystem).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder
|
PathLike
|
Target the folder whose contents will be removed. |
required |
recursive
|
bool
|
If True (default), remove directory trees; when False, only direct children are considered (dirs must be empty). |
True
|
include_hidden
|
bool
|
If False, skip entries with any components starting with |
True
|
pattern
|
Optional[str]
|
Keep only entries whose name contains this substring. |
None
|
antipattern
|
Optional[str]
|
Exclude entries whose name contains this substring. |
None
|
shell_pattern
|
Optional[str]
|
Optional shell pattern matched against the name (e.g., |
None
|
trash
|
bool
|
Move entries to OS trash instead of deleting permanently. |
False
|
follow_symlinks
|
bool
|
If True and deleting permanently, follow symlinks to dirs (dangerous). When |
False
|
missing_ok
|
bool
|
If True, do not raise when folder does not exist. |
False
|
ignore_errors
|
bool
|
If True, log errors and continue; otherwise, re-raise. |
False
|
confirm_if_over
|
Optional[int]
|
Threshold for interactive confirmation before deletion. If the number of matching entries is >= this value, prompt the user via |
None
|
Returns:
| Type | Description |
|---|---|
int
|
Number of entries removed (or that would be if |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If folder does not exist and |
NotADirectoryError
|
If folder exists but is not a directory. |
Source code in src/sciwork/fs/delete.py
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | |
delete(path, *, missing_ok=False, recursive=False, follow_symlinks=False, confirm=False)
¶
Deletes a path (file, directory, or symlink).
- Files and symlinks are unlinked.
- Directories:
* if
recursiveis True, remove the whole tree; * if False (default), only remove an empty directory (likermdir). - Symlinks to directories are treated as symlinks (unlinked) unless
follow_symlinksis True.
Respects dry_run (only logs actions).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
Path of the target file or directory (absolute or relative to |
required |
missing_ok
|
bool
|
If True, do not raise when the path does not exist. |
False
|
recursive
|
bool
|
When deleting a directory, remove contents recursively. |
False
|
follow_symlinks
|
bool
|
If True, and path is a symlink to a directory, delete the target directory tree instead of the link. |
False
|
confirm
|
bool
|
If True, prompt the user before deleting. |
False
|
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
When the path does not exist and |
ValueError
|
Unsupported path type or path type. |
Source code in src/sciwork/fs/delete.py
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
trash(path, *, missing_ok=False, confirm=False)
¶
Move a file or directory to the OS thrash/recycling bin.
Requires the optional dependency Send2Trash
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
Target path (absolute or relative to |
required |
missing_ok
|
bool
|
If True, do not raise when the path does not exist. |
False
|
confirm
|
bool
|
If True, prompt the user before moving to trash. |
False
|
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
When the path does not exist and |
Source code in src/sciwork/fs/delete.py
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | |
Transfer¶
sciwork.fs.transfer.Transfer(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
File/dir transfer utilities (copy/move/delete).
This class reuses:
- :class:PathOpsBase for path resolution and dry-run flags
- :class:Create for :meth:ensure_parent
- :class:Deleter for removing existing targets (when overwrite=True)
Parameters mirror shutil semantics but add safety rails and consistent logging.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_copy_dir(src, dst, *, preserve_metadata)
staticmethod
¶
Copy a directory tree.
We use the copytree with dirs_exist_ok=True (target already removed if overwrite). The copy function is copy2 when preserve_metadata; else copy.
Source code in src/sciwork/fs/transfer.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | |
_copy_file(src, dst, *, preserve_metadata, follow_symlinks)
staticmethod
¶
Copy a single file with desired semantics.
Source code in src/sciwork/fs/transfer.py
85 86 87 88 89 90 91 92 93 94 95 96 97 | |
_move_any(src, dst)
staticmethod
¶
Cross-device save move.
Source code in src/sciwork/fs/transfer.py
115 116 117 118 | |
_preflight_target(target, *, overwrite, create_parents)
¶
Ensure parent, and optionally remove existing target if overwrite=True.
Respects dry_run.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Path
|
The target path to create or overwrite. |
required |
overwrite
|
bool
|
If True and the target exist, remove it. |
required |
create_parents
|
bool
|
Ensure the parent directory exists. |
required |
Source code in src/sciwork/fs/transfer.py
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | |
_resolve_transfer_target(src, dst)
staticmethod
¶
Compute the effective target path for a transfer.
If dst exists and is a directory, returns dst / src.name.
Otherwise, returns dst as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
src
|
Path
|
Source path (must exist). |
required |
dst
|
Path
|
Destination path (can be a dir or file path). |
required |
Returns:
| Type | Description |
|---|---|
Path
|
Effective target path. |
Source code in src/sciwork/fs/transfer.py
29 30 31 32 33 34 35 36 37 38 39 40 41 | |
prepare_transfer(source, destination, *, overwrite, create_parents)
¶
Prepare file transfer by validating the source and destination paths,
handling target preparation, and resolving conflicts such as existing
files based on the overwrite policy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
Path
|
Path object representing the source file or directory. |
required |
destination
|
Path
|
Path object representing the destination file or directory. |
required |
overwrite
|
bool
|
Boolean indicating whether to overwrite existing target files. |
required |
create_parents
|
bool
|
A boolean indicating whether to create non-existent parent directories for the destination path. |
required |
Returns:
| Type | Description |
|---|---|
|
A tuple containing the absolute path of the source and the resolved target destination path. |
Source code in src/sciwork/fs/transfer.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | |
transfer(source, destination, *, operation='copy', overwrite=False, preserve_metadata=True, create_parents=True, follow_symlinks=True)
¶
Copy or move a file/directory.
Behavior¶
- If destination is an existing directory, the entry is copied/moved into it.
- If destination looks like a file path, the entry is copied/moved to that path.
- When
overwrite=True, an existing target is removed first (file/symlink or whole tree). moveuses :func:shutil.move(cross-device).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
PathLike
|
Source file or directory. |
required |
destination
|
PathLike
|
Destination directory of the final path. |
required |
operation
|
Literal['copy', 'move']
|
|
'copy'
|
overwrite
|
bool
|
Remove the existing target first (default: False). |
False
|
preserve_metadata
|
bool
|
For file copies, use :func: |
True
|
create_parents
|
bool
|
Ensure the parent directory for target exists (default: True). |
True
|
follow_symlinks
|
bool
|
For file copies, pass through to shutil to follow symlinks (default: True). |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
The absolute resolved target path. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Source does not exist. |
FileExistsError
|
Target exists and the |
ValueError
|
Invalid operation. |
PermissionError
|
On OS-level errors. |
OSError
|
On OS-level errors. |
Source code in src/sciwork/fs/transfer.py
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
GetContents¶
sciwork.fs.getcontents.GetContents(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Handles directory listing and filtering of files and folders based on various criteria.
This class provides two main APIs: self.get_files_or_folders for
getting files and folders as separate lists or getting directory
contents with detailed metadata by self.get_contents.
It supports filters like pattern matching, time-based cutoffs,
and optionally includes EXIF metadata for files.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
__iter_matching_entries(root, *, recursive, follow_symlinks, include_hidden, pattern, antipattern, shell_pattern, cutoff_older, cutoff_newer, ignore_errors=True)
staticmethod
¶
Yield (entry, stat_result) for items under root that pass name+time filters.
Uses lstat() to keep symlink semantics consistent with metadata.
For parameters, see :meth:get_contents.
Source code in src/sciwork/fs/getcontents.py
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
_confirm_threshold_once(*, threshold, root)
¶
Ask the user for confirmation when the listing grows past a threshold.
Uses sciwork.console.Prompter.confirm() for a consistent UX.
Source code in src/sciwork/fs/getcontents.py
53 54 55 56 57 58 59 60 | |
_time_cutoff_pair(older_than, newer_than)
staticmethod
¶
Turn older/newer specs into POSIX timestamps (or None).
Source code in src/sciwork/fs/getcontents.py
36 37 38 39 40 41 42 | |
_try_exif(entry)
staticmethod
¶
Attach best-effort EXIF (lazy import) for files.
Source code in src/sciwork/fs/getcontents.py
44 45 46 47 48 49 50 51 | |
get_contents(folder_path=None, *, recursive=False, include_hidden=True, pattern=None, antipattern=None, shell_pattern=None, follow_symlinks=False, exif=False, max_items=None, confirm_if_over=None, ignore_errors=True, return_absolute_paths=False, older_than=None, newer_than=None)
¶
List directory contents and return a mapping of path → metadata.
Metadata per entry includes:
- type: 'file' | 'dir' | 'symlink'
- size (bytes, files only)
- created / modified / accessed (ISO 8601, UTC)
- mime (best-effort via :mod:mimetypes)
- ext (file extension, lowercase, including dot)
- optional exif (if exif=True and Pillow is available)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Folder to list. If |
None
|
recursive
|
bool
|
Recurse into subdirectories. |
False
|
include_hidden
|
bool
|
If False, skip dot-entries. |
True
|
pattern
|
Optional[str]
|
Include only names containing this substring. |
None
|
antipattern
|
Optional[str]
|
Exclude names containing this substring. |
None
|
shell_pattern
|
Optional[str]
|
Shell-like pattern for names (e.g., |
None
|
follow_symlinks
|
bool
|
If True, follow directory symlinks during recursion. |
False
|
exif
|
bool
|
If True, try to attach a small EXIF dict for images (best-effort). |
False
|
max_items
|
Optional[int]
|
Stop after collecting this many items. |
None
|
confirm_if_over
|
Optional[int]
|
If set (e.g., 500), prompt once via |
None
|
ignore_errors
|
bool
|
If True, log and continue on errors; else re-raise. |
True
|
return_absolute_paths
|
bool
|
If True, keys are absolute paths; otherwise, keys are relative to folder. |
False
|
older_than
|
Optional[Union[float, int, str, datetime]]
|
Only include entries older that this cutoff (mtime). Accepts seconds-ago (number), ISO 8601 string, duration like '2h', '7d', or a class |
None
|
newer_than
|
Optional[Union[float, int, str, datetime]]
|
Only include entries newer that this cutoff (mtime). Same accepted formats as |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, Dict[str, Any]]
|
Dict[path_str, dict] mapping to metadata. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If folder does not exist. |
NotADirectoryError
|
If the path is not a directory. |
Source code in src/sciwork/fs/getcontents.py
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | |
get_files_and_folders(folder_path=None, *, recursive=False, include_hidden=True, pattern=None, antipattern=None, shell_pattern=None, follow_symlinks=False, return_absolute_paths=False, max_items=None, older_than=None, newer_than=None)
¶
Return two lists (files, folders) with paths matching the filters.
The method mirrors the filtering knobs of :meth:get_contents but
collects only paths (no metadata), which is both faster and simpler
to consume when you just need the file/directory lists.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Folder to list. If |
None
|
recursive
|
bool
|
Recurse into subdirectories. |
False
|
include_hidden
|
bool
|
If False, skip dot-entries. |
True
|
pattern
|
Optional[str]
|
Include only names containing this substring. |
None
|
antipattern
|
Optional[str]
|
Exclude names containing this substring. |
None
|
shell_pattern
|
Optional[str]
|
Shell-like pattern for names (e.g., |
None
|
follow_symlinks
|
bool
|
If True, follow directory symlinks during recursion. |
False
|
return_absolute_paths
|
bool
|
If True, keys are absolute paths; otherwise, keys are relative to folder. |
False
|
max_items
|
Optional[int]
|
Stop after collecting this many items. |
None
|
older_than
|
Optional[Union[float, int, str, datetime]]
|
Only include entries older that this cutoff (mtime). Accepts seconds-ago (number), ISO 8601 string, duration like '2h', '7d', or a class |
None
|
newer_than
|
Optional[Union[float, int, str, datetime]]
|
Only include entries newer that this cutoff (mtime). Same accepted formats as |
None
|
Returns:
| Type | Description |
|---|---|
Dict[str, list[Path]] | None
|
|
Source code in src/sciwork/fs/getcontents.py
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | |
Select¶
sciwork.fs.select.Select(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
High-level selector built on top of class:PathOpsBase.
Reuses a listing/filtering pipeline (get_files_and_folders and
get_contents) and adds sorting and single/multiple selection.
Programmatic via indices or interactive via :class:sciwork.console.Prompter.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_collect_fast(root, *, recursive, include_hidden, follow_symlinks, pattern, antipattern, shell_pattern, path_type, allowed_exts)
staticmethod
¶
Collect only paths (no metadata) via :meth:get_files_and_folders.
Source code in src/sciwork/fs/select.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | |
_collect_with_meta(root, *, recursive, include_hidden, follow_symlinks, pattern, antipattern, shell_pattern, path_type, allowed_exts)
staticmethod
¶
Collect (path, metadata) pairs via :meth:get_contents and filter by
type/extensions.
Source code in src/sciwork/fs/select.py
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |
_prompt_texts(root, candidates, selection_type)
staticmethod
¶
Build a list of lines and a hint for the prompt.
Source code in src/sciwork/fs/select.py
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
_select_many(candidates, *, root, default_indices, prompt_text)
¶
Pick multiple paths.
Accepts comma-separated indices and ranges in the prompt, e.g.:
1,3,5-7. Indices are 1-based.
Source code in src/sciwork/fs/select.py
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
_select_one(candidates, *, root, default_index, prompt_text)
¶
Pick a single path from the candidates (index or interactive).
Source code in src/sciwork/fs/select.py
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | |
select_paths(folder_path=None, *, recursive=False, include_hidden=True, follow_symlinks=False, pattern=None, antipattern=None, shell_pattern=None, sort_by='name', path_type='files', allowed_exts=None, descending=False, multiple=False, default_index=None, default_indices=None, prompt_text=None, return_absolute_paths=False)
¶
Selector one or many paths from a folder using the existing listing/filtering pipeline.
Strategy¶
- If sorting is
name/extonly → use a fast path via :meth:get_files_and_folders. - If sorting is
ctime/mtime/size→ use :meth:get_contents. (needs metadata) - A single candidate returns immediately; otherwise select by index/indices, or
interactively via :class:
sciwork.console.Prompter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
Optional[PathLike]
|
Root directory (absolute or relative to |
None
|
recursive
|
bool
|
Recurse into subdirectories. |
False
|
include_hidden
|
bool
|
Include dot-entries. |
True
|
follow_symlinks
|
bool
|
Follow directory symlinks during recursion. |
False
|
pattern
|
Optional[str]
|
Text pattern to be included in the file names. |
None
|
antipattern
|
Optional[str]
|
Text pattern to be excluded from the file names. |
None
|
shell_pattern
|
Optional[str]
|
Shell-like pattern to be included in the file names. |
None
|
sort_by
|
Literal['name', 'ctime', 'mtime', 'size', 'ext', 'exts']
|
|
'name'
|
path_type
|
Literal['files', 'folders', 'any']
|
|
'files'
|
allowed_exts
|
Optional[Iterable[str]]
|
Allowed extensions for files (e.g., |
None
|
descending
|
bool
|
Sort descending. |
False
|
multiple
|
bool
|
If |
False
|
default_index
|
Optional[int]
|
Single selection (1-based). If set, bypasses the prompt. |
None
|
default_indices
|
Optional[Iterable[int]]
|
Multiple selection (1-based). If set, bypasses the prompt. |
None
|
prompt_text
|
Optional[str]
|
Custom prompt text (when prompting is needed). |
None
|
return_absolute_paths
|
bool
|
If |
False
|
Returns:
| Type | Description |
|---|---|
Union[Path, List[Path]]
|
Either a single selected path ( |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
When no matching entries are found. |
ValueError
|
On invalid parameters, selection or index is out of range. |
Source code in src/sciwork/fs/select.py
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | |
Open¶
sciwork.fs.open.Open(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Cross-platform helpers to open files/folders in the system explorer/viewer.
Expects the host class to provide:
- self._abs(path) from :class:PathOpsBase
- self.dry_run from :class:PathOpsBase
- Prompter().confirm(...) from :class:sciwork.console.Prompter
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_system_open(target)
staticmethod
¶
Open target (folder/file) in the system's file explorer/viewer.
Returns a Popen if the opener is a regular process that we can wait on.
On Windows, os.startfile is preferred and returns None (detached).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Path
|
The resolved path to open. |
required |
Returns:
| Type | Description |
|---|---|
Optional[Popen]
|
subprocess.Popen. |
Raises:
| Type | Description |
|---|---|
RunTimeError
|
Unsupported OS or no opener found. |
OSError
|
spawn/permission errors. |
Source code in src/sciwork/fs/open.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
open_folder_and_wait(folder_path, *, confirm_manual=True, wait=False, timeout=None)
¶
Open a folder in the system file explorer and optionally wait/confirms.
Behavior:
- Validates the path exists and is a directory.
- Respects base_dir and dry_run.
- If wait=True, blocks until the spawned opener process exits (not usual;
most openers detach-on Win/Mac the opener returns immediately).
- If confirm_manual=True, asks the user to press Enter to continue.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
folder_path
|
PathLike
|
Folder to open (absolute or relative to |
required |
confirm_manual
|
bool
|
Prompt the user to continue after opening. |
True
|
wait
|
bool
|
Try to wait for the opener to exit (best-effort; many GUIs detach). |
False
|
timeout
|
Optional[float]
|
Optional timeout for waiting (seconds). |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
The resolved absolute folder path. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Folder does not exist. |
NotADirectoryError
|
Path exists but is not a directory. |
RuntimeError
|
Unsupported OS or no opener available. |
OSError
|
OS-level failures (permissions, spawn errors). |
Source code in src/sciwork/fs/open.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
TreeOps¶
sciwork.fs.trees.TreeOps(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Filesystem tree builder.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
build_tree(tree_dict, *, file_mode='a')
¶
Create a filesystem tree based on an adjacency dictionary.
Input shape
- tree_dict["parents"]: list of root components (strings)
- For each internal node: parent_name: [child1, child2, ...]
- Each leaf is the last component of the branch. If it looks like a file
(it has known suffix), creates an empty file, otherwise creates a directory.
Example:: { "parents": ["data"], "data": ["raw", "processed"], "raw": ["in.csv", "out.txt"], "processed": ["table.xlsx"] }
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tree_dict
|
Dict[str, List[str]]
|
Adjacency mapping with a required 'parents' key. |
required |
file_mode
|
str
|
Mode passed to :meth: |
'a'
|
Returns:
| Type | Description |
|---|---|
Dict[str, Path]
|
Mapping leaf name -> absolute Path created (dir or file). |
Raises:
| Type | Description |
|---|---|
KeyError
|
If 'parents' key is missing. |
ValueError
|
On invalid topology (cycles, multiple parents, orphan nodes). |
Source code in src/sciwork/fs/trees.py
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | |
Archives¶
sciwork.fs.archives.Archives(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase
Archive utilities: safe extraction and creation of archives.
- Heavy modules are imported lazily in helpers (zipfile, pyzipper, tarfile, rarfile).
- Safe extraction with traversal protection via :func:
assert_within_dir. - Respects :attr:
dry_run.
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
_default_ext_for(format_name)
staticmethod
¶
Return the default extension for a given format name.
Source code in src/sciwork/fs/archives.py
107 108 109 110 | |
_destination_dir(src, extract_to, *, overwrite)
¶
Figure out (and prepare) the output directory for extraction.
Source code in src/sciwork/fs/archives.py
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
_ensure_archive_suffix(path, arch_format)
¶
Ensure the archive path has the correct suffix.
Source code in src/sciwork/fs/archives.py
112 113 114 115 116 117 118 | |
_extract_rar(src, dest, *, password, safe)
staticmethod
¶
Extract RAR archive.
Source code in src/sciwork/fs/archives.py
97 98 99 100 101 102 103 104 | |
_extract_tar(src, dest, *, safe)
staticmethod
¶
Extract TAR archive.
Source code in src/sciwork/fs/archives.py
88 89 90 91 92 93 94 95 | |
_extract_zip(src, dest, *, password, safe)
staticmethod
¶
Extract ZIP from src to dest. If password is provided, use pyzipper
(AES/ZipCrypto); otherwise use the standard zipfile. Safe extraction (anti-traversal)
via safe_extract_zip().
Source code in src/sciwork/fs/archives.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | |
_resolve_output_path(src_dir, output_archive_path, arch_format, *, overwrite)
¶
Source code in src/sciwork/fs/archives.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
_unlink_before_compression(dest, overwrite)
¶
Unlink the destination if it exists and overwrite=True.
Source code in src/sciwork/fs/archives.py
140 141 142 143 144 145 146 | |
compress_to_archive(source, output_archive_path=None, *, arch_format='zip', overwrite=False, password=None, include_hidden=True, compresslevel=None)
¶
Compress a directory into an archive (ZIP/TAR*). Supports password only for ZIP via pyzipper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
PathLike
|
Directory to compress. |
required |
output_archive_path
|
Optional[PathLike]
|
Output archive path. If None, create alongside source with the appropriate extension. |
None
|
arch_format
|
Literal['zip', 'tar', 'gztar', 'bztar', 'xztar']
|
'zip' | 'tar' | 'gztar' | 'bztar' | 'xztar' |
'zip'
|
overwrite
|
bool
|
If True and output exist, remove it first. |
False
|
password
|
Optional[str]
|
Optional password (ZIP only; AES-256 via pyzipper). |
None
|
include_hidden
|
bool
|
Include dot-files/directories. |
True
|
compresslevel
|
Optional[int]
|
Compression level (None for default). |
None
|
Returns:
| Type | Description |
|---|---|
Path
|
Absolute path to the created archive. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Source not found. |
NotADirectoryError
|
Source is not a directory. |
FileExistsError
|
Output exists and |
ValueError
|
Invalid format or password used with TAR. |
Source code in src/sciwork/fs/archives.py
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | |
extract_archive(archive_path, extract_to=None, *, overwrite=False, password=None, safe=True)
¶
Extract an archive into a directory.
Supported:
- ZIP (password optional; legacy ZipCrypto)
- TAR / TAR.GZ / TAR.BZ2 / TAR.XZ (no password)
- RAR (password optional, requires mod:rarfile and an external backend)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
archive_path
|
PathLike
|
Path to the archive file. |
required |
extract_to
|
Optional[PathLike]
|
Target directory; default is |
None
|
overwrite
|
bool
|
Allow extraction into a non-empty target dir. |
False
|
password
|
Optional[str]
|
Optional password for ZIP/RAR. Ignored for TAR*. |
None
|
safe
|
bool
|
If True, protect against path traversal (recommended). |
True
|
Returns:
| Type | Description |
|---|---|
Path
|
Absolute path to the extraction directory. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Archive not found. |
FileExistsError
|
Destination exists and is not empty and |
ValueError
|
Unsupported type or password provided for unsupported format. |
PermissionError
|
On OS errors. |
OSError
|
On OS errors. |
Source code in src/sciwork/fs/archives.py
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | |
Load¶
sciwork.fs.load.Load(base_dir=None, *, dry_run=False, input_func=None, **kwargs)
¶
Bases: PathOpsBase, Classify, BaseLoaders
Facade that provides :meth:any_data_loader on top of concrete loaders.
This class relies on other mixins present in your project:
PathOpsBasefor path resolution (_abs) and base_dir handling- a classifier method
classify_path(path) -> str(e.g., 'comma_separated_values', 'text_only', ...) - encoding/delimiter helpers:
detect_encodinganddetect_delimiter
If your current PathOps already mixes these in, you can inherit:
Source code in src/sciwork/fs/base.py
37 38 39 40 41 42 43 44 45 46 47 | |
any_data_loader(path, *, sheet_name=None, encoding=None, delimiter=None, header=None, dtype=None, include_hidden_rows=False, force_type=None)
¶
Open a variety of data files and return either a DataFrame or Python data structures.
Supported:
- Excel (.xlsx, .xlsm, .xls) → pandas.DataFrame (optionally skip rows)
- CSV/TSV/Text (.csv/.tsv/.txt) → pandas.DataFrame (delimiter detection when missing)
- JSON (.json) → dict/list (returned as loaded Python objects)
- XML (.xml) → pandas.DataFrame (flat dict per element)
- SIF (.sif) → pandas.DataFrame (via :meth:_load_sif)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
PathLike
|
Input file path. |
required |
sheet_name
|
Optional[str]
|
For Excel: sheet name to load. If 'choice', the user is prompted to pick. If None, the first sheet is used. |
None
|
encoding
|
Optional[str]
|
Encoding for text files; auto-detected if None. |
None
|
delimiter
|
Optional[str]
|
Delimiter for CSV/TXT; auto-detected if None. |
None
|
header
|
Optional[int]
|
Header row index (0-based) for tabular readers. |
None
|
dtype
|
Optional[dict]
|
Optional dtype mapping passed to the pandas readers. |
None
|
include_hidden_rows
|
bool
|
If True, Excel reader includes rows even if hidden. If False, hidden rows are skipped (via openpyxl). |
False
|
force_type
|
Optional[str]
|
Force a specific type_label (bypasses classification). |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
DataFrame or Python object depending on format. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
Source not found. |
ValueError
|
For unsupported/unknown types. |
Source code in src/sciwork/fs/load.py
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | |