fix iniparse
lint / docker (push) Successful in 9m14s

fix code passing ruff linter
pre-commit ruff
pre-commit ruff format
This commit is contained in:
2024-11-29 23:45:40 +01:00
parent aa8a68aa80
commit 737f9bea38
27 changed files with 2375 additions and 2016 deletions
+90 -74
View File
@@ -12,41 +12,48 @@ The underlying INIConfig object can be accessed as cfg.data
"""
import re
from typing import Dict, List, TextIO, Optional, Type, Union, Tuple
import six
from .configparser import (
DuplicateSectionError,
NoSectionError,
NoOptionError,
InterpolationMissingOptionError,
InterpolationDepthError,
InterpolationSyntaxError,
DEFAULTSECT,
MAX_INTERPOLATION_DEPTH,
)
# These are imported only for compatibility.
# The code below does not reference them directly.
from .configparser import Error, InterpolationError, MissingSectionHeaderError, ParsingError
from . import ini
# These are imported only for compatiability.
# The code below does not reference them directly.
from .configparser import (DEFAULTSECT, MAX_INTERPOLATION_DEPTH,
DuplicateSectionError, Error,
InterpolationDepthError, InterpolationError,
InterpolationMissingOptionError,
InterpolationSyntaxError, MissingSectionHeaderError,
NoOptionError, NoSectionError, ParsingError)
class RawConfigParser(object):
def __init__(self, defaults=None, dict_type=dict):
if dict_type != dict:
raise ValueError('Custom dict types not supported')
class RawConfigParser:
def __init__(self, defaults: Optional[Dict[str, str]] = None, dict_type: Union[Type[Dict], str] = dict):
if not isinstance(dict_type, dict):
raise ValueError("Custom dict types not supported")
self.data = ini.INIConfig(defaults=defaults, optionxformsource=self)
def optionxform(self, optionstr):
def optionxform(self, optionstr: str) -> str:
return optionstr.lower()
def defaults(self):
d = {}
secobj = self.data._defaults
def defaults(self) -> Dict[str, str]:
d: Dict[str, str] = {}
secobj: ini.INISection = self.data._defaults
name: str
for name in secobj._options:
d[name] = secobj._compat_get(name)
return d
def sections(self):
def sections(self) -> List[str]:
"""Return a list of section names, excluding [DEFAULT]"""
return list(self.data)
def add_section(self, section):
def add_section(self, section: str) -> None:
"""Create a new section in the configuration.
Raise DuplicateSectionError if a section by the specified name
@@ -56,28 +63,28 @@ class RawConfigParser(object):
# The default section is the only one that gets the case-insensitive
# treatment - so it is special-cased here.
if section.lower() == "default":
raise ValueError('Invalid section name: %s' % section)
raise ValueError("Invalid section name: %s" % section)
if self.has_section(section):
raise DuplicateSectionError(section)
else:
self.data._new_namespace(section)
def has_section(self, section):
def has_section(self, section: str) -> bool:
"""Indicate whether the named section is present in the configuration.
The DEFAULT section is not acknowledged.
"""
return section in self.data
def options(self, section):
def options(self, section: str) -> List[str]:
"""Return a list of option names for the given section name."""
if section in self.data:
return list(self.data[section])
else:
raise NoSectionError(section)
def read(self, filenames):
def read(self, filenames: Union[List[str], str]) -> List[str]:
"""Read and parse a filename or a list of filenames.
Files that cannot be opened are silently ignored; this is
@@ -86,9 +93,11 @@ class RawConfigParser(object):
home directory, systemwide directory), and all existing
configuration files in the list will be read. A single
filename may also be given.
Returns the list of files that were read.
"""
files_read = []
if isinstance(filenames, six.string_types):
if isinstance(filenames, str):
filenames = [filenames]
for filename in filenames:
try:
@@ -100,7 +109,7 @@ class RawConfigParser(object):
fp.close()
return files_read
def readfp(self, fp, filename=None):
def readfp(self, fp: TextIO, filename: Optional[str] = None) -> None:
"""Like read() but the argument must be a file-like object.
The `fp' argument must have a `readline' method. Optional
@@ -110,60 +119,70 @@ class RawConfigParser(object):
"""
self.data._readfp(fp)
def get(self, section, option, vars=None):
def get(self, section: str, option: str, vars: dict = None) -> str:
if not self.has_section(section):
raise NoSectionError(section)
sec = self.data[section]
sec: ini.INISection = self.data[section]
if option in sec:
return sec._compat_get(option)
else:
raise NoOptionError(option, section)
def items(self, section):
def items(self, section: str) -> List[Tuple[str, str]]:
if section in self.data:
ans = []
opt: str
for opt in self.data[section]:
ans.append((opt, self.get(section, opt)))
return ans
else:
raise NoSectionError(section)
def getint(self, section, option):
def getint(self, section: str, option: str) -> int:
return int(self.get(section, option))
def getfloat(self, section, option):
def getfloat(self, section: str, option: str) -> float:
return float(self.get(section, option))
_boolean_states = {'1': True, 'yes': True, 'true': True, 'on': True,
'0': False, 'no': False, 'false': False, 'off': False}
_boolean_states = {
"1": True,
"yes": True,
"true": True,
"on": True,
"0": False,
"no": False,
"false": False,
"off": False,
}
def getboolean(self, section, option):
def getboolean(self, section: str, option: str) -> bool:
v = self.get(section, option)
if v.lower() not in self._boolean_states:
raise ValueError('Not a boolean: %s' % v)
raise ValueError("Not a boolean: %s" % v)
return self._boolean_states[v.lower()]
def has_option(self, section, option):
def has_option(self, section: str, option: str) -> bool:
"""Check for the existence of a given option in a given section."""
if section in self.data:
sec = self.data[section]
else:
raise NoSectionError(section)
return (option in sec)
return option in sec
def set(self, section, option, value):
def set(self, section: str, option: str, value: str) -> None:
"""Set an option."""
if section in self.data:
self.data[section][option] = value
else:
raise NoSectionError(section)
def write(self, fp):
def write(self, fp: TextIO) -> None:
"""Write an .ini-format representation of the configuration state."""
fp.write(str(self.data))
def remove_option(self, section, option):
# FIXME Return a boolean instead of integer
def remove_option(self, section: str, option: str) -> int:
"""Remove an option."""
if section in self.data:
sec = self.data[section]
@@ -175,7 +194,7 @@ class RawConfigParser(object):
else:
return 0
def remove_section(self, section):
def remove_section(self, section: str) -> bool:
"""Remove a file section."""
if not self.has_section(section):
return False
@@ -183,15 +202,15 @@ class RawConfigParser(object):
return True
class ConfigDict(object):
"""Present a dict interface to a ini section."""
class ConfigDict:
"""Present a dict interface to an ini section."""
def __init__(self, cfg, section, vars):
self.cfg = cfg
self.section = section
self.vars = vars
def __init__(self, cfg: RawConfigParser, section: str, vars: dict):
self.cfg: RawConfigParser = cfg
self.section: str = section
self.vars: dict = vars
def __getitem__(self, key):
def __getitem__(self, key: str) -> Union[str, List[Union[int, str]]]:
try:
return RawConfigParser.get(self.cfg, self.section, key, self.vars)
except (NoOptionError, NoSectionError):
@@ -199,8 +218,13 @@ class ConfigDict(object):
class ConfigParser(RawConfigParser):
def get(self, section, option, raw=False, vars=None):
def get(
self,
section: str,
option: str,
raw: bool = False,
vars: Optional[dict] = None,
) -> object:
"""Get an option value for a given section.
All % interpolations are expanded in the return values, based on the
@@ -223,25 +247,24 @@ class ConfigParser(RawConfigParser):
d = ConfigDict(self, section, vars)
return self._interpolate(section, option, value, d)
def _interpolate(self, section, option, rawval, vars):
def _interpolate(self, section: str, option: str, rawval: object, vars: "ConfigDict"):
# do the string interpolation
value = rawval
depth = MAX_INTERPOLATION_DEPTH
while depth: # Loop through this until it's done
while depth: # Loop through this until it's done
depth -= 1
if "%(" in value:
try:
value = value % vars
except KeyError as e:
raise InterpolationMissingOptionError(
option, section, rawval, e.args[0])
raise InterpolationMissingOptionError(option, section, rawval, e.args[0])
else:
break
if value.find("%(") != -1:
raise InterpolationDepthError(option, section, rawval)
return value
def items(self, section, raw=False, vars=None):
def items(self, section: str, raw: bool = False, vars: Optional[dict] = None):
"""Return a list of tuples with (name, value) for each option
in the section.
@@ -269,40 +292,37 @@ class ConfigParser(RawConfigParser):
d = ConfigDict(self, section, vars)
if raw:
return [(option, d[option])
for option in options]
return [(option, d[option]) for option in options]
else:
return [(option, self._interpolate(section, option, d[option], d))
for option in options]
return [(option, self._interpolate(section, option, d[option], d)) for option in options]
class SafeConfigParser(ConfigParser):
_interpvar_re = re.compile(r"%\(([^)]+)\)s")
_badpercent_re = re.compile(r"%[^%]|%$")
def set(self, section, option, value):
if not isinstance(value, six.string_types):
def set(self, section: str, option: str, value: object) -> None:
if not isinstance(value, str):
raise TypeError("option values must be strings")
# check for bad percent signs:
# first, replace all "good" interpolations
tmp_value = self._interpvar_re.sub('', value)
tmp_value = self._interpvar_re.sub("", value)
# then, check if there's a lone percent sign left
m = self._badpercent_re.search(tmp_value)
if m:
raise ValueError("invalid interpolation syntax in %r at "
"position %d" % (value, m.start()))
raise ValueError("invalid interpolation syntax in %r at " "position %d" % (value, m.start()))
ConfigParser.set(self, section, option, value)
def _interpolate(self, section, option, rawval, vars):
def _interpolate(self, section: str, option: str, rawval: str, vars: ConfigDict):
# do the string interpolation
L = []
self._interpolate_some(option, L, rawval, section, vars, 1)
return ''.join(L)
return "".join(L)
_interpvar_match = re.compile(r"%\(([^)]+)\)s").match
def _interpolate_some(self, option, accum, rest, section, map, depth):
def _interpolate_some(self, option: str, accum: List[str], rest: str, section: str, map: ConfigDict, depth: int) -> None:
if depth > MAX_INTERPOLATION_DEPTH:
raise InterpolationDepthError(option, section, rest)
while rest:
@@ -323,18 +343,14 @@ class SafeConfigParser(ConfigParser):
if m is None:
raise InterpolationSyntaxError(option, section, "bad interpolation variable reference %r" % rest)
var = m.group(1)
rest = rest[m.end():]
rest = rest[m.end() :]
try:
v = map[var]
except KeyError:
raise InterpolationMissingOptionError(
option, section, rest, var)
raise InterpolationMissingOptionError(option, section, rest, var)
if "%" in v:
self._interpolate_some(option, accum, v,
section, map, depth + 1)
self._interpolate_some(option, accum, v, section, map, depth + 1)
else:
accum.append(v)
else:
raise InterpolationSyntaxError(
option, section,
"'%' must be followed by '%' or '(', found: " + repr(rest))
raise InterpolationSyntaxError(option, section, "'%' must be followed by '%' or '(', found: " + repr(rest))