Compare commits

..

37 commits

Author SHA1 Message Date
076f654a2d
lint/arg 2024-09-13 15:55:46 +02:00
63d30013a3
lint/fs 2024-09-13 15:53:20 +02:00
e306971534
lint/cmd 2024-09-13 15:45:17 +02:00
2dfdabed26
lint/sphinx 2024-09-13 15:40:19 +02:00
5361fbd9a0
3.11 2024-08-20 14:14:03 +02:00
519613eeeb
sphinx/web 2024-07-17 19:10:36 +02:00
282e2ac7a1
log/level 2024-06-13 10:16:53 +02:00
3ce03d17c1
fix 2024-06-12 14:55:37 +02:00
4414a9a712
ruff/line-length 2024-06-12 14:54:59 +02:00
959107c245
run/check 2024-06-12 14:52:55 +02:00
73dc9598b7
useless 2024-06-12 14:48:37 +02:00
0a035f2cd6
ruff/format 2024-06-12 14:46:34 +02:00
7d0ffb8a65
ruff/lint 2024-06-12 14:45:30 +02:00
2648c2e6ba
/.venv 2024-06-12 14:43:26 +02:00
d23bbdd7c9
entry point 2024-06-10 18:02:49 +02:00
df2537dd6d
main/imports 2024-06-10 15:43:59 +02:00
a5ca3a6044
lint main 2024-06-10 15:39:39 +02:00
88434db29a
lint fix 2024-06-10 15:31:15 +02:00
adbdf47ef4
lint |None 2024-06-10 15:27:33 +02:00
9349775193
log/stream 2024-06-10 15:23:05 +02:00
aad5c140dd
−# 2024-06-10 12:52:19 +02:00
c702283696
lint commas 2024-06-10 12:49:49 +02:00
b44b6bd4d4
lint deb 2024-06-10 10:06:25 +02:00
fc3e191dc1
lint prj 2024-06-10 10:04:54 +02:00
e84417c077
lint fs 2024-06-10 10:01:24 +02:00
517da87ffb
lint main 2024-06-10 09:56:59 +02:00
bf5a8a65d7
lint cmd 2024-06-10 09:55:13 +02:00
67b8d4c981
lint squashfs 2024-06-10 09:53:51 +02:00
470d7aa1e9
lint deb 2024-06-10 09:52:56 +02:00
592023d214
lint fs 2024-06-10 09:51:59 +02:00
c7db231dc2
lint grub 2024-06-10 09:50:13 +02:00
a4f49d6ac0
exception 2024-06-10 09:43:22 +02:00
fdbd850d23
lint rwx 2024-06-10 09:41:34 +02:00
b197a15689
linting 2024-06-10 09:38:08 +02:00
5666177582
pyproject/" 2024-06-10 09:37:23 +02:00
4ab0a575b7
pyproject/ruff 2024-06-10 09:35:12 +02:00
b969aa886e
ignore /.vscode 2024-06-10 09:34:45 +02:00
16 changed files with 161 additions and 104 deletions

3
.gitignore vendored
View file

@ -1,4 +1,5 @@
__pycache__
/tmp
/.idea
/.venv
/.vscode
/dist

View file

@ -1,32 +1,39 @@
[build-system]
requires = ['hatchling']
build-backend = 'hatchling.build'
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
authors = [
{ name = 'Marc Beninca', email = 'git@marc.beninca.link' },
{ name = "Marc Beninca", email = "git@marc.beninca.link" },
]
maintainers = [
{ name = 'Marc Beninca', email = 'git@marc.beninca.link' },
{ name = "Marc Beninca", email = "git@marc.beninca.link" },
]
classifiers = [
'Programming Language :: Python :: 3',
'License :: OSI Approved :: GNU Affero General Public License v3',
'Operating System :: OS Independent',
"Programming Language :: Python :: 3",
"License :: OSI Approved :: GNU Affero General Public License v3",
"Operating System :: OS Independent",
]
dependencies = []
description = 'Read Write eXecute'
dynamic = ['version']
description = "Read Write eXecute"
dynamic = ["version"]
keywords = []
license-files = { paths = ['license.md'] }
name = 'rwx'
readme = 'readme.md'
requires-python = '>= 3.10'
license-files = { paths = ["license.md"] }
name = "rwx"
readme = "readme.md"
requires-python = ">= 3.11"
[project.scripts]
# command = 'package.module:function'
# command = "package.module:function"
[project.urls]
[tool.hatch.version]
path = 'rwx/__init__.py'
path = "rwx/__init__.py"
[tool.ruff]
line-length = 80
[tool.ruff.lint]
ignore = ["COM812", "D203", "D213", "ISC001"]
select = ["ALL"]

View file

@ -1 +1,3 @@
__version__ = '0.0.1'
"""Read Write eXecute."""
__version__ = "0.0.1"

View file

