Replace tomli with tomlkit

Signed-off-by: Dimitris Zlatanidis <d.zlatanidis@gmail.com>
This commit is contained in:
Dimitris Zlatanidis 2024-06-06 23:05:23 +03:00
parent 40ccfeb279
commit b78e71a67b
9 changed files with 133 additions and 214 deletions

View file

@ -6,6 +6,7 @@
* Added PACKAGE_METHOD config to choose the upgrade method
* Added DOWNGRADE_PACKAGES config to allow to downgrade packages (Thanks to marav)
* Added PACKAGE_TYPE config if you prefer to add your own binary type
* Added python3-tomlkit to replace tomli and tomllib for -current
- Updated:
* Updated message for invalid package version

View file

@ -35,7 +35,8 @@ classifiers = [
]
dependencies = [
"pythondialog>=3.5.3"
"pythondialog>=3.5.3",
"tomlkit>=0.12.5"
]
[tool.flit_core]

View file

@ -1,5 +1,5 @@
pythondialog >= 3.5.3
build >= 0.10.0
tomlkit >= 0.12.5
[socks]
PySocks >= 1.7.1

View file

@ -3,7 +3,7 @@ Extra requirements for Salix GNU/Linux distribution.
There are some additional requirements for salixos users:
python-urllib3
python-tomli
python-tomlkit
python-packaging
pyparsing
lftp

View file

@ -2,11 +2,8 @@
# -*- coding: utf-8 -*-
try:
import tomli
except ModuleNotFoundError:
import tomllib as tomli
import tomlkit
from tomlkit.exceptions import TOMLKitError
from pathlib import Path
from slpkg.configs import Configs
@ -27,10 +24,10 @@ class Blacklist(Configs): # pylint: disable=[R0903]
packages: list = []
if self.blacklist_file_toml.is_file():
try:
with open(self.blacklist_file_toml, 'rb') as black_file:
black: dict = {k.lower(): v for k, v in tomli.load(black_file).items()}
packages: list = black['packages']
except (tomli.TOMLDecodeError, KeyError) as error:
with open(self.blacklist_file_toml, 'r', encoding='utf-8') as file:
black: dict = tomlkit.parse(file.read())
packages: list = black['PACKAGES']
except (KeyError, TOMLKitError) as error:
print()
self.toml_errors.raise_toml_error_message(error, self.blacklist_file_toml)

View file

@ -2,10 +2,8 @@
# -*- coding: utf-8 -*-
try:
import tomli
except ModuleNotFoundError:
import tomllib as tomli
import tomlkit
from tomlkit.exceptions import TOMLKitError
import platform
from typing import Any
@ -76,57 +74,57 @@ class Configs: # pylint: disable=[R0902]
try:
# Load user configuration.
configs = {}
conf = {}
config_path_file = Path(etc_path, f'{prog_name}.toml')
if config_path_file.exists():
with open(config_path_file, 'rb') as conf:
configs = {k.lower(): v for k, v in tomli.load(conf).items()}
with open(config_path_file, 'r', encoding='utf-8') as file:
conf = tomlkit.parse(file.read())
if configs:
config = {k.lower(): v for k, v in configs['configs'].items()}
if conf:
config = conf['CONFIGS']
os_arch: str = config['os_arch']
file_list_suffix: str = config['file_list_suffix']
package_type = config['package_type']
installpkg: str = config['installpkg']
reinstall: str = config['reinstall']
removepkg: str = config['removepkg']
kernel_version: str = config['kernel_version']
colors: bool = config['colors']
makeflags: str = config['makeflags']
gpg_verification: bool = config['gpg_verification']
checksum_md5: bool = config['checksum_md5']
dialog: bool = config['dialog']
view_missing_deps: bool = config['view_missing_deps']
package_method: bool = config['package_method']
downgrade_packages: bool = config['downgrade_packages']
delete_sources: bool = config['delete_sources']
downloader: str = config['downloader']
wget_options: str = config['wget_options']
curl_options: str = config['curl_options']
lftp_get_options: str = config['lftp_get_options']
lftp_mirror_options: str = config['lftp_mirror_options']
download_only_path: Path = Path(config['download_only_path'])
ascii_characters: bool = config['ascii_characters']
ask_question: bool = config['ask_question']
parallel_downloads: bool = config['parallel_downloads']
maximum_parallel: int = config['maximum_parallel']
progress_bar_conf: bool = config['progress_bar']
progress_spinner: str = config['progress_spinner']
spinner_color: str = config['spinner_color']
border_color: str = config['border_color']
process_log: bool = config['process_log']
os_arch: str = config['OS_ARCH']
file_list_suffix: str = config['FILE_LIST_SUFFIX']
package_type = config['PACKAGE_TYPE']
installpkg: str = config['INSTALLPKG']
reinstall: str = config['REINSTALL']
removepkg: str = config['REMOVEPKG']
kernel_version: str = config['KERNEL_VERSION']
colors: bool = config['COLORS']
makeflags: str = config['MAKEFLAGS']
gpg_verification: bool = config['GPG_VERIFICATION']
checksum_md5: bool = config['CHECKSUM_MD5']
dialog: bool = config['DIALOG']
view_missing_deps: bool = config['VIEW_MISSING_DEPS']
package_method: bool = config['PACKAGE_METHOD']
downgrade_packages: bool = config['DOWNGRADE_PACKAGES']
delete_sources: bool = config['DELETE_SOURCES']
downloader: str = config['DOWNLOADER']
wget_options: str = config['WGET_OPTIONS']
curl_options: str = config['CURL_OPTIONS']
lftp_get_options: str = config['LFTP_GET_OPTIONS']
lftp_mirror_options: str = config['LFTP_MIRROR_OPTIONS']
download_only_path: Path = Path(config['DOWNLOAD_ONLY_PATH'])
ascii_characters: bool = config['ASCII_CHARACTERS']
ask_question: bool = config['ASK_QUESTION']
parallel_downloads: bool = config['PARALLEL_DOWNLOADS']
maximum_parallel: int = config['MAXIMUM_PARALLEL']
progress_bar_conf: bool = config['PROGRESS_BAR']
progress_spinner: str = config['PROGRESS_SPINNER']
spinner_color: str = config['SPINNER_COLOR']
border_color: str = config['BORDER_COLOR']
process_log: bool = config['PROCESS_LOG']
urllib_retries: Any = config['urllib_retries']
urllib_redirect: Any = config['urllib_redirect']
urllib_timeout: float = config['urllib_timeout']
urllib_retries: Any = config['URLLIB_RETRIES']
urllib_redirect: Any = config['URLLIB_REDIRECT']
urllib_timeout: float = config['URLLIB_TIMEOUT']
proxy_address: str = config['proxy_address']
proxy_username: str = config['proxy_username']
proxy_password: str = config['proxy_password']
proxy_address: str = config['PROXY_ADDRESS']
proxy_username: str = config['PROXY_USERNAME']
proxy_password: str = config['PROXY_PASSWORD']
except (KeyError, tomli.TOMLDecodeError) as error:
toml_errors.raise_toml_error_message(error, toml_file=Path('/etc/slpkg/slpkg.toml'))
except (KeyError, TOMLKitError) as e:
toml_errors.raise_toml_error_message(e, toml_file=Path('/etc/slpkg/slpkg.toml'))
blink: str = ''
bold: str = ''

View file

