Source code for univention.config_registry.misc
"""Univention Configuration Registry helper functions."""
# main configuration registry classes
#
# SPDX-FileCopyrightText: 2004-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only
import os
import re
import string # pylint: disable-msg=W0402
import sys
from shlex import quote as escape_value
from typing import IO
__all__ = [
'INVALID_KEY_CHARS',
'directory_files',
'escape_value',
'key_shell_escape',
'replace_dict',
'replace_umlaut',
'validate_key',
]
[docs]
def replace_dict(line: str, dictionary: dict[str, str]) -> str:
"""
Map any character from line to its value from dictionary.
>>> replace_dict('kernel', {'e': 'E', 'k': '', 'n': 'pp'})
'ErppEl'
"""
return ''.join(dictionary.get(_, _) for _ in line)
[docs]
def replace_umlaut(line: str) -> str:
"""
Replace german umlauts.
>>> replace_umlaut(u'überschrieben') == u'ueberschrieben'
True
"""
return replace_dict(line, UMLAUTS) # pylint: disable-msg=E1101
UMLAUTS = { # type: ignore # pylint: disable-msg=W0612
'Ä': 'Ae',
'ä': 'ae',
'Ö': 'Oe',
'ö': 'oe',
'Ü': 'Ue',
'ü': 'ue',
'ß': 'ss',
}
def asciify(text: str) -> str:
"""
Replace any non-ASCII characters.
:param text: Input text.
:returns: Replaced text.
"""
return text.encode('ascii', 'replace').decode("ascii")
[docs]
def key_shell_escape(line: str) -> str:
"""
Escape variable name by substituting shell invalid characters by '_'.
:param line: UCR variable name.
:returns: substitued variable name
"""
if not line:
raise ValueError('got empty line')
new_line = []
if line[0] in string.digits:
new_line.append('_')
for letter in line:
if letter in VALID_CHARS: # pylint: disable-msg=E1101
new_line.append(letter)
else:
new_line.append('_')
return ''.join(new_line)
VALID_CHARS = ( # type: ignore # pylint: disable-msg=W0612
string.ascii_letters + string.digits + '_')
[docs]
def validate_key(key: str, out: IO = sys.stderr) -> bool:
"""
Check if key consists of only shell valid characters.
:param key: UCR variable name to check.
:param out: Output stream where error message is printed to.
:returns: `True` if the name is valid, `False` otherwise.
"""
old = key
key = replace_umlaut(key)
if old != key:
print('Umlauts in config variable key are not recommended. Please consider renaming "%s" to %s.' % (old, key), file=out)
# return False # Bug #53742
if len(key) > 0:
if ': ' in key:
print('Please fix invalid ": " in config variable key "%s".' % (key,), file=out)
return False
match = INVALID_KEY_CHARS.search(key)
if not match:
return True
print('Please fix invalid character "%s" in config variable key "%s".' % (match.group(), key), file=out)
return False
INVALID_KEY_CHARS = re.compile('[][\r\n!"#$%&\'()+,;<=>?\\\\`{}§]')
[docs]
def directory_files(directory: str) -> list[str]:
"""
Return a list of all files below the given directory.
:param directory: Base directory path.
:returns: List of absolute file names.
"""
result = []
for dirpath, _dirnames, filenames in os.walk(directory):
for filename in filenames:
filename = os.path.join(dirpath, filename)
if os.path.isfile(filename):
result.append(filename)
return result