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

View file

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

View file

@ -1,5 +1,5 @@
pythondialog >= 3.5.3 pythondialog >= 3.5.3
build >= 0.10.0 tomlkit >= 0.12.5
[socks] [socks]
PySocks >= 1.7.1 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: There are some additional requirements for salixos users:
python-urllib3 python-urllib3
python-tomli python-tomlkit
python-packaging python-packaging
pyparsing pyparsing
lftp lftp

View file

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

View file

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

View file

@ -2,11 +2,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import re
import os import os
import ast
from pathlib import Path from pathlib import Path
import tomlkit
from slpkg.configs import Configs from slpkg.configs import Configs
from slpkg.utilities import Utilities
from slpkg.dialog_box import DialogBox from slpkg.dialog_box import DialogBox
from slpkg.error_messages import Errors from slpkg.error_messages import Errors
@ -18,7 +20,6 @@ class FormConfigs(Configs):
super(Configs).__init__() super(Configs).__init__()
self.dialogbox = DialogBox() self.dialogbox = DialogBox()
self.errors = Errors() self.errors = Errors()
self.utils = Utilities()
self.orig_configs: list = [] self.orig_configs: list = []
self.config_file: Path = Path(self.etc_path, f'{self.prog_name}.toml') self.config_file: Path = Path(self.etc_path, f'{self.prog_name}.toml')
@ -40,7 +41,7 @@ class FormConfigs(Configs):
title: str = ' Configuration File ' title: str = ' Configuration File '
# Creating the elements for the dialog form. # 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: if value is True:
value: str = 'true' value: str = 'true'
elif value is False: elif value is False:
@ -54,104 +55,46 @@ class FormConfigs(Configs):
os.system('clear') os.system('clear')
if code == 'help': if code == 'help':
tags = self.configs.values()
self.help() self.help()
check: bool = self.check_configs(tags) if code == 'ok':
self.write_configs(tags)
if code == 'ok' and check:
self.write_file(tags)
elif not check:
self.edit()
def help(self) -> None: def help(self) -> None:
"""Load the configuration file on a text box.""" """Load the configuration file on a text box."""
self.dialogbox.textbox(str(self.config_file), 40, 60) self.dialogbox.textbox(str(self.config_file), 40, 60)
self.edit() 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: def read_configs(self) -> None:
"""Read the original config file.""" """Read the original config file."""
with open(self.config_file, 'r', encoding='utf-8') as toml_file: with open(self.config_file, 'r', encoding='utf-8') as file:
self.orig_configs: list = toml_file.readlines() self.toml_original = tomlkit.parse(file.read())
def write_file(self, tags: list) -> None: def write_configs(self, tags: list) -> None:
"""Write the new values to the config file.""" """Write new configs to the file.
Args:
tags (list): User new configs
"""
self.read_configs() self.read_configs()
with open(self.config_file, 'w', encoding='utf-8') as patch_toml: for key, new in zip(self.toml_original['CONFIGS'].keys(), tags):
for line in self.orig_configs: digit_pattern = re.compile(r"^-?\d+(\.\d+)?$") # pattern for int and float numbers.
for key, value in zip(self.configs['configs'].keys(), tags): list_pattern = re.compile(r'^\s*\[.*\]\s*$') # pattern for list.
if line.lstrip().startswith(f'{key} ='): if new == 'true':
line = f' {key} = "{value}"\n' 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 =', with open(self.config_file, 'w', encoding='utf-8') as file:
'DIALOG =', file.write(tomlkit.dumps(self.toml_original))
'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)

View file

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

View file

@ -306,19 +306,3 @@ class Utilities(Configs):
pattern: str = '|'.join(blacklist) pattern: str = '|'.join(blacklist)
matching_packages: list = [pkg for pkg in packages if re.search(pattern, pkg)] matching_packages: list = [pkg for pkg in packages if re.search(pattern, pkg)]
return matching_packages 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