Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
configparser.py1416 linesDownload Raw Back to Lib
1"""Configuration file parser.2 3A configuration file consists of sections, lead by a "[section]" header,4and followed by "name: value" entries, with continuations and such in5the style of RFC 822.6 7Intrinsic defaults can be specified by passing them into the8ConfigParser constructor as a dictionary.9 10class:11 12ConfigParser -- responsible for parsing a list of13                    configuration files, and managing the parsed database.14 15    methods:16 17    __init__(defaults=None, dict_type=_default_dict, allow_no_value=False,18             delimiters=('=', ':'), comment_prefixes=('#', ';'),19             inline_comment_prefixes=None, strict=True,20             empty_lines_in_values=True, default_section='DEFAULT',21             interpolation=<unset>, converters=<unset>,22             allow_unnamed_section=False):23        Create the parser. When `defaults` is given, it is initialized into the24        dictionary or intrinsic defaults. The keys must be strings, the values25        must be appropriate for %()s string interpolation.26 27        When `dict_type` is given, it will be used to create the dictionary28        objects for the list of sections, for the options within a section, and29        for the default values.30 31        When `delimiters` is given, it will be used as the set of substrings32        that divide keys from values.33 34        When `comment_prefixes` is given, it will be used as the set of35        substrings that prefix comments in empty lines. Comments can be36        indented.37 38        When `inline_comment_prefixes` is given, it will be used as the set of39        substrings that prefix comments in non-empty lines.40 41        When `strict` is True, the parser won't allow for any section or option42        duplicates while reading from a single source (file, string or43        dictionary). Default is True.44 45        When `empty_lines_in_values` is False (default: True), each empty line46        marks the end of an option. Otherwise, internal empty lines of47        a multiline option are kept as part of the value.48 49        When `allow_no_value` is True (default: False), options without50        values are accepted; the value presented for these is None.51 52        When `default_section` is given, the name of the special section is53        named accordingly. By default it is called ``"DEFAULT"`` but this can54        be customized to point to any other valid section name. Its current55        value can be retrieved using the ``parser_instance.default_section``56        attribute and may be modified at runtime.57 58        When `interpolation` is given, it should be an Interpolation subclass59        instance. It will be used as the handler for option value60        pre-processing when using getters. RawConfigParser objects don't do61        any sort of interpolation, whereas ConfigParser uses an instance of62        BasicInterpolation. The library also provides a ``zc.buildout``63        inspired ExtendedInterpolation implementation.64 65        When `converters` is given, it should be a dictionary where each key66        represents the name of a type converter and each value is a callable67        implementing the conversion from string to the desired datatype. Every68        converter gets its corresponding get*() method on the parser object and69        section proxies.70 71        When `allow_unnamed_section` is True (default: False), options72        without section are accepted: the section for these is73        ``configparser.UNNAMED_SECTION``.74 75    sections()76        Return all the configuration section names, sans DEFAULT.77 78    has_section(section)79        Return whether the given section exists.80 81    has_option(section, option)82        Return whether the given option exists in the given section.83 84    options(section)85        Return list of configuration options for the named section.86 87    read(filenames, encoding=None)88        Read and parse the iterable of named configuration files, given by89        name.  A single filename is also allowed.  Non-existing files90        are ignored.  Return list of successfully read files.91 92    read_file(f, filename=None)93        Read and parse one configuration file, given as a file object.94        The filename defaults to f.name; it is only used in error95        messages (if f has no `name` attribute, the string `<???>` is used).96 97    read_string(string)98        Read configuration from a given string.99 100    read_dict(dictionary)101        Read configuration from a dictionary. Keys are section names,102        values are dictionaries with keys and values that should be present103        in the section. If the used dictionary type preserves order, sections104        and their keys will be added in order. Values are automatically105        converted to strings.106 107    get(section, option, raw=False, vars=None, fallback=_UNSET)108        Return a string value for the named option.  All % interpolations are109        expanded in the return values, based on the defaults passed into the110        constructor and the DEFAULT section.  Additional substitutions may be111        provided using the `vars` argument, which must be a dictionary whose112        contents override any pre-existing defaults. If `option` is a key in113        `vars`, the value from `vars` is used.114 115    getint(section, options, raw=False, vars=None, fallback=_UNSET)116        Like get(), but convert value to an integer.117 118    getfloat(section, options, raw=False, vars=None, fallback=_UNSET)119        Like get(), but convert value to a float.120 121    getboolean(section, options, raw=False, vars=None, fallback=_UNSET)122        Like get(), but convert value to a boolean (currently case123        insensitively defined as 0, false, no, off for False, and 1, true,124        yes, on for True).  Returns False or True.125 126    items(section=_UNSET, raw=False, vars=None)127        If section is given, return a list of tuples with (name, value) for128        each option in the section. Otherwise, return a list of tuples with129        (section_name, section_proxy) for each section, including DEFAULTSECT.130 131    remove_section(section)132        Remove the given file section and all its options.133 134    remove_option(section, option)135        Remove the given option from the given section.136 137    set(section, option, value)138        Set the given option.139 140    write(fp, space_around_delimiters=True)141        Write the configuration state in .ini format. If142        `space_around_delimiters` is True (the default), delimiters143        between keys and values are surrounded by spaces.144"""145 146# Do not import dataclasses; overhead is unacceptable (gh-117703)147 148from collections.abc import Iterable, MutableMapping149from collections import ChainMap as _ChainMap150import contextlib151import functools152import io153import itertools154import os155import re156import sys157 158__all__ = ("NoSectionError", "DuplicateOptionError", "DuplicateSectionError",159           "NoOptionError", "InterpolationError", "InterpolationDepthError",160           "InterpolationMissingOptionError", "InterpolationSyntaxError",161           "ParsingError", "MissingSectionHeaderError",162           "MultilineContinuationError", "UnnamedSectionDisabledError",163           "InvalidWriteError", "ConfigParser", "RawConfigParser",164           "Interpolation", "BasicInterpolation",  "ExtendedInterpolation",165           "SectionProxy", "ConverterMapping",166           "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH", "UNNAMED_SECTION")167 168_default_dict = dict169DEFAULTSECT = "DEFAULT"170 171MAX_INTERPOLATION_DEPTH = 10172 173 174 175# exception classes176class Error(Exception):177    """Base class for ConfigParser exceptions."""178 179    def __init__(self, msg=''):180        self.message = msg181        Exception.__init__(self, msg)182 183    def __repr__(self):184        return self.message185 186    __str__ = __repr__187 188 189class NoSectionError(Error):190    """Raised when no section matches a requested option."""191 192    def __init__(self, section):193        Error.__init__(self, 'No section: %r' % (section,))194        self.section = section195        self.args = (section, )196 197 198class DuplicateSectionError(Error):199    """Raised when a section is repeated in an input source.200 201    Possible repetitions that raise this exception are: multiple creation202    using the API or in strict parsers when a section is found more than once203    in a single input file, string or dictionary.204    """205 206    def __init__(self, section, source=None, lineno=None):207        msg = [repr(section), " already exists"]208        if source is not None:209            message = ["While reading from ", repr(source)]210            if lineno is not None:211                message.append(" [line {0:2d}]".format(lineno))212            message.append(": section ")213            message.extend(msg)214            msg = message215        else:216            msg.insert(0, "Section ")217        Error.__init__(self, "".join(msg))218        self.section = section219        self.source = source220        self.lineno = lineno221        self.args = (section, source, lineno)222 223 224class DuplicateOptionError(Error):225    """Raised by strict parsers when an option is repeated in an input source.226 227    Current implementation raises this exception only when an option is found228    more than once in a single file, string or dictionary.229    """230 231    def __init__(self, section, option, source=None, lineno=None):232        msg = [repr(option), " in section ", repr(section),233               " already exists"]234        if source is not None:235            message = ["While reading from ", repr(source)]236            if lineno is not None:237                message.append(" [line {0:2d}]".format(lineno))238            message.append(": option ")239            message.extend(msg)240            msg = message241        else:242            msg.insert(0, "Option ")243        Error.__init__(self, "".join(msg))244        self.section = section245        self.option = option246        self.source = source247        self.lineno = lineno248        self.args = (section, option, source, lineno)249 250 251class NoOptionError(Error):252    """A requested option was not found."""253 254    def __init__(self, option, section):255        Error.__init__(self, "No option %r in section: %r" %256                       (option, section))257        self.option = option258        self.section = section259        self.args = (option, section)260 261 262class InterpolationError(Error):263    """Base class for interpolation-related exceptions."""264 265    def __init__(self, option, section, msg):266        Error.__init__(self, msg)267        self.option = option268        self.section = section269        self.args = (option, section, msg)270 271 272class InterpolationMissingOptionError(InterpolationError):273    """A string substitution required a setting which was not available."""274 275    def __init__(self, option, section, rawval, reference):276        msg = ("Bad value substitution: option {!r} in section {!r} contains "277               "an interpolation key {!r} which is not a valid option name. "278               "Raw value: {!r}".format(option, section, reference, rawval))279        InterpolationError.__init__(self, option, section, msg)280        self.reference = reference281        self.args = (option, section, rawval, reference)282 283 284class InterpolationSyntaxError(InterpolationError):285    """Raised when the source text contains invalid syntax.286 287    Current implementation raises this exception when the source text into288    which substitutions are made does not conform to the required syntax.289    """290 291 292class InterpolationDepthError(InterpolationError):293    """Raised when substitutions are nested too deeply."""294 295    def __init__(self, option, section, rawval):296        msg = ("Recursion limit exceeded in value substitution: option {!r} "297               "in section {!r} contains an interpolation key which "298               "cannot be substituted in {} steps. Raw value: {!r}"299               "".format(option, section, MAX_INTERPOLATION_DEPTH,300                         rawval))301        InterpolationError.__init__(self, option, section, msg)302        self.args = (option, section, rawval)303 304 305class ParsingError(Error):306    """Raised when a configuration file does not follow legal syntax."""307 308    def __init__(self, source, *args):309        super().__init__(f'Source contains parsing errors: {source!r}')310        self.source = source311        self.errors = []312        self.args = (source, )313        if args:314            self.append(*args)315 316    def append(self, lineno, line):317        self.errors.append((lineno, line))318        self.message += '\n\t[line %2d]: %s' % (lineno, repr(line))319 320    def combine(self, others):321        for other in others:322            for error in other.errors:323                self.append(*error)324        return self325 326    @staticmethod327    def _raise_all(exceptions: Iterable['ParsingError']):328        """329        Combine any number of ParsingErrors into one and raise it.330        """331        exceptions = iter(exceptions)332        with contextlib.suppress(StopIteration):333            raise next(exceptions).combine(exceptions)334 335 336 337class MissingSectionHeaderError(ParsingError):338    """Raised when a key-value pair is found before any section header."""339 340    def __init__(self, filename, lineno, line):341        Error.__init__(342            self,343            'File contains no section headers.\nfile: %r, line: %d\n%r' %344            (filename, lineno, line))345        self.source = filename346        self.lineno = lineno347        self.line = line348        self.args = (filename, lineno, line)349 350 351class MultilineContinuationError(ParsingError):352    """Raised when a key without value is followed by continuation line"""353    def __init__(self, filename, lineno, line):354        Error.__init__(355            self,356            "Key without value continued with an indented line.\n"357            "file: %r, line: %d\n%r"358            %(filename, lineno, line))359        self.source = filename360        self.lineno = lineno361        self.line = line362        self.args = (filename, lineno, line)363 364 365class UnnamedSectionDisabledError(Error):366    """Raised when an attempt to use UNNAMED_SECTION is made with the367    feature disabled."""368    def __init__(self):369        Error.__init__(self, "Support for UNNAMED_SECTION is disabled.")370 371 372class _UnnamedSection:373 374    def __repr__(self):375        return "<UNNAMED_SECTION>"376 377class InvalidWriteError(Error):378    """Raised when attempting to write data that the parser would read back differently.379    ex: writing a key which begins with the section header pattern would read back as a380    new section """381 382    def __init__(self, msg=''):383        Error.__init__(self, msg)384 385 386UNNAMED_SECTION = _UnnamedSection()387 388 389# Used in parser getters to indicate the default behaviour when a specific390# option is not found it to raise an exception. Created to enable `None` as391# a valid fallback value.392_UNSET = object()393 394 395class Interpolation:396    """Dummy interpolation that passes the value through with no changes."""397 398    def before_get(self, parser, section, option, value, defaults):399        return value400 401    def before_set(self, parser, section, option, value):402        return value403 404    def before_read(self, parser, section, option, value):405        return value406 407    def before_write(self, parser, section, option, value):408        return value409 410 411class BasicInterpolation(Interpolation):412    """Interpolation as implemented in the classic ConfigParser.413 414    The option values can contain format strings which refer to other values in415    the same section, or values in the special default section.416 417    For example:418 419        something: %(dir)s/whatever420 421    would resolve the "%(dir)s" to the value of dir.  All reference422    expansions are done late, on demand. If a user needs to use a bare % in423    a configuration file, she can escape it by writing %%. Other % usage424    is considered a user error and raises `InterpolationSyntaxError`."""425 426    _KEYCRE = re.compile(r"%\(([^)]+)\)s")427 428    def before_get(self, parser, section, option, value, defaults):429        L = []430        self._interpolate_some(parser, option, L, value, section, defaults, 1)431        return ''.join(L)432 433    def before_set(self, parser, section, option, value):434        tmp_value = value.replace('%%', '') # escaped percent signs435        tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax436        if '%' in tmp_value:437            raise ValueError("invalid interpolation syntax in %r at "438                             "position %d" % (value, tmp_value.find('%')))439        return value440 441    def _interpolate_some(self, parser, option, accum, rest, section, map,442                          depth):443        rawval = parser.get(section, option, raw=True, fallback=rest)444        if depth > MAX_INTERPOLATION_DEPTH:445            raise InterpolationDepthError(option, section, rawval)446        while rest:447            p = rest.find("%")448            if p < 0:449                accum.append(rest)450                return451            if p > 0:452                accum.append(rest[:p])453                rest = rest[p:]454            # p is no longer used455            c = rest[1:2]456            if c == "%":457                accum.append("%")458                rest = rest[2:]459            elif c == "(":460                m = self._KEYCRE.match(rest)461                if m is None:462                    raise InterpolationSyntaxError(option, section,463                        "bad interpolation variable reference %r" % rest)464                var = parser.optionxform(m.group(1))465                rest = rest[m.end():]466                try:467                    v = map[var]468                except KeyError:469                    raise InterpolationMissingOptionError(470                        option, section, rawval, var) from None471                if "%" in v:472                    self._interpolate_some(parser, option, accum, v,473                                           section, map, depth + 1)474                else:475                    accum.append(v)476            else:477                raise InterpolationSyntaxError(478                    option, section,479                    "'%%' must be followed by '%%' or '(', "480                    "found: %r" % (rest,))481 482 483class ExtendedInterpolation(Interpolation):484    """Advanced variant of interpolation, supports the syntax used by485    `zc.buildout`. Enables interpolation between sections."""486 487    _KEYCRE = re.compile(r"\$\{([^}]+)\}")488 489    def before_get(self, parser, section, option, value, defaults):490        L = []491        self._interpolate_some(parser, option, L, value, section, defaults, 1)492        return ''.join(L)493 494    def before_set(self, parser, section, option, value):495        tmp_value = value.replace('$$', '') # escaped dollar signs496        tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax497        if '$' in tmp_value:498            raise ValueError("invalid interpolation syntax in %r at "499                             "position %d" % (value, tmp_value.find('$')))500        return value501 502    def _interpolate_some(self, parser, option, accum, rest, section, map,503                          depth):504        rawval = parser.get(section, option, raw=True, fallback=rest)505        if depth > MAX_INTERPOLATION_DEPTH:506            raise InterpolationDepthError(option, section, rawval)507        while rest:508            p = rest.find("$")509            if p < 0:510                accum.append(rest)511                return512            if p > 0:513                accum.append(rest[:p])514                rest = rest[p:]515            # p is no longer used516            c = rest[1:2]517            if c == "$":518                accum.append("$")519                rest = rest[2:]520            elif c == "{":521                m = self._KEYCRE.match(rest)522                if m is None:523                    raise InterpolationSyntaxError(option, section,524                        "bad interpolation variable reference %r" % rest)525                path = m.group(1).split(':')526                rest = rest[m.end():]527                sect = section528                opt = option529                try:530                    if len(path) == 1:531                        opt = parser.optionxform(path[0])532                        v = map[opt]533                    elif len(path) == 2:534                        sect = path[0]535                        opt = parser.optionxform(path[1])536                        v = parser.get(sect, opt, raw=True)537                    else:538                        raise InterpolationSyntaxError(539                            option, section,540                            "More than one ':' found: %r" % (rest,))541                except (KeyError, NoSectionError, NoOptionError):542                    raise InterpolationMissingOptionError(543                        option, section, rawval, ":".join(path)) from None544                if v is None:545                    continue546                if "$" in v:547                    self._interpolate_some(parser, opt, accum, v, sect,548                                           dict(parser.items(sect, raw=True)),549                                           depth + 1)550                else:551                    accum.append(v)552            else:553                raise InterpolationSyntaxError(554                    option, section,555                    "'$' must be followed by '$' or '{', "556                    "found: %r" % (rest,))557 558 559class _ReadState:560    elements_added : set[str]561    cursect : dict[str, str] | None = None562    sectname : str | None = None563    optname : str | None = None564    lineno : int = 0565    indent_level : int = 0566    errors : list[ParsingError]567 568    def __init__(self):569        self.elements_added = set()570        self.errors = list()571 572 573class _Line(str):574    __slots__ = 'clean', 'has_comments'575 576    def __new__(cls, val, *args, **kwargs):577        return super().__new__(cls, val)578 579    def __init__(self, val, comments):580        trimmed = val.strip()581        self.clean = comments.strip(trimmed)582        self.has_comments = trimmed != self.clean583 584 585class _CommentSpec:586    def __init__(self, full_prefixes, inline_prefixes):587        full_patterns = (588            # prefix at the beginning of a line589            fr'^({re.escape(prefix)}).*'590            for prefix in full_prefixes591        )592        inline_patterns = (593            # prefix at the beginning of the line or following a space594            fr'(^|\s)({re.escape(prefix)}.*)'595            for prefix in inline_prefixes596        )597        self.pattern = re.compile('|'.join(itertools.chain(full_patterns, inline_patterns)))598 599    def strip(self, text):600        return self.pattern.sub('', text).rstrip()601 602    def wrap(self, text):603        return _Line(text, self)604 605 606class RawConfigParser(MutableMapping):607    """ConfigParser that does not do interpolation."""608 609    # Regular expressions for parsing section headers and options610    _SECT_TMPL = r"""611        \[                                 # [612        (?P<header>.+)                     # very permissive!613        \]                                 # ]614        """615    _OPT_TMPL = r"""616        (?P<option>.*?)                    # very permissive!617        \s*(?P<vi>{delim})\s*              # any number of space/tab,618                                           # followed by any of the619                                           # allowed delimiters,620                                           # followed by any space/tab621        (?P<value>.*)$                     # everything up to eol622        """623    _OPT_NV_TMPL = r"""624        (?P<option>.*?)                    # very permissive!625        \s*(?:                             # any number of space/tab,626        (?P<vi>{delim})\s*                 # optionally followed by627                                           # any of the allowed628                                           # delimiters, followed by any629                                           # space/tab630        (?P<value>.*))?$                   # everything up to eol631        """632    # Interpolation algorithm to be used if the user does not specify another633    _DEFAULT_INTERPOLATION = Interpolation()634    # Compiled regular expression for matching sections635    SECTCRE = re.compile(_SECT_TMPL, re.VERBOSE)636    # Compiled regular expression for matching options with typical separators637    OPTCRE = re.compile(_OPT_TMPL.format(delim="=|:"), re.VERBOSE)638    # Compiled regular expression for matching options with optional values639    # delimited using typical separators640    OPTCRE_NV = re.compile(_OPT_NV_TMPL.format(delim="=|:"), re.VERBOSE)641    # Compiled regular expression for matching leading whitespace in a line642    NONSPACECRE = re.compile(r"\S")643    # Possible boolean values in the configuration.644    BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True,645                      '0': False, 'no': False, 'false': False, 'off': False}646 647    def __init__(self, defaults=None, dict_type=_default_dict,648                 allow_no_value=False, *, delimiters=('=', ':'),649                 comment_prefixes=('#', ';'), inline_comment_prefixes=None,650                 strict=True, empty_lines_in_values=True,651                 default_section=DEFAULTSECT,652                 interpolation=_UNSET, converters=_UNSET,653                 allow_unnamed_section=False,):654 655        self._dict = dict_type656        self._sections = self._dict()657        self._defaults = self._dict()658        self._converters = ConverterMapping(self)659        self._proxies = self._dict()660        self._proxies[default_section] = SectionProxy(self, default_section)661        self._delimiters = tuple(delimiters)662        if delimiters == ('=', ':'):663            self._optcre = self.OPTCRE_NV if allow_no_value else self.OPTCRE664        else:665            d = "|".join(re.escape(d) for d in delimiters)666            if allow_no_value:667                self._optcre = re.compile(self._OPT_NV_TMPL.format(delim=d),668                                          re.VERBOSE)669            else:670                self._optcre = re.compile(self._OPT_TMPL.format(delim=d),671                                          re.VERBOSE)672        self._comments = _CommentSpec(comment_prefixes or (), inline_comment_prefixes or ())673        self._strict = strict674        self._allow_no_value = allow_no_value675        self._empty_lines_in_values = empty_lines_in_values676        self.default_section=default_section677        self._interpolation = interpolation678        if self._interpolation is _UNSET:679            self._interpolation = self._DEFAULT_INTERPOLATION680        if self._interpolation is None:681            self._interpolation = Interpolation()682        if not isinstance(self._interpolation, Interpolation):683            raise TypeError(684                f"interpolation= must be None or an instance of Interpolation;"685                f" got an object of type {type(self._interpolation)}"686            )687        if converters is not _UNSET:688            self._converters.update(converters)689        if defaults:690            self._read_defaults(defaults)691        self._allow_unnamed_section = allow_unnamed_section692 693    def defaults(self):694        return self._defaults695 696    def sections(self):697        """Return a list of section names, excluding [DEFAULT]"""698        # self._sections will never have [DEFAULT] in it699        return list(self._sections.keys())700 701    def add_section(self, section):702        """Create a new section in the configuration.703 704        Raise DuplicateSectionError if a section by the specified name705        already exists. Raise ValueError if name is DEFAULT.706        """707        if section == self.default_section:708            raise ValueError('Invalid section name: %r' % section)709 710        if section is UNNAMED_SECTION:711            if not self._allow_unnamed_section:712                raise UnnamedSectionDisabledError713 714        if section in self._sections:715            raise DuplicateSectionError(section)716        self._sections[section] = self._dict()717        self._proxies[section] = SectionProxy(self, section)718 719    def has_section(self, section):720        """Indicate whether the named section is present in the configuration.721 722        The DEFAULT section is not acknowledged.723        """724        return section in self._sections725 726    def options(self, section):727        """Return a list of option names for the given section name."""728        try:729            opts = self._sections[section].copy()730        except KeyError:731            raise NoSectionError(section) from None732        opts.update(self._defaults)733        return list(opts.keys())734 735    def read(self, filenames, encoding=None):736        """Read and parse a filename or an iterable of filenames.737 738        Files that cannot be opened are silently ignored; this is739        designed so that you can specify an iterable of potential740        configuration file locations (e.g. current directory, user's741        home directory, systemwide directory), and all existing742        configuration files in the iterable will be read.  A single743        filename may also be given.744 745        Return list of successfully read files.746        """747        if isinstance(filenames, (str, bytes, os.PathLike)):748            filenames = [filenames]749        encoding = io.text_encoding(encoding)750        read_ok = []751        for filename in filenames:752            try:753                with open(filename, encoding=encoding) as fp:754                    self._read(fp, filename)755            except OSError:756                continue757            if isinstance(filename, os.PathLike):758                filename = os.fspath(filename)759            read_ok.append(filename)760        return read_ok761 762    def read_file(self, f, source=None):763        """Like read() but the argument must be a file-like object.764 765        The `f` argument must be iterable, returning one line at a time.766        Optional second argument is the `source` specifying the name of the767        file being read. If not given, it is taken from f.name. If `f` has no768        `name` attribute, `<???>` is used.769        """770        if source is None:771            try:772                source = f.name773            except AttributeError:774                source = '<???>'775        self._read(f, source)776 777    def read_string(self, string, source='<string>'):778        """Read configuration from a given string."""779        sfile = io.StringIO(string)780        self.read_file(sfile, source)781 782    def read_dict(self, dictionary, source='<dict>'):783        """Read configuration from a dictionary.784 785        Keys are section names, values are dictionaries with keys and values786        that should be present in the section. If the used dictionary type787        preserves order, sections and their keys will be added in order.788 789        All types held in the dictionary are converted to strings during790        reading, including section names, option names and keys.791 792        Optional second argument is the `source` specifying the name of the793        dictionary being read.794        """795        elements_added = set()796        for section, keys in dictionary.items():797            if section is not UNNAMED_SECTION:798                section = str(section)799            try:800                self.add_section(section)801            except (DuplicateSectionError, ValueError):802                if self._strict and section in elements_added:803                    raise804            elements_added.add(section)805            for key, value in keys.items():806                key = self.optionxform(str(key))807                if value is not None:808                    value = str(value)809                if self._strict and (section, key) in elements_added:810                    raise DuplicateOptionError(section, key, source)811                elements_added.add((section, key))812                self.set(section, key, value)813 814    def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET):815        """Get an option value for a given section.816 817        If `vars` is provided, it must be a dictionary. The option is looked up818        in `vars` (if provided), `section`, and in `DEFAULTSECT` in that order.819        If the key is not found and `fallback` is provided, it is used as820        a fallback value. `None` can be provided as a `fallback` value.821 822        If interpolation is enabled and the optional argument `raw` is False,823        all interpolations are expanded in the return values.824 825        Arguments `raw`, `vars`, and `fallback` are keyword only.826 827        The section DEFAULT is special.828        """829        try:830            d = self._unify_values(section, vars)831        except NoSectionError:832            if fallback is _UNSET:833                raise834            else:835                return fallback836        option = self.optionxform(option)837        try:838            value = d[option]839        except KeyError:840            if fallback is _UNSET:841                raise NoOptionError(option, section)842            else:843                return fallback844 845        if raw or value is None:846            return value847        else:848            return self._interpolation.before_get(self, section, option, value,849                                                  d)850 851    def _get(self, section, conv, option, **kwargs):852        return conv(self.get(section, option, **kwargs))853 854    def _get_conv(self, section, option, conv, *, raw=False, vars=None,855                  fallback=_UNSET, **kwargs):856        try:857            return self._get(section, conv, option, raw=raw, vars=vars,858                             **kwargs)859        except (NoSectionError, NoOptionError):860            if fallback is _UNSET:861                raise862            return fallback863 864    # getint, getfloat and getboolean provided directly for backwards compat865    def getint(self, section, option, *, raw=False, vars=None,866               fallback=_UNSET, **kwargs):867        return self._get_conv(section, option, int, raw=raw, vars=vars,868                              fallback=fallback, **kwargs)869 870    def getfloat(self, section, option, *, raw=False, vars=None,871                 fallback=_UNSET, **kwargs):872        return self._get_conv(section, option, float, raw=raw, vars=vars,873                              fallback=fallback, **kwargs)874 875    def getboolean(self, section, option, *, raw=False, vars=None,876                   fallback=_UNSET, **kwargs):877        return self._get_conv(section, option, self._convert_to_boolean,878                              raw=raw, vars=vars, fallback=fallback, **kwargs)879 880    def items(self, section=_UNSET, raw=False, vars=None):881        """Return a list of (name, value) tuples for each option in a section.882 883        All % interpolations are expanded in the return values, based on the884        defaults passed into the constructor, unless the optional argument885        `raw` is true.  Additional substitutions may be provided using the886        `vars` argument, which must be a dictionary whose contents overrides887        any pre-existing defaults.888 889        The section DEFAULT is special.890        """891        if section is _UNSET:892            return super().items()893        d = self._defaults.copy()894        try:895            d.update(self._sections[section])896        except KeyError:897            if section != self.default_section:898                raise NoSectionError(section)899        orig_keys = list(d.keys())900        # Update with the entry specific variables901        if vars:902            for key, value in vars.items():903                d[self.optionxform(key)] = value904        value_getter = lambda option: self._interpolation.before_get(self,905            section, option, d[option], d)906        if raw:907            value_getter = lambda option: d[option]908        return [(option, value_getter(option)) for option in orig_keys]909 910    def popitem(self):911        """Remove a section from the parser and return it as912        a (section_name, section_proxy) tuple. If no section is present, raise913        KeyError.914 915        The section DEFAULT is never returned because it cannot be removed.916        """917        for key in self.sections():918            value = self[key]919            del self[key]920            return key, value921        raise KeyError922 923    def optionxform(self, optionstr):924        return optionstr.lower()925 926    def has_option(self, section, option):927        """Check for the existence of a given option in a given section.928        If the specified `section` is None or an empty string, DEFAULT is929        assumed. If the specified `section` does not exist, returns False."""930        if not section or section == self.default_section:931            option = self.optionxform(option)932            return option in self._defaults933        elif section not in self._sections:934            return False935        else:936            option = self.optionxform(option)937            return (option in self._sections[section]938                    or option in self._defaults)939 940    def set(self, section, option, value=None):941        """Set an option."""942        if value:943            value = self._interpolation.before_set(self, section, option,944                                                   value)945        if not section or section == self.default_section:946            sectdict = self._defaults947        else:948            try:949                sectdict = self._sections[section]950            except KeyError:951                raise NoSectionError(section) from None952        sectdict[self.optionxform(option)] = value953 954    def write(self, fp, space_around_delimiters=True):955        """Write an .ini-format representation of the configuration state.956 957        If `space_around_delimiters` is True (the default), delimiters958        between keys and values are surrounded by spaces.959 960        Please note that comments in the original configuration file are not961        preserved when writing the configuration back.962        """963        if space_around_delimiters:964            d = " {} ".format(self._delimiters[0])965        else:966            d = self._delimiters[0]967        if self._defaults:968            self._write_section(fp, self.default_section,969                                    self._defaults.items(), d)970        if UNNAMED_SECTION in self._sections and self._sections[UNNAMED_SECTION]:971            self._write_section(fp, UNNAMED_SECTION, self._sections[UNNAMED_SECTION].items(), d, unnamed=True)972 973        for section in self._sections:974            if section is UNNAMED_SECTION:975                continue976            self._write_section(fp, section,977                                self._sections[section].items(), d)978 979    def _write_section(self, fp, section_name, section_items, delimiter, unnamed=False):980        """Write a single section to the specified 'fp'."""981        if not unnamed:982            fp.write("[{}]\n".format(section_name))983        for key, value in section_items:984            self._validate_key_contents(key)985            value = self._interpolation.before_write(self, section_name, key,986                                                     value)987            if value is not None or not self._allow_no_value:988                value = delimiter + str(value).replace('\n', '\n\t')989            else:990                value = ""991            fp.write("{}{}\n".format(key, value))992        fp.write("\n")993 994    def remove_option(self, section, option):995        """Remove an option."""996        if not section or section == self.default_section:997            sectdict = self._defaults998        else:999            try:1000                sectdict = self._sections[section]1001            except KeyError:1002                raise NoSectionError(section) from None1003        option = self.optionxform(option)1004        existed = option in sectdict1005        if existed:1006            del sectdict[option]1007        return existed1008 1009    def remove_section(self, section):1010        """Remove a file section."""1011        existed = section in self._sections1012        if existed:1013            del self._sections[section]1014            del self._proxies[section]1015        return existed1016 1017    def __getitem__(self, key):1018        if key != self.default_section and not self.has_section(key):1019            raise KeyError(key)1020        return self._proxies[key]1021 1022    def __setitem__(self, key, value):1023        # To conform with the mapping protocol, overwrites existing values in1024        # the section.1025        if key in self and self[key] is value:1026            return1027        # XXX this is not atomic if read_dict fails at any point. Then again,1028        # no update method in configparser is atomic in this implementation.1029        if key == self.default_section:1030            self._defaults.clear()1031        elif key in self._sections:1032            self._sections[key].clear()1033        self.read_dict({key: value})1034 1035    def __delitem__(self, key):1036        if key == self.default_section:1037            raise ValueError("Cannot remove the default section.")1038        if not self.has_section(key):1039            raise KeyError(key)1040        self.remove_section(key)1041 1042    def __contains__(self, key):1043        return key == self.default_section or self.has_section(key)1044 1045    def __len__(self):1046        return len(self._sections) + 1 # the default section1047 1048    def __iter__(self):1049        # XXX does it break when underlying container state changed?1050        return itertools.chain((self.default_section,), self._sections.keys())1051 1052    def _read(self, fp, fpname):1053        """Parse a sectioned configuration file.1054 1055        Each section in a configuration file contains a header, indicated by1056        a name in square brackets (`[]`), plus key/value options, indicated by1057        `name` and `value` delimited with a specific substring (`=` or `:` by1058        default).1059 1060        Values can span multiple lines, as long as they are indented deeper1061        than the first line of the value. Depending on the parser's mode, blank1062        lines may be treated as parts of multiline values or ignored.1063 1064        Configuration files may include comments, prefixed by specific1065        characters (`#` and `;` by default). Comments may appear on their own1066        in an otherwise empty line or may be entered in lines holding values or1067        section names. Please note that comments get stripped off when reading configuration files.1068        """1069        try:1070            ParsingError._raise_all(self._read_inner(fp, fpname))1071        finally:1072            self._join_multiline_values()1073 1074    def _read_inner(self, fp, fpname):1075        st = _ReadState()1076 1077        for st.lineno, line in enumerate(map(self._comments.wrap, fp), start=1):1078            if not line.clean:1079                if self._empty_lines_in_values:1080                    # add empty line to the value, but only if there was no1081                    # comment on the line1082                    if (not line.has_comments and1083                        st.cursect is not None and1084                        st.optname and1085                        st.cursect[st.optname] is not None):1086                        st.cursect[st.optname].append('') # newlines added at join1087                else:1088                    # empty line marks end of value1089                    st.indent_level = sys.maxsize1090                continue1091 1092            first_nonspace = self.NONSPACECRE.search(line)1093            st.cur_indent_level = first_nonspace.start() if first_nonspace else 01094 1095            if self._handle_continuation_line(st, line, fpname):1096                continue1097 1098            self._handle_rest(st, line, fpname)1099 1100        return st.errors1101 1102    def _handle_continuation_line(self, st, line, fpname):1103        # continuation line?1104        is_continue = (st.cursect is not None and st.optname and1105            st.cur_indent_level > st.indent_level)1106        if is_continue:1107            if st.cursect[st.optname] is None:1108                raise MultilineContinuationError(fpname, st.lineno, line)1109            st.cursect[st.optname].append(line.clean)1110        return is_continue1111 1112    def _handle_rest(self, st, line, fpname):1113        # a section header or option header?1114        if self._allow_unnamed_section and st.cursect is None:1115            self._handle_header(st, UNNAMED_SECTION, fpname)1116 1117        st.indent_level = st.cur_indent_level1118        # is it a section header?1119        mo = self.SECTCRE.match(line.clean)1120 1121        if not mo and st.cursect is None:1122            raise MissingSectionHeaderError(fpname, st.lineno, line)1123 1124        self._handle_header(st, mo.group('header'), fpname) if mo else self._handle_option(st, line, fpname)1125 1126    def _handle_header(self, st, sectname, fpname):1127        st.sectname = sectname1128        if st.sectname in self._sections:1129            if self._strict and st.sectname in st.elements_added:1130                raise DuplicateSectionError(st.sectname, fpname,1131                                            st.lineno)1132            st.cursect = self._sections[st.sectname]1133            st.elements_added.add(st.sectname)1134        elif st.sectname == self.default_section:1135            st.cursect = self._defaults1136        else:1137            st.cursect = self._dict()1138            self._sections[st.sectname] = st.cursect1139            self._proxies[st.sectname] = SectionProxy(self, st.sectname)1140            st.elements_added.add(st.sectname)1141        # So sections can't start with a continuation line1142        st.optname = None1143 1144    def _handle_option(self, st, line, fpname):1145        # an option line?1146        st.indent_level = st.cur_indent_level1147 1148        mo = self._optcre.match(line.clean)1149        if not mo:1150            # a non-fatal parsing error occurred. set up the1151            # exception but keep going. the exception will be1152            # raised at the end of the file and will contain a1153            # list of all bogus lines1154            st.errors.append(ParsingError(fpname, st.lineno, line))1155            return1156 1157        st.optname, vi, optval = mo.group('option', 'vi', 'value')1158        if not st.optname:1159            st.errors.append(ParsingError(fpname, st.lineno, line))1160        st.optname = self.optionxform(st.optname.rstrip())1161        if (self._strict and1162            (st.sectname, st.optname) in st.elements_added):1163            raise DuplicateOptionError(st.sectname, st.optname,1164                                    fpname, st.lineno)1165        st.elements_added.add((st.sectname, st.optname))1166        # This check is fine because the OPTCRE cannot1167        # match if it would set optval to None1168        if optval is not None:1169            optval = optval.strip()1170            st.cursect[st.optname] = [optval]1171        else:1172            # valueless option handling1173            st.cursect[st.optname] = None1174 1175    def _join_multiline_values(self):1176        defaults = self.default_section, self._defaults1177        all_sections = itertools.chain((defaults,),1178                                       self._sections.items())1179        for section, options in all_sections:1180            for name, val in options.items():1181                if isinstance(val, list):1182                    val = '\n'.join(val).rstrip()1183                options[name] = self._interpolation.before_read(self,1184                                                                section,1185                                                                name, val)1186 1187    def _read_defaults(self, defaults):1188        """Read the defaults passed in the initializer.1189        Note: values can be non-string."""1190        for key, value in defaults.items():1191            self._defaults[self.optionxform(key)] = value1192 1193    def _unify_values(self, section, vars):1194        """Create a sequence of lookups with 'vars' taking priority over1195        the 'section' which takes priority over the DEFAULTSECT.1196 1197        """1198        sectiondict = {}1199        try:1200            sectiondict = self._sections[section]

Showing the first 1,200 of 1416 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai