Merge branch 'main' into 'main'

بازنویسی کامل سورس

See merge request applications/parch-profiler!3
This commit is contained in:
Sohrab Behdani 2024-12-10 14:43:46 +00:00
commit b26e6e847c
16 changed files with 521 additions and 44 deletions

3
.gitignore vendored
View file

@ -160,4 +160,5 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ .idea/

View file

@ -1,4 +1,3 @@
### 📦 **Parch-Profiler** ### 📦 **Parch-Profiler**
Parch-Profiler is a powerful Python-based utility designed specifically for Parch Linux. It simplifies the management of system packages and configurations by allowing you to generate, validate, and install packages—including AUR and Flatpak—using a structured TOML configuration file. Parch-Profiler is a powerful Python-based utility designed specifically for Parch Linux. It simplifies the management of system packages and configurations by allowing you to generate, validate, and install packages—including AUR and Flatpak—using a structured TOML configuration file.
@ -34,7 +33,7 @@ Parch-Profiler is a powerful Python-based utility designed specifically for Parc
To install packages, clone configurations, and enable services: To install packages, clone configurations, and enable services:
```bash ```bash
python profiler.py --load config.toml parch-profiler apply --config config.toml
``` ```
### **2. Validating a TOML Configuration** ### **2. Validating a TOML Configuration**
@ -42,7 +41,7 @@ python profiler.py --load config.toml
Check if your TOML file is correctly formatted: Check if your TOML file is correctly formatted:
```bash ```bash
python profiler.py --check config.toml parch-profiler check config.toml
``` ```
### **3. Generating a System Package List** ### **3. Generating a System Package List**
@ -50,30 +49,16 @@ python profiler.py --check config.toml
Generate a TOML file listing all installed Pacman, AUR, and Flatpak packages: Generate a TOML file listing all installed Pacman, AUR, and Flatpak packages:
```bash ```bash
python profiler.py --generate-system output.toml parch-profiler gen
``` ```
### **4. Generating a TOML from a Text File**
Convert a simple text file into a TOML configuration:
```bash
python profiler.py --generate-file input.txt output.toml
```
### **5. Reviewing and Editing Generated TOML Files**
After generating a TOML file, you will be prompted to review and edit it using your preferred text editor (`vim` or `nano`).
---
## 🧰 **Sample `proto.toml` File** ## 🧰 **Sample `proto.toml` File**
Heres a sample `proto.toml` file that you can use as a starting point for your configurations: Heres a sample `proto.toml` file that you can use as a starting point for your configurations:
```toml ```toml
# Pacman packages to be installed # Pacman packages to be installed
[packages] [packages.pacman]
packages = [ packages = [
"base-devel", "base-devel",
"neovim", "neovim",
@ -81,23 +66,19 @@ packages = [
] ]
# AUR packages to be installed # AUR packages to be installed
[aur] [packages.paru]
aur_packages = [ packages = [
"google-chrome", "google-chrome",
"paru-bin" "paru-bin"
] ]
# Flatpak packages to be installed # Flatpak packages to be installed
[flatpak] [packages.flatpak]
flatpak_packages = [ packages = [
"com.spotify.Client", "com.spotify.Client",
"org.videolan.VLC" "org.videolan.VLC"
] ]
# Configuration repositories to clone
[config]
nvim = { url = "https://github.com/yourusername/nvim-config.git" }
# Systemd services to enable and start # Systemd services to enable and start
[systemd] [systemd]
systemd_services = [ systemd_services = [
@ -108,26 +89,18 @@ systemd_services = [
--- ---
## 📄 **Sample `input.txt` for TOML Generation**
If you prefer to start from a simple text file, heres how your `input.txt` might look:
```text
packages: base-devel, neovim, git
aur: google-chrome, paru-bin
flatpak: com.spotify.Client, org.videolan.VLC
```
---
## 🛠️ **Installation** ## 🛠️ **Installation**
To use Parch-Profiler on Parch Linux, clone the repository and ensure you have Python installed on your system: To use Parch-Profiler on Parch Linux, clone the repository and ensure you have Python installed on your system:
```bash ```bash
git clone https://git.parchlinux.com/applications/parch-profiler.git git clone https://github.com/MirS0bhan/parch-profiler.git
cd parch-profiler python parch-profiler --help
python profiler.py --help ```
OR
```bash
sudo pacman -S parch-profiler
parch-profiler --help
``` ```
--- ---
@ -146,7 +119,7 @@ This project is licensed under the GPL-3 License - see the [LICENSE](./LICENSE)
## 🛠️ **Requirements** ## 🛠️ **Requirements**
- **Python 3.x** - **Python ^3.8**
- **Parch Linux** - **Parch Linux**
- **Pacman, paru, flatpak** - **Pacman, paru, flatpak**

4
__main__.py Normal file
View file

@ -0,0 +1,4 @@
from src.parch_profiler.cli import app
if __name__ == "__main__":
app()

222
poetry.lock generated Normal file
View file

@ -0,0 +1,222 @@
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
[[package]]
name = "click"
version = "8.1.7"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.7"
files = [
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
]
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.6"
description = "Cross-platform colored terminal text."
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
files = [
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
]
[[package]]
name = "markdown-it-py"
version = "3.0.0"
description = "Python port of markdown-it. Markdown parsing, done right!"
optional = false
python-versions = ">=3.8"
files = [
{file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"},
{file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"},
]
[package.dependencies]
mdurl = ">=0.1,<1.0"
[package.extras]
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
code-style = ["pre-commit (>=3.0,<4.0)"]
compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
linkify = ["linkify-it-py (>=1,<3)"]
plugins = ["mdit-py-plugins"]
profiling = ["gprof2dot"]
rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
[[package]]
name = "mdurl"
version = "0.1.2"
description = "Markdown URL utilities"
optional = false
python-versions = ">=3.7"
files = [
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
[[package]]
name = "plumbum"
version = "1.8.3"
description = "Plumbum: shell combinators library"
optional = false
python-versions = ">=3.6"
files = [
{file = "plumbum-1.8.3-py3-none-any.whl", hash = "sha256:8595d36dae2472587d6f59789c8d7b26250f45f6f6ed75ccb378de59ee7b9cf9"},
{file = "plumbum-1.8.3.tar.gz", hash = "sha256:6092c85ab970b7a7a9d5d85c75200bc93be82b33c9bdf640ffa87d2d7c8709f0"},
]
[package.dependencies]
pywin32 = {version = "*", markers = "platform_system == \"Windows\" and platform_python_implementation != \"PyPy\""}
[package.extras]
dev = ["paramiko", "psutil", "pytest (>=6.0)", "pytest-cov", "pytest-mock", "pytest-timeout"]
docs = ["sphinx (>=4.0.0)", "sphinx-rtd-theme (>=1.0.0)"]
ssh = ["paramiko"]
[[package]]
name = "pygments"
version = "2.18.0"
description = "Pygments is a syntax highlighting package written in Python."
optional = false
python-versions = ">=3.8"
files = [
{file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
{file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
]
[package.extras]
windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pywin32"
version = "306"
description = "Python for Window Extensions"
optional = false
python-versions = "*"
files = [
{file = "pywin32-306-cp310-cp310-win32.whl", hash = "sha256:06d3420a5155ba65f0b72f2699b5bacf3109f36acbe8923765c22938a69dfc8d"},
{file = "pywin32-306-cp310-cp310-win_amd64.whl", hash = "sha256:84f4471dbca1887ea3803d8848a1616429ac94a4a8d05f4bc9c5dcfd42ca99c8"},
{file = "pywin32-306-cp311-cp311-win32.whl", hash = "sha256:e65028133d15b64d2ed8f06dd9fbc268352478d4f9289e69c190ecd6818b6407"},
{file = "pywin32-306-cp311-cp311-win_amd64.whl", hash = "sha256:a7639f51c184c0272e93f244eb24dafca9b1855707d94c192d4a0b4c01e1100e"},
{file = "pywin32-306-cp311-cp311-win_arm64.whl", hash = "sha256:70dba0c913d19f942a2db25217d9a1b726c278f483a919f1abfed79c9cf64d3a"},
{file = "pywin32-306-cp312-cp312-win32.whl", hash = "sha256:383229d515657f4e3ed1343da8be101000562bf514591ff383ae940cad65458b"},
{file = "pywin32-306-cp312-cp312-win_amd64.whl", hash = "sha256:37257794c1ad39ee9be652da0462dc2e394c8159dfd913a8a4e8eb6fd346da0e"},
{file = "pywin32-306-cp312-cp312-win_arm64.whl", hash = "sha256:5821ec52f6d321aa59e2db7e0a35b997de60c201943557d108af9d4ae1ec7040"},
{file = "pywin32-306-cp37-cp37m-win32.whl", hash = "sha256:1c73ea9a0d2283d889001998059f5eaaba3b6238f767c9cf2833b13e6a685f65"},
{file = "pywin32-306-cp37-cp37m-win_amd64.whl", hash = "sha256:72c5f621542d7bdd4fdb716227be0dd3f8565c11b280be6315b06ace35487d36"},
{file = "pywin32-306-cp38-cp38-win32.whl", hash = "sha256:e4c092e2589b5cf0d365849e73e02c391c1349958c5ac3e9d5ccb9a28e017b3a"},
{file = "pywin32-306-cp38-cp38-win_amd64.whl", hash = "sha256:e8ac1ae3601bee6ca9f7cb4b5363bf1c0badb935ef243c4733ff9a393b1690c0"},
{file = "pywin32-306-cp39-cp39-win32.whl", hash = "sha256:e25fd5b485b55ac9c057f67d94bc203f3f6595078d1fb3b458c9c28b7153a802"},
{file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"},
]
[[package]]
name = "rich"
version = "13.7.1"
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
optional = false
python-versions = ">=3.7.0"
files = [
{file = "rich-13.7.1-py3-none-any.whl", hash = "sha256:4edbae314f59eb482f54e9e30bf00d33350aaa94f4bfcd4e9e3110e64d0d7222"},
{file = "rich-13.7.1.tar.gz", hash = "sha256:9be308cb1fe2f1f57d67ce99e95af38a1e2bc71ad9813b0e247cf7ffbcc3a432"},
]
[package.dependencies]
markdown-it-py = ">=2.2.0"
pygments = ">=2.13.0,<3.0.0"
typing-extensions = {version = ">=4.0.0,<5.0", markers = "python_version < \"3.9\""}
[package.extras]
jupyter = ["ipywidgets (>=7.5.1,<9)"]
[[package]]
name = "shellingham"
version = "1.5.4"
description = "Tool to Detect Surrounding Shell"
optional = false
python-versions = ">=3.7"
files = [
{file = "shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686"},
{file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"},
]
[[package]]
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
files = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
[[package]]
name = "typer"
version = "0.12.5"
description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
optional = false
python-versions = ">=3.7"
files = [
{file = "typer-0.12.5-py3-none-any.whl", hash = "sha256:62fe4e471711b147e3365034133904df3e235698399bc4de2b36c8579298d52b"},
{file = "typer-0.12.5.tar.gz", hash = "sha256:f592f089bedcc8ec1b974125d64851029c3b1af145f04aca64d69410f0c9b722"},
]
[package.dependencies]
click = ">=8.0.0"
rich = ">=10.11.0"
shellingham = ">=1.3.0"
typing-extensions = ">=3.7.4.3"
[[package]]
name = "typing-extensions"
version = "4.12.2"
description = "Backported and Experimental Type Hints for Python 3.8+"
optional = false
python-versions = ">=3.8"
files = [
{file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"},
{file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"},
]
[[package]]
name = "typing-validation"
version = "1.2.11.post4"
description = "A simple library for runtime type-checking."
optional = false
python-versions = ">=3.7"
files = [
{file = "typing_validation-1.2.11.post4-py3-none-any.whl", hash = "sha256:73dd504ddebf5210e80d5f65ba9b30efbd0fa42f266728fda7c4f0ba335c699c"},
{file = "typing_validation-1.2.11.post4.tar.gz", hash = "sha256:7aed04ecfbda07e63b7266f90e5d096f96344f7facfe04bb081b21e4a9781670"},
]
[package.dependencies]
typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.11\""}
[package.extras]
dev = ["mypy", "pylint", "pytest", "pytest-cov", "rich"]
[[package]]
name = "vlidt"
version = "0.2.2"
description = "dataclass & validation simple as well as hell."
optional = false
python-versions = "<4.0,>=3.8"
files = [
{file = "vlidt-0.2.2-py3-none-any.whl", hash = "sha256:38be3328510ffb0a56c49e9b5eb26554f9549e3ad5b8b995b6335db6f9aca49f"},
{file = "vlidt-0.2.2.tar.gz", hash = "sha256:9268d45d97b894b61ff8d6682c09a5710ce193b064f1dbc5c000eafb166c5d7f"},
]
[package.dependencies]
typing-validation = ">=1.2.11.post4,<2.0.0"
[metadata]
lock-version = "2.0"
python-versions = "^3.8"
content-hash = "c52741cb4d6436f04978ffb95818cddb3d187d90fac66d5d58ea73539ee35f4f"

26
pyproject.toml Normal file
View file

@ -0,0 +1,26 @@
[tool.poetry]
name = "parch_profiler"
version = "0.1.0"
description = "parch linux basic congiuration manager"
authors = ["Your Name <you@example.com>"]
license = "GNU GENERAL PUBLIC LICENSE v3"
readme = "README.md"
packages = [
{ include = "parch_profiler", from = "src" }
]
[tool.poetry.dependencies]
python = "^3.8"
typer = "^0.12.4"
plumbum = "^1.8.3"
toml = "^0.10.2"
typing-validation = "^1.2.11.post4"
vlidt = "^0.2.1"
[tool.poetry.scripts]
parch-profiler = "parch_profiler.cli:app"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View file

67
src/parch_profiler/cli.py Normal file
View file

@ -0,0 +1,67 @@
from pathlib import Path
import vlidt
import typer
import toml
from .profiler import install_config, generate_config, Config
app = typer.Typer()
CONFIG_FILE = "packages_config.toml"
from rich.console import Console
app = typer.Typer()
console = Console()
CONFIG_FILE = "config.toml" # Define your default config file path
@app.command()
def gen(output: Path = typer.Option(Path(CONFIG_FILE), help="Path to save the generated config file")):
"""
Generate a config file with the list of installed packages.
"""
conf = generate_config()
if vlidt.base.validate(conf):
conf = vlidt.dump(conf)
with open(output, "w") as f:
toml.dump(conf, f)
console.print(f"Config file generated at [bold green]{output}[/bold green] :boom:")
@app.command()
def apply(config: Path = typer.Option(Path(CONFIG_FILE), help="Path to the config file to apply")):
"""
Apply the packages from the config file.
"""
dd = toml.load(open(config, "r"))
install_config(vlidt.load(Config, dd))
console.print("[bold green]Packages applied successfully.[/bold green]")
@app.command()
def check(config: Path = typer.Option(Path(CONFIG_FILE), help="Path to the config file to validate")):
"""
Validate the config file format.
"""
data = toml.load(open(config, "r"))
conf = vlidt.load(Config, data)
vlidt.base.validate(conf)
conf = vlidt.dump(conf)
assert conf != data
with open(config, "w") as f:
toml.dump(conf, f)
console.print("[bold green]Config file is valid.[/bold green] :white_check_mark:")
def main():
app()
if __name__ == "__main__":
main()

View file

@ -0,0 +1,33 @@
from typing import Optional
from plumbum.cmd import git
from os.path import expanduser
from vlidt import BaseModel
class NvimConfig(BaseModel):
url: Optional[str] = None
nvim_git_dir = f"{expanduser('~')}/.config/nvim/.git"
nvim_work_tree = f"{expanduser('~')}/.config/nvim/"
_dir = ["--git-dir", nvim_git_dir, "--work-tree", nvim_work_tree]
def nvim_upstream():
"""
Retrieves the Git remote repositories for the specified Git directory and working tree.
"""
try:
# Execute the Git command with the specified Git directory and working tree
remote = git[*_dir, "remote", "-v", "get-url", "origin"]().strip()
return NvimConfig(remote)
except Exception as e:
print(f"Error retrieving Git remotes: {e}. cant resolve nvim config upstream")
return None
def nvim_clone(url: str):
git["clone", url, nvim_work_tree]()

View file

@ -0,0 +1,37 @@
from ..pckmng import pacman, aur, flatpak
from .base import PackageConfig
from vlidt import BaseModel
_package_managers = {
pkgmgr.__name__.split('.')[-1] : pkgmgr for pkgmgr in [
pacman,
aur,
flatpak
]
}
class PackageManager(BaseModel):
pacman: pacman.PacmanConf
aur: aur.ParuConf
flatpak: flatpak.FlatpakConf
def package_manager(name: str):
return _package_managers[name]
def pckmng_gen():
return PackageManager(
pacman.pkg_list(),
aur.pkg_list(),
flatpak.pkg_list()
)
def pckmng_ins(packages):
for name, config in packages.items():
pc = package_manager(name)
pc.install(config)

View file

@ -0,0 +1,22 @@
from plumbum.cmd import paru
from .base import PackageConfig
class ParuConf(PackageConfig):
pass
# command
install_pck = paru["-S", "--noconfirm"]
list_pck = paru["-Qmq"]
def install(pkg_conf: ParuConf):
cmd = install_pck[pkg_conf.packages]
return cmd()
def pkg_list():
cmd = list_pck
return ParuConf(packages=cmd().splitlines())

View file

@ -0,0 +1,7 @@
from typing import List
from vlidt import BaseModel
class PackageConfig(BaseModel):
packages: List[str]

View file

@ -0,0 +1,22 @@
from plumbum.cmd import flatpak
from .base import PackageConfig
class FlatpakConf(PackageConfig):
pass
# commands
install_pck = flatpak["install", "-y"]
list_pck = flatpak["list", "--app", "--columns=application"]
def install(self):
cmd = install_pck[self.pckconf.packages]
return cmd()
def pkg_list():
cmd = list_pck
return FlatpakConf(packages=cmd().splitlines())

View file

@ -0,0 +1,22 @@
from plumbum.cmd import sudo, pacman
from .base import PackageConfig
class PacmanConf(PackageConfig):
pass
# commands
install_pck = sudo[pacman["-S", "--noconfirm"]]
list_pck = pacman["-Qeq"]
def install(pkg_conf: PacmanConf):
cmd = install_pck[pkg_conf.packages]
return cmd()
def pkg_list() -> PacmanConf:
cmd = list_pck
return PacmanConf(packages=cmd().splitlines())

View file

@ -0,0 +1,27 @@
from typing import Optional, Dict, Type, List
from vlidt import BaseModel
from .pckmng import pckmng_gen, pckmng_ins, PackageManager
from .systemd import enable_service_list
from .nvim import nvim_upstream, NvimConfig
class Config(BaseModel):
packages: PackageManager
systemd_services: Optional[List[str]] = None
nvim: NvimConfig = None
def install_config(conf: Config):
pckmng_ins(conf.packages) # installing packages
if conf.systemd_services:
enable_service_list(conf.systemd_services)
def generate_config():
return Config(
pckmng_gen(),
nvim=nvim_upstream()
)

View file

@ -0,0 +1,14 @@
from typing import List, NewType
from plumbum.cmd import sudo, systemctl
systemctl = sudo[systemctl]
enable_service = systemctl["enable"]
start_service = systemctl["start"]
def enable_service_list(services: List[str]):
for service in services:
enable_service[service]()
start_service[service]()