@ -2,11 +2,13 @@
# -*- coding: utf-8 -*-
import re
import os
import ast
from pathlib import Path
import tomlkit
from slpkg.configs import Configs
from slpkg.utilities import Utilities
from slpkg.dialog_box import DialogBox
from slpkg.error_messages import Errors
@ -18,7 +20,6 @@ class FormConfigs(Configs):
super(Configs).__init__()
self.dialogbox = DialogBox()
self.errors = Errors()
self.utils = Utilities()
self.orig_configs: list = []
self.config_file: Path = Path(self.etc_path, f'{self.prog_name}.toml')
@ -40,7 +41,7 @@ class FormConfigs(Configs):
title: str = ' Configuration File '
# Creating the elements for the dialog form.
for i, (key, value) in enumerate(self.configs['configs'].items(), start=1):
for i, (key, value) in enumerate(self.config.items(), start=1):
if value is True:
value: str = 'true'
elif value is False:
@ -54,104 +55,46 @@ class FormConfigs(Configs):
os.system('clear')
if code == 'help':
tags = self.configs.values()
self.help()
check: bool = self.check_configs(tags)
if code == 'ok' and check:
self.write_file(tags)
elif not check:
self.edit()
if code == 'ok':
self.write_configs(tags)
def help(self) -> None:
"""Load the configuration file on a text box."""
self.dialogbox.textbox(str(self.config_file), 40, 60)
self.edit()
def check_configs(self, tags: list) -> bool:
"""Check for true of false values."""
keys: list = [
'COLORS',
'DIALOG',
'VIEW_MISSING_DEPS',
'PACKAGE_METHOD',
'DOWNGRADE_PACKAGES',
'DELETE_SOURCES',
'SILENT_MODE',
'ASCII_CHARACTERS',
'ASK_QUESTION',
'KERNEL_VERSION',
'PARALLEL_DOWNLOADS',
'PROGRESS_BAR',
'SPINNING_BAR',
'CASE_INSENSITIVE',
'PROCESS_LOG',
'URLLIB_RETRIES',
'URLLIB_REDIRECT',
'GPG_VERIFICATION',
'CHECKSUM_MD5'
]
values: list = ['true', 'false']
for key, value in zip(self.configs['configs'].keys(), tags):
if key in keys and value not in values:
self.dialogbox.msgbox(f"\nError: Value for '{key}', it must be 'true' or 'false.'\n",
height=7, width=60)
return False
if key in ['DOWNLOADER'] and value not in ['wget2', 'wget', 'curl', 'lftp']:
self.dialogbox.msgbox(f"\nError: Value for '{key}' not supported.\n",
height=7, width=60)
return False
return True
def read_configs(self) -> None:
"""Read the original config file."""
with open(self.config_file, 'r', encoding='utf-8') as toml_file:
self.orig_configs: list = toml_file.readlines()
with open(self.config_file, 'r', encoding='utf-8') as file:
self.toml_original = tomlkit.parse(file.read())
def write_file(self, tags: list) -> None:
"""Write the new values to the config file."""
def write_configs(self, tags: list) -> None:
"""Write new configs to the file.
Args:
tags (list): User new configs
"""
self.read_configs()
with open(self.config_file, 'w', encoding='utf-8') as patch_toml:
for line in self.orig_configs:
for key, value in zip(self.configs['configs'].keys(), tags):
for key, new in zip(self.toml_original['CONFIGS'].keys(), tags):
digit_pattern = re.compile(r"^-?\d+(\.\d+)?$") # pattern for int and float numbers.
list_pattern = re.compile(r'^\s*\[.*\]\s*$') # pattern for list.
if line.lstrip().startswith(f'{key} ='):
line = f' {key} = "{value}"\n'
if new == 'true':
new = True
elif new == 'false':
new = False
elif digit_pattern.match(new):
if new.isdigit():
new = int(new.replace('"', ''))
else:
new = float(new.replace('"', ''))
elif list_pattern.match(new):
new = ast.literal_eval(new)
if line.lstrip().startswith(
self.toml_original['CONFIGS'][key] = new
('COLORS =',
'DIALOG =',
'VIEW_MISSING_DEPS =',
'PACKAGE_METHOD =',
'DOWNGRADE_PACKAGES =',
'DELETE_SOURCES =',
'SILENT_MODE =',
'ASCII_CHARACTERS =',
'ASK_QUESTION =',
'KERNEL_VERSION =',
'PARALLEL_DOWNLOADS =',
'MAXIMUM_PARALLEL = ',
'PROGRESS_BAR =',
'SPINNING_BAR =',
'CASE_SENSITIVE =',
'PROCESS_LOG =',
'URLLIB_RETRIES =',
'URLLIB_REDIRECT =',
'URLLIB_TIMEOUT =',
'GPG_VERIFICATION =',
'CHECKSUM_MD5 =')
):
line: str = line.replace('"', '')
elif line.lstrip().startswith('PACKAGE_TYPE ='):
line: str = line.replace('"[', '[')
line: str = line.replace(']"', ']')
line: str = line.replace("'", '"')
patch_toml.write(line)
with open(self.config_file, 'w', encoding='utf-8') as file:
file.write(tomlkit.dumps(self.toml_original))

View file

