clan-core/pkgs/clan-cli/clan_cli/api/directory.py

129 lines
3.0 KiB
Python
Raw Normal View History

2024-06-19 09:36:11 +00:00
import json
2024-06-08 13:01:45 +00:00
import os
from dataclasses import dataclass, field
from pathlib import Path
2024-06-19 09:36:11 +00:00
from typing import Any, Literal
2024-06-08 13:01:45 +00:00
from clan_cli.errors import ClanError
2024-06-19 09:36:11 +00:00
from clan_cli.nix import nix_shell, run_no_stdout
2024-06-08 13:01:45 +00:00
from . import API
@dataclass
class FileFilter:
title: str | None
mime_types: list[str] | None
patterns: list[str] | None
suffixes: list[str] | None
@dataclass
class FileRequest:
# Mode of the os dialog window
2024-06-11 14:28:02 +00:00
mode: Literal["open_file", "select_folder", "save"]
# Title of the os dialog window
title: str | None = None
# Pre-applied filters for the file dialog
filters: FileFilter | None = None
@API.register
def open_file(file_request: FileRequest) -> str | None:
"""
Abstract api method to open a file dialog window.
It must return the name of the selected file or None if no file was selected.
"""
raise NotImplementedError("Each specific platform should implement this function.")
2024-06-08 13:01:45 +00:00
@dataclass
class File:
path: str
file_type: Literal["file", "directory", "symlink"]
@dataclass
class Directory:
path: str
files: list[File] = field(default_factory=list)
@API.register
def get_directory(current_path: str) -> Directory:
curr_dir = Path(current_path)
directory = Directory(path=str(curr_dir))
if not curr_dir.is_dir():
raise ClanError()
with os.scandir(curr_dir.resolve()) as it:
for entry in it:
if entry.is_symlink():
directory.files.append(
File(
path=str(curr_dir / Path(entry.name)),
file_type="symlink",
)
)
elif entry.is_file():
directory.files.append(
File(
path=str(curr_dir / Path(entry.name)),
file_type="file",
)
)
elif entry.is_dir():
directory.files.append(
File(
path=str(curr_dir / Path(entry.name)),
file_type="directory",
)
)
return directory
2024-06-19 09:36:11 +00:00
@dataclass
class BlkInfo:
name: str
rm: str
size: str
ro: bool
mountpoints: list[str]
type_: Literal["disk"]
@dataclass
class Blockdevices:
blockdevices: list[BlkInfo]
def blk_from_dict(data: dict) -> BlkInfo:
return BlkInfo(
name=data["name"],
rm=data["rm"],
size=data["size"],
ro=data["ro"],
mountpoints=data["mountpoints"],
type_=data["type"], # renamed here
)
@API.register
def show_block_devices() -> Blockdevices:
"""
Abstract api method to show block devices.
It must return a list of block devices.
"""
cmd = nix_shell(["nixpkgs#util-linux"], ["lsblk", "--json"])
proc = run_no_stdout(cmd)
res = proc.stdout.strip()
blk_info: dict[str, Any] = json.loads(res)
return Blockdevices(
blockdevices=[blk_from_dict(device) for device in blk_info["blockdevices"]]
)