@ -1,18 +1,19 @@
#! /usr/bin/env python3
import os
"""Entry point."""
from pathlib import Path
import fs
if __name__ == '__main__':
file_path = os.path.realpath(__file__)
root_path = os.path.dirname(file_path)
directory_path = os.path.join(root_path, 'tmp')
file_path = os.path.join(directory_path, 'file')
if __name__ == "__main__":
file_path = Path(__file__).resolve()
root_path = file_path.parent
directory_path = root_path / "tmp"
file_path = directory_path / "file"
fs.wipe(directory_path)
fs.make_directory(directory_path)
fs.write(file_path, 'Martine écrit beaucoup.')
fs.write(file_path, "Martine écrit beaucoup.")
fs.empty_file(file_path)
fs.write(file_path, 'Martine écrit moins.')
fs.write(file_path, "Martine écrit moins.")

View file

@ -1,6 +1,9 @@
"""Handle system arguments."""
import sys
def split() -> tuple[str, list[str]]:
"""Split command & actual arguments."""
command, *arguments = sys.argv
return command, arguments

View file

@ -1,15 +1,17 @@
"""Handle system commands & packages."""
commands: list[str] = []
packages: list[str] = []
def need(command: str) -> None:
"""Assert package dependency for a command."""
match command:
case 'debootstrap':
package = 'debootstrap'
case 'mksquashfs' | 'unsquashfs':
package = 'squashfs-tools'
case "debootstrap":
package = "debootstrap"
case "mksquashfs" | "unsquashfs":
package = "squashfs-tools"
case _:
package = None
if package:
if package not in packages:
if package and package not in packages:
packages.append(package)

View file

@ -1,14 +1,19 @@
import ps
import rwx.cmd
rwx.cmd.need('mksquashfs')
rwx.cmd.need("mksquashfs")
def mksquashfs(input_root: str, output_file: str):
ps.run([
'mksquashfs',
ps.run(
[
"mksquashfs",
input_root,
output_file,
'-comp', 'zstd',
'-Xcompression-level', str(18),
])
"-comp",
"zstd",
"-Xcompression-level",
str(18),
]
)

View file

@ -1,20 +1,20 @@
import cmd
import ps
cmd.need('debootstrap')
cmd.need("debootstrap")
BOOTSTRAP_ARCHITECTURE = 'amd64'
BOOTSTRAP_VARIANT = 'minbase'
BOOTSTRAP_ARCHITECTURE = "amd64"
BOOTSTRAP_VARIANT = "minbase"
def bootstrap(root_path: str, suite: str, mirror_location: str):
command = [
('debootstrap',),
('--arch', BOOTSTRAP_ARCHITECTURE),
('--variant', BOOTSTRAP_VARIANT),
("debootstrap",),
("--arch", BOOTSTRAP_ARCHITECTURE),
("--variant", BOOTSTRAP_VARIANT),
(suite,),
(root_path,),
(mirror_location,),
]
completed_process = ps.run(command)
return completed_process
return ps.run(command)

2
rwx/err/__init__.py Normal file
View file

@ -0,0 +1,2 @@
class Exception(Exception):
pass

View file

@ -1,36 +1,41 @@
"""Operations involving FileSystems."""
import os
import shutil
from rwx import ps
CHARSET = 'UTF-8'
CHARSET = "UTF-8"
def create_image(file_path: str, size_bytes: int):
def create_image(file_path: str, size_bytes: int) -> None:
"""Create a virtual device image file."""
ps.run(
('qemu-img', 'create'),
('-f', 'qcow2'),
("qemu-img", "create"),
("-f", "qcow2"),
(file_path, size_bytes),
)
def empty_file(path: str):
write(path, str())
def empty_file(path: str) -> None:
"""Empty the file at provided path."""
write(path, "")
def get_mount_uuid(path: str):
def get_mount_uuid(path: str) -> str:
"""Return the UUID of provided mountpoint path."""
return ps.run_line(
('findmnt',),
('--noheadings',),
('--output', 'UUID'),
("findmnt",),
("--noheadings",),
("--output", "UUID"),
(path,),
)
def get_path_mount(path: str):
return ps.run_line(
('stat',),
('--format', '%m'),
("stat",),
("--format", "%m"),
(path,),
)
@ -44,7 +49,7 @@ def make_directory(path: str):
def read_file(file_path: str):
with open(file_path, 'br') as file_object:
with open(file_path, "br") as file_object:
return file_object.read()
@ -66,5 +71,5 @@ def wipe(path: str):
def write(file_path: str, text: str, charset=CHARSET):
with open(file_path, 'bw') as file_object:
with open(file_path, "bw") as file_object:
file_object.write(text.encode(charset))

View file

