diff --git a/.github/workflows/codacy-coverage-reporter.yml b/.github/workflows/codacy-coverage-reporter.yml
new file mode 100644
index 0000000..ba4d0c7
--- /dev/null
+++ b/.github/workflows/codacy-coverage-reporter.yml
@@ -0,0 +1,29 @@
+name: codacy-coverage-reporter
+
+on: ["push"]
+
+jobs:
+ run:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Install Python
+ uses: actions/setup-python@master
+ with:
+ python-version: 3.8
+ - name: Setup Poetry Environment
+ run: |
+ curl -sSL https://install.python-poetry.org | python3 -
+ poetry install
+ - name: Run tests
+ run: |
+ poetry run coverage run -m pytest .
+ - name: Generate Coverage Report
+ run: |
+ poetry run coverage report -m
+ poetry run coverage xml
+ - name: Upload Coverage Report to Codacy
+ uses: codacy/codacy-coverage-reporter-action@v1
+ with:
+ project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
+ coverage-reports: coverage.xml
diff --git a/libpacstall/config.py b/libpacstall/config.py
new file mode 100644
index 0000000..e0e395d
--- /dev/null
+++ b/libpacstall/config.py
@@ -0,0 +1,105 @@
+# ____ __ ____
+# / __ \____ ___________/ /_____ _/ / /
+# / /_/ / __ `/ ___/ ___/ __/ __ `/ / /
+# / ____/ /_/ / /__(__ ) /_/ /_/ / / /
+# /_/ \__,_/\___/____/\__/\__,_/_/_/
+#
+# Copyright (C) 2022-present
+#
+# This file is part of Pacstall
+#
+# Pacstall is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License
+#
+# Pacstall is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Pacstall. If not, see .
+
+"""Module for config parsing."""
+
+from os import cpu_count, environ
+from pathlib import Path
+from typing import Any, Dict
+
+from tomli import load
+
+
+class Settings:
+ """
+ Facade for the file settings.
+
+ Attributes
+ ----------
+ jobs
+ The number of jobs to use for building.
+ editor
+ The editor to use for opening files.
+ """
+
+ jobs: int
+ editor: str
+
+ def __init__(self, raw_config: Dict[str, Any]) -> None:
+ """
+ Initialize the settings.
+
+ Parameters
+ ----------
+ raw_config
+ The raw config dictionary.
+ """
+
+ settings = raw_config["settings"]
+ self.jobs = settings.get("jobs", cpu_count())
+
+ # Loading order:
+ # 1. `editor` config file value.
+ # 2. `EDITOR` environment variable.
+ # 3. `VISUAL` environment variable.
+ # 4. `sensible-editor`
+ self.editor = settings.get(
+ "editor", environ.get("EDITOR", environ.get("VISUAL", "sensible-editor"))
+ )
+
+
+class Config:
+ """
+ Facade for the config file.
+
+ Attributes
+ ----------
+ raw_config
+ The raw config parsed dictionary.
+ settings
+ Facade for the config file settings.
+ """
+
+ settings: Settings
+ raw_config: Dict[str, Any]
+
+ def __init__(
+ self,
+ config_file: Path = Path("/etc/pacstall/config.toml"),
+ ) -> None:
+ """
+ Initialize the config.
+
+ Parameters
+ ----------
+ config_file
+ The config file to parse.
+ """
+
+ config_file.touch(exist_ok=True)
+
+ with config_file.open(mode="rb") as file:
+ raw_config = load(file)
+
+ self.raw_config = raw_config
+
+ self.settings = Settings(raw_config)
diff --git a/poetry.lock b/poetry.lock
index 31a7af3..206e5de 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,3 +1,25 @@
+[[package]]
+name = "atomicwrites"
+version = "1.4.0"
+description = "Atomic file writes."
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+
+[[package]]
+name = "attrs"
+version = "21.4.0"
+description = "Classes Without Boilerplate"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[package.extras]
+dev = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "furo", "sphinx", "sphinx-notfound-page", "pre-commit", "cloudpickle"]
+docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
+tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface", "cloudpickle"]
+tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "cloudpickle"]
+
[[package]]
name = "black"
version = "22.1.0"
@@ -59,6 +81,17 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+[[package]]
+name = "coverage"
+version = "6.3.2"
+description = "Code coverage measurement for Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+toml = ["tomli"]
+
[[package]]
name = "distlib"
version = "0.3.4"
@@ -90,6 +123,14 @@ python-versions = ">=3.7"
[package.extras]
license = ["ukkonen"]
+[[package]]
+name = "iniconfig"
+version = "1.1.1"
+description = "iniconfig: brain-dead simple config-ini parsing"
+category = "dev"
+optional = false
+python-versions = "*"
+
[[package]]
name = "isort"
version = "5.10.1"
@@ -138,6 +179,17 @@ category = "dev"
optional = false
python-versions = "*"
+[[package]]
+name = "packaging"
+version = "21.3"
+description = "Core utilities for Python packages"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.dependencies]
+pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+
[[package]]
name = "pathspec"
version = "0.9.0"
@@ -158,6 +210,18 @@ python-versions = ">=3.7"
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
+[[package]]
+name = "pluggy"
+version = "1.0.0"
+description = "plugin and hook calling mechanisms for python"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+dev = ["pre-commit", "tox"]
+testing = ["pytest", "pytest-benchmark"]
+
[[package]]
name = "pre-commit"
version = "2.17.0"
@@ -174,6 +238,46 @@ pyyaml = ">=5.1"
toml = "*"
virtualenv = ">=20.0.8"
+[[package]]
+name = "py"
+version = "1.11.0"
+description = "library with cross-python path, ini-parsing, io, code, log facilities"
+category = "dev"
+optional = false
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+
+[[package]]
+name = "pyparsing"
+version = "3.0.7"
+description = "Python parsing module"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
+
+[[package]]
+name = "pytest"
+version = "7.1.1"
+description = "pytest: simple powerful testing with Python"
+category = "dev"
+optional = false
+python-versions = ">=3.7"
+
+[package.dependencies]
+atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""}
+attrs = ">=19.2.0"
+colorama = {version = "*", markers = "sys_platform == \"win32\""}
+iniconfig = "*"
+packaging = "*"
+pluggy = ">=0.12,<2.0"
+py = ">=1.8.2"
+tomli = ">=1.0.0"
+
+[package.extras]
+testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
+
[[package]]
name = "pyupgrade"
version = "2.31.1"
@@ -221,7 +325,7 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
name = "tomli"
version = "2.0.1"
description = "A lil' TOML parser"
-category = "dev"
+category = "main"
optional = false
python-versions = ">=3.7"
@@ -254,9 +358,17 @@ testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)",
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
-content-hash = "e70d1be6064e92cef46fb9bad73d7d8c9e318b6bb6abdc0a563e164081c9e595"
+content-hash = "a70573c39e8a8b54472bdda5593a3996f9fb6a8245640507bba92f787df59000"
[metadata.files]
+atomicwrites = [
+ {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"},
+ {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"},
+]
+attrs = [
+ {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"},
+ {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
+]
black = [
{file = "black-22.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:1297c63b9e1b96a3d0da2d85d11cd9bf8664251fd69ddac068b98dc4f34f73b6"},
{file = "black-22.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2ff96450d3ad9ea499fc4c60e425a1439c2120cbbc1ab959ff20f7c76ec7e866"},
@@ -298,6 +410,49 @@ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
]
+coverage = [
+ {file = "coverage-6.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9b27d894748475fa858f9597c0ee1d4829f44683f3813633aaf94b19cb5453cf"},
+ {file = "coverage-6.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37d1141ad6b2466a7b53a22e08fe76994c2d35a5b6b469590424a9953155afac"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9987b0354b06d4df0f4d3e0ec1ae76d7ce7cbca9a2f98c25041eb79eec766f1"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:26e2deacd414fc2f97dd9f7676ee3eaecd299ca751412d89f40bc01557a6b1b4"},
+ {file = "coverage-6.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4dd8bafa458b5c7d061540f1ee9f18025a68e2d8471b3e858a9dad47c8d41903"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:46191097ebc381fbf89bdce207a6c107ac4ec0890d8d20f3360345ff5976155c"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6f89d05e028d274ce4fa1a86887b071ae1755082ef94a6740238cd7a8178804f"},
+ {file = "coverage-6.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:58303469e9a272b4abdb9e302a780072c0633cdcc0165db7eec0f9e32f901e05"},
+ {file = "coverage-6.3.2-cp310-cp310-win32.whl", hash = "sha256:2fea046bfb455510e05be95e879f0e768d45c10c11509e20e06d8fcaa31d9e39"},
+ {file = "coverage-6.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:a2a8b8bcc399edb4347a5ca8b9b87e7524c0967b335fbb08a83c8421489ddee1"},
+ {file = "coverage-6.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f1555ea6d6da108e1999b2463ea1003fe03f29213e459145e70edbaf3e004aaa"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5f4e1edcf57ce94e5475fe09e5afa3e3145081318e5fd1a43a6b4539a97e518"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a15dc0a14008f1da3d1ebd44bdda3e357dbabdf5a0b5034d38fcde0b5c234b7"},
+ {file = "coverage-6.3.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21b7745788866028adeb1e0eca3bf1101109e2dc58456cb49d2d9b99a8c516e6"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8ce257cac556cb03be4a248d92ed36904a59a4a5ff55a994e92214cde15c5bad"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b0be84e5a6209858a1d3e8d1806c46214e867ce1b0fd32e4ea03f4bd8b2e3359"},
+ {file = "coverage-6.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:acf53bc2cf7282ab9b8ba346746afe703474004d9e566ad164c91a7a59f188a4"},
+ {file = "coverage-6.3.2-cp37-cp37m-win32.whl", hash = "sha256:8bdde1177f2311ee552f47ae6e5aa7750c0e3291ca6b75f71f7ffe1f1dab3dca"},
+ {file = "coverage-6.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b31651d018b23ec463e95cf10070d0b2c548aa950a03d0b559eaa11c7e5a6fa3"},
+ {file = "coverage-6.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07e6db90cd9686c767dcc593dff16c8c09f9814f5e9c51034066cad3373b914d"},
+ {file = "coverage-6.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c6dbb42f3ad25760010c45191e9757e7dce981cbfb90e42feef301d71540059"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76aeef1b95aff3905fb2ae2d96e319caca5b76fa41d3470b19d4e4a3a313512"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cf5cfcb1521dc3255d845d9dca3ff204b3229401994ef8d1984b32746bb45ca"},
+ {file = "coverage-6.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fbbdc8d55990eac1b0919ca69eb5a988a802b854488c34b8f37f3e2025fa90d"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ec6bc7fe73a938933d4178c9b23c4e0568e43e220aef9472c4f6044bfc6dd0f0"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9baff2a45ae1f17c8078452e9e5962e518eab705e50a0aa8083733ea7d45f3a6"},
+ {file = "coverage-6.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fd9e830e9d8d89b20ab1e5af09b32d33e1a08ef4c4e14411e559556fd788e6b2"},
+ {file = "coverage-6.3.2-cp38-cp38-win32.whl", hash = "sha256:f7331dbf301b7289013175087636bbaf5b2405e57259dd2c42fdcc9fcc47325e"},
+ {file = "coverage-6.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:68353fe7cdf91f109fc7d474461b46e7f1f14e533e911a2a2cbb8b0fc8613cf1"},
+ {file = "coverage-6.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b78e5afb39941572209f71866aa0b206c12f0109835aa0d601e41552f9b3e620"},
+ {file = "coverage-6.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4e21876082ed887baed0146fe222f861b5815455ada3b33b890f4105d806128d"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34626a7eee2a3da12af0507780bb51eb52dca0e1751fd1471d0810539cefb536"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1ebf730d2381158ecf3dfd4453fbca0613e16eaa547b4170e2450c9707665ce7"},
+ {file = "coverage-6.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd6fe30bd519694b356cbfcaca9bd5c1737cddd20778c6a581ae20dc8c04def2"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:96f8a1cb43ca1422f36492bebe63312d396491a9165ed3b9231e778d43a7fca4"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dd035edafefee4d573140a76fdc785dc38829fe5a455c4bb12bac8c20cfc3d69"},
+ {file = "coverage-6.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5ca5aeb4344b30d0bec47481536b8ba1181d50dbe783b0e4ad03c95dc1296684"},
+ {file = "coverage-6.3.2-cp39-cp39-win32.whl", hash = "sha256:f5fa5803f47e095d7ad8443d28b01d48c0359484fec1b9d8606d0e3282084bc4"},
+ {file = "coverage-6.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:9548f10d8be799551eb3a9c74bbf2b4934ddb330e08a73320123c07f95cc2d92"},
+ {file = "coverage-6.3.2-pp36.pp37.pp38-none-any.whl", hash = "sha256:18d520c6860515a771708937d2f78f63cc47ab3b80cb78e86573b0a760161faf"},
+ {file = "coverage-6.3.2.tar.gz", hash = "sha256:03e2a7826086b91ef345ff18742ee9fc47a6839ccd517061ef8fa1976e652ce9"},
+]
distlib = [
{file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
@@ -310,6 +465,10 @@ identify = [
{file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"},
{file = "identify-2.4.12.tar.gz", hash = "sha256:3f3244a559290e7d3deb9e9adc7b33594c1bc85a9dd82e0f1be519bf12a1ec17"},
]
+iniconfig = [
+ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
+ {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
+]
isort = [
{file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
{file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
@@ -347,6 +506,10 @@ nodeenv = [
{file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"},
{file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"},
]
+packaging = [
+ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
+ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+]
pathspec = [
{file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
@@ -355,10 +518,26 @@ platformdirs = [
{file = "platformdirs-2.5.1-py3-none-any.whl", hash = "sha256:bcae7cab893c2d310a711b70b24efb93334febe65f8de776ee320b517471e227"},
{file = "platformdirs-2.5.1.tar.gz", hash = "sha256:7535e70dfa32e84d4b34996ea99c5e432fa29a708d0f4e394bbcb2a8faa4f16d"},
]
+pluggy = [
+ {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
+ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
+]
pre-commit = [
{file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"},
{file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"},
]
+py = [
+ {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"},
+ {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"},
+]
+pyparsing = [
+ {file = "pyparsing-3.0.7-py3-none-any.whl", hash = "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484"},
+ {file = "pyparsing-3.0.7.tar.gz", hash = "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea"},
+]
+pytest = [
+ {file = "pytest-7.1.1-py3-none-any.whl", hash = "sha256:92f723789a8fdd7180b6b06483874feca4c48a5c76968e03bb3e7f806a1869ea"},
+ {file = "pytest-7.1.1.tar.gz", hash = "sha256:841132caef6b1ad17a9afde46dc4f6cfa59a05f9555aae5151f73bdf2820ca63"},
+]
pyupgrade = [
{file = "pyupgrade-2.31.1-py2.py3-none-any.whl", hash = "sha256:4060a7c20c79d373a3dcf34566b275c6de6cd2b034ad22465d3263fb0de82648"},
{file = "pyupgrade-2.31.1.tar.gz", hash = "sha256:22e0ad6dd39c4381805cb059f1e691b6315c62c0ebcec98a5f29d22cd186a72a"},
diff --git a/pyproject.toml b/pyproject.toml
index fb11fc2..8ae348d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -51,6 +51,7 @@ classifiers = [
[tool.poetry.dependencies]
python = "^3.8"
+tomli = "^2.0.1"
[tool.poetry.dev-dependencies]
black = "^22.1"
@@ -59,6 +60,8 @@ isort = "^5.10.1"
mypy = "^0.942"
pre-commit = "^2.15.0"
pyupgrade = "^2.29.1"
+pytest = "^7.1.1"
+coverage = "^6.3.2"
[tool.isort]
balanced_wrapping = true
diff --git a/tests/test_config_parser.py b/tests/test_config_parser.py
new file mode 100644
index 0000000..0e108c2
--- /dev/null
+++ b/tests/test_config_parser.py
@@ -0,0 +1,167 @@
+# ____ __ ____
+# / __ \____ ___________/ /_____ _/ / /
+# / /_/ / __ `/ ___/ ___/ __/ __ `/ / /
+# / ____/ /_/ / /__(__ ) /_/ /_/ / / /
+# /_/ \__,_/\___/____/\__/\__,_/_/_/
+#
+# Copyright (C) 2022-present
+#
+# This file is part of Pacstall
+#
+# Pacstall is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License
+#
+# Pacstall is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Pacstall. If not, see .
+
+"""Tests for the config parser module."""
+
+from os import cpu_count, environ
+from pathlib import Path
+from typing import Generator
+
+import pytest
+
+from libpacstall import config as libpacstall_config
+
+boilerplate_toml = """
+ ## This is the boilerplate toml file's contents.
+
+ # Configure Pacstall settings here.
+ [settings]
+ jobs = 10 # Number of jobs to run in parallel.
+ editor = "nvim" # Editor to use for editing.
+ """
+
+
+@pytest.fixture()
+def config_file(tmp_path: Path) -> Generator[Path, None, None]:
+ """
+ Fixutre to create a config file.
+
+ Parameters
+ ----------
+ tmp_path
+ Path to the temporary directory. (fixture)
+
+ Yields
+ ------
+ Path
+ Path to the config file.
+ """
+
+ config_file = tmp_path / "config.toml"
+ yield config_file
+ config_file.unlink()
+
+
+def test_raw_config(config_file: Path, tmp_path: Path) -> None:
+ """
+ Test that the raw config is parsed from the config file correctly.
+
+ Parameters
+ ----------
+ config_file
+ Path to the config file. (fixture)
+ tmp_path
+ Path to the temporary directory. (fixture)
+ """
+
+ config_file.write_text(boilerplate_toml)
+
+ assert libpacstall_config.Config(config_file=config_file).raw_config == {
+ "settings": {
+ "jobs": 10,
+ "editor": "nvim",
+ }
+ }
+
+
+class TestSettings:
+ def test_jobs(self, config_file: Path) -> None:
+ """
+ Test that the jobs setting is correctly parsed.
+
+ Parameters
+ ----------
+ config_file
+ Path to the config file. (fixture)
+ """
+
+ # Test boilerplate config.
+ config_file.write_text(boilerplate_toml)
+ assert libpacstall_config.Config(config_file=config_file).settings.jobs == 10
+
+ # Test config with no jobs.
+ jobless_toml = """
+ [settings]
+ editor = "nvim"
+ """
+
+ config_file.write_text(jobless_toml)
+ assert (
+ libpacstall_config.Config(config_file=config_file).settings.jobs
+ == cpu_count()
+ )
+
+ def test_editor(self, config_file: Path, monkeypatch: pytest.MonkeyPatch) -> None:
+ """
+ Test that the editor is set to the correct value.
+
+ This test is a bit tricky because we need to mock the environ
+ variable.
+
+ Parameters
+ ----------
+ config_file
+ Path to the config file. (fixture)
+ monkeypatch
+ The monkeypatch fixture.
+ """
+
+ # Test boilerplate config.
+ config_file.write_text(boilerplate_toml)
+ assert (
+ libpacstall_config.Config(config_file=config_file).settings.editor == "nvim"
+ )
+
+ # Test config with no editor.
+ editorless_toml = """
+ [settings]
+ jobs = 10
+ """
+
+ config_file.write_text(editorless_toml)
+ assert libpacstall_config.Config(
+ config_file=config_file
+ ).settings.editor == environ.get(
+ "EDITOR", environ.get("VISUAL", "sensible-editor")
+ )
+
+ # Test config with no EDITOR environment variable.
+ with monkeypatch.context() as monkey:
+ monkey.delenv("EDITOR", raising=False)
+ monkey.setenv("VISUAL", "TEST_EDITOR")
+
+ config_file.write_text(editorless_toml)
+
+ assert (
+ libpacstall_config.Config(config_file=config_file).settings.editor
+ == "TEST_EDITOR"
+ )
+
+ # Test config with no EDITOR and VISUAL environment variable.
+ with monkeypatch.context() as monkey:
+ monkey.delenv("EDITOR", raising=False)
+ monkey.delenv("VISUAL", raising=False)
+
+ assert (
+ libpacstall_config.Config(config_file=config_file).settings.editor
+ == "sensible-editor"
+ )