@ -2,11 +2,8 @@
# -*- coding: utf-8 -*-
try:
import tomli
except ModuleNotFoundError:
import tomllib as tomli
import tomlkit
from tomlkit.exceptions import TOMLKitError
from pathlib import Path
from typing import ClassVar
from dataclasses import dataclass
@ -157,82 +154,80 @@ class Repositories: # pylint: disable=[R0902]
try:
if repositories_toml_file.is_file():
with open(repositories_toml_file, 'rb') as repo:
repos_config = tomli.load(repo)
with open(repositories_toml_file, 'r', encoding='utf-8') as file:
repos_config = tomlkit.parse(file.read())
repos_config = utils.convert_dict_keys_to_lower(repos_config)
default_repository: str = repos_config['DEFAULT']['REPOSITORY'].lower()
default_repository: str = repos_config['default']['repository'].lower()
new_packages = repos_config['NEW_PACKAGES']['REPOSITORIES']
remove_packages = repos_config['REMOVE_PACKAGES']['REPOSITORIES']
new_packages = repos_config['new_packages']['repositories']
remove_packages = repos_config['remove_packages']['repositories']
sbo_repo: bool = repos_config['SBO']['ENABLE']
sbo_repo_mirror: str = repos_config['SBO']['MIRROR']
sbo_repo: bool = repos_config['sbo']['enable']
sbo_repo_mirror: str = repos_config['sbo']['mirror']
ponce_repo: bool = repos_config['PONCE']['ENABLE']
ponce_repo_mirror: str = repos_config['PONCE']['MIRROR']
ponce_repo: bool = repos_config['ponce']['enable']
ponce_repo_mirror: str = repos_config['ponce']['mirror']
slack_repo: bool = repos_config['SLACK']['ENABLE']
slack_repo_mirror: str = repos_config['SLACK']['MIRROR']
slack_repo: bool = repos_config['slack']['enable']
slack_repo_mirror: str = repos_config['slack']['mirror']
slack_extra_repo: bool = repos_config['slack_extra']['enable']
slack_extra_repo_url: str = repos_config['slack_extra']['mirror']
slack_extra_repo: bool = repos_config['SLACK_EXTRA']['ENABLE']
slack_extra_repo_url: str = repos_config['SLACK_EXTRA']['MIRROR']
slack_extra_repo_mirror_packages: str = slack_extra_repo_url
slack_extra_repo_mirror_changelog: str = f"{'/'.join(slack_extra_repo_url.split('/')[:-2])}/"
slack_patches_repo: bool = repos_config['slack_patches']['enable']
slack_patches_repo_url: str = repos_config['slack_patches']['mirror']
slack_patches_repo: bool = repos_config['SLACK_PATCHES']['ENABLE']
slack_patches_repo_url: str = repos_config['SLACK_PATCHES']['MIRROR']
slack_patches_repo_mirror_packages: str = slack_patches_repo_url
slack_patches_repo_mirror_changelog: str = f"{'/'.join(slack_patches_repo_url.split('/')[:-2])}/"
alien_repo: bool = repos_config['alien']['enable']
alien_repo_url: str = repos_config['alien']['mirror']
alien_repo: bool = repos_config['ALIEN']['ENABLE']
alien_repo_url: str = repos_config['ALIEN']['MIRROR']
alien_repo_mirror_packages: str = alien_repo_url
alien_repo_mirror_changelog: str = f"{'/'.join(alien_repo_url.split('/')[:-3])}/"
multilib_repo: bool = repos_config['multilib']['enable']
multilib_repo_url: str = repos_config['multilib']['mirror']
multilib_repo: bool = repos_config['MULTILIB']['ENABLE']
multilib_repo_url: str = repos_config['MULTILIB']['MIRROR']
multilib_repo_mirror_packages: str = multilib_repo_url
multilib_repo_mirror_changelog: str = f"{'/'.join(multilib_repo_url.split('/')[:-2])}/"
restricted_repo: bool = repos_config['restricted']['enable']
restricted_repo_url: str = repos_config['restricted']['mirror']
restricted_repo: bool = repos_config['RESTRICTED']['ENABLE']
restricted_repo_url: str = repos_config['RESTRICTED']['MIRROR']
restricted_repo_mirror_packages: str = restricted_repo_url
restricted_repo_mirror_changelog: str = f"{'/'.join(restricted_repo_url.split('/')[:-3])}/"
gnome_repo: bool = repos_config['gnome']['enable']
gnome_repo_mirror: str = repos_config['gnome']['mirror']
gnome_repo: bool = repos_config['GNOME']['ENABLE']
gnome_repo_mirror: str = repos_config['GNOME']['MIRROR']
msb_repo: bool = repos_config['msb']['enable']
msb_repo_url: str = repos_config['msb']['mirror']
msb_repo: bool = repos_config['MSB']['ENABLE']
msb_repo_url: str = repos_config['MSB']['MIRROR']
msb_repo_mirror_packages: str = msb_repo_url
msb_repo_mirror_changelog: str = f"{'/'.join(msb_repo_url.split('/')[:-4])}/"
csb_repo: bool = repos_config['csb']['enable']
csb_repo_mirror: str = repos_config['csb']['mirror']
csb_repo: bool = repos_config['CSB']['ENABLE']
csb_repo_mirror: str = repos_config['CSB']['MIRROR']
conraid_repo: bool = repos_config['conraid']['enable']
conraid_repo_mirror: str = repos_config['conraid']['mirror']
conraid_repo: bool = repos_config['CONRAID']['ENABLE']
conraid_repo_mirror: str = repos_config['CONRAID']['MIRROR']
slackonly_repo: bool = repos_config['slackonly']['enable']
slackonly_repo_mirror: str = repos_config['slackonly']['mirror']
slackonly_repo: bool = repos_config['SLACKONLY']['ENABLE']
slackonly_repo_mirror: str = repos_config['SLACKONLY']['MIRROR']
salix_repo: bool = repos_config['salix']['enable']
salix_repo_mirror: str = repos_config['salix']['mirror']
salix_repo: bool = repos_config['SALIX']['ENABLE']
salix_repo_mirror: str = repos_config['SALIX']['MIRROR']
salix_extra_repo: bool = repos_config['salix_extra']['enable']
salix_extra_repo_mirror: str = repos_config['salix_extra']['mirror']
salix_extra_repo: bool = repos_config['SALIX_EXTRA']['ENABLE']
salix_extra_repo_mirror: str = repos_config['SALIX_EXTRA']['MIRROR']
slackel_repo: bool = repos_config['slackel']['enable']
slackel_repo_mirror: str = repos_config['slackel']['mirror']
slackel_repo: bool = repos_config['SLACKEL']['ENABLE']
slackel_repo_mirror: str = repos_config['SLACKEL']['MIRROR']
slint_repo: bool = repos_config['slint']['enable']
slint_repo_mirror: str = repos_config['slint']['mirror']
slint_repo: bool = repos_config['SLINT']['ENABLE']
slint_repo_mirror: str = repos_config['SLINT']['MIRROR']
pprkut_repo: bool = repos_config['pprkut']['enable']
pprkut_repo_mirror: str = repos_config['pprkut']['mirror']
except (tomli.TOMLDecodeError, KeyError) as error:
pprkut_repo: bool = repos_config['PPRKUT']['ENABLE']
pprkut_repo_mirror: str = repos_config['PPRKUT']['MIRROR']
except (KeyError, TOMLKitError) as error:
toml_errors.raise_toml_error_message(error, repositories_toml_file)
# Dictionary configurations of repositories.
@ -418,7 +413,7 @@ class Repositories: # pylint: disable=[R0902]
'repo_tag': pprkut_repo_tag}
}
all_repos = list(repos_config.keys())
all_repos = [name.lower() for name in repos_config.keys()]
defaults_repos = list(repositories.keys())
diff_repos = list(set(all_repos) - set(defaults_repos))

View file

@ -306,19 +306,3 @@ class Utilities(Configs):
pattern: str = '|'.join(blacklist)
matching_packages: list = [pkg for pkg in packages if re.search(pattern, pkg)]
return matching_packages
def convert_dict_keys_to_lower(self, d: dict) -> dict:
"""Convert dictionary keys to lower.
Args:
d (dict): Dictionary data.
Returns:
dict: Dictionary in lower case.
"""
new_dict = {}
for key, value in d.items():
if isinstance(value, dict):
value = self.convert_dict_keys_to_lower(value)
new_dict[key.lower()] = value
return new_dict