@ -1,33 +1,39 @@
import cmd
import ps
cmd.need('grub-mkimage')
cmd.need("grub-mkimage")
COMPRESSION = 'xz'
COMPRESSION = "xz"
ENV_BYTES = 1024
ENV_COMMENT = '#'
ENV_HEADER = f'''{ENV_COMMENT} GRUB Environment Block
'''
ENV_COMMENT = "#"
ENV_HEADER = f"""{ENV_COMMENT} GRUB Environment Block
"""
MODULES = {
'i386-pc': [
('biosdisk',),
('ntldr',),
]
"i386-pc": [
("biosdisk",),
("ntldr",),
],
}
def make_image(image_format: str, image_path: str, modules: list[str],
memdisk_path: str, pubkey_path: str = None) -> None:
def make_image(
image_format: str,
image_path: str,
modules: list[str],
memdisk_path: str,
pubkey_path: str | None = None,
) -> None:
args = [
('grub-mkimage',),
('--compress', COMPRESSION),
('--format', image_format),
('--output', image_path),
('--memdisk', memdisk_path),
("grub-mkimage",),
("--compress", COMPRESSION),
("--format", image_format),
("--output", image_path),
("--memdisk", memdisk_path),
]
if pubkey_path:
args.append(('--pubkey', pubkey_path))
args.append(("--pubkey", pubkey_path))
args.extend(modules)
if modules := MODULES.get(image_format, None):
if modules := MODULES.get(image_format):
args.extend(modules)
ps.run(*args)

View file

@ -2,21 +2,31 @@ import logging
import sys
def get_logger(name: str) -> logging.Logger:
def get_file_logger(name: str) -> logging.Logger:
formatter = logging.Formatter(
"%(name)s: %(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(process)d >>> %(message)s"
"%(name)s: %(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(process)d >>> %(message)s",
)
# file_handler = logging.FileHandler('log.txt')
# file_handler.setFormatter(formatter)
# file_handler.setLevel(logging.INFO)
#
out_handler = logging.StreamHandler(stream=sys.stdout)
out_handler.setFormatter(formatter)
out_handler.setLevel(logging.INFO)
#
logger = logging.getLogger(name)
# logger.addHandler(file_handler)
logger.addHandler(out_handler)
logger.setLevel(logging.INFO)
#
return logger
def get_stream_logger(level: int) -> logging.Logger:
out_handler = logging.StreamHandler(stream=sys.stdout)
out_handler.setLevel(level)
#
logger = logging.getLogger()
logger.addHandler(out_handler)
logger.setLevel(level)
#
return logger
stream = get_stream_logger(logging.INFO)

View file

@ -2,7 +2,7 @@ from os import path
class Project:
def __init__(self, file_path: str):
def __init__(self, file_path: str) -> None:
self.file: str = path.realpath(file_path)
self.root: str = path.dirname(self.file)
self.name: str = path.basename(self.root)

View file

@ -1,4 +1,7 @@
"""Project consisting only of a Sphinx documentation."""
from os import path
from sphinx.cmd.build import build_main
from rwx.fs import wipe
@ -6,22 +9,28 @@ from rwx.prj import Project
class SphinxProject(Project):
def __init__(self, file_path: str):
def __init__(self, file_path: str) -> None:
super().__init__(file_path)
def build(self):
output_root: str = path.join(self.root, 'out')
def build(self) -> None:
output_root: str = path.join(self.root, "out")
wipe(output_root)
arguments: list[str] = [
"-E",
"-j", "2",
"-b", "html",
"-D", f"project={self.name}",
"-D", "master_doc={}".format("index"),
"-D", "html_theme={}".format("sphinx_rtd_theme"),
"-c", self.root,
"-j",
"2",
"-b",
"html",
"-D",
f"project={self.name}",
"-D",
"master_doc={}".format("index"),
"-D",
"html_theme={}".format("sphinx_rtd_theme"),
"-c",
self.root,
# "-C",
path.join(self.root, self.name),
path.join(output_root, self.name),
path.join(output_root, "web"),
]
build_main(arguments)

View file

@ -14,7 +14,9 @@ def get_tuples_args(tuples) -> list[str]:
def run(*tuples) -> subprocess.CompletedProcess:
return subprocess.run(get_tuples_args(tuples), capture_output=False)
return subprocess.run(
get_tuples_args(tuples), capture_output=False, check=True
)
def run_line(*tuples, charset: str = txt.CHARSET) -> str:
@ -23,6 +25,8 @@ def run_line(*tuples, charset: str = txt.CHARSET) -> str:
def run_lines(*tuples, charset: str = txt.CHARSET) -> list[str]:
process = subprocess.run(get_tuples_args(tuples), capture_output=True)
process = subprocess.run(
get_tuples_args(tuples), capture_output=True, check=True
)
string = process.stdout.decode(charset)
return string.rstrip().splitlines()

View file

@ -1 +1 @@
CHARSET = 'UTF-8'
CHARSET = "UTF-8"