# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/.
def read_ini(
fp,
defaults=None,
default="DEFAULT",
comments=None,
separators=None,
strict=True,
handle_defaults=True,
document=False,
add_line_no=False,
): """
read an .ini file andreturn a list of [(section, values)]
- fp : file pointer or path to read
- defaults : default set of variables
- default : name of the section for the default section
- comments : characters that if they start a line denote a comment
- separators : strings that denote key, value separation in order
- strict : whether to be strict about parsing
- handle_defaults : whether to incorporate defaults into each section
- add_line_no: whether to include the line number that points to the test in the generated ini file. """
# variables
defaults = defaults or {}
default_section = {}
comments = comments or ("#",)
separators = separators or ("=", ":")
sections = []
key = value = None
section_names = set() if isinstance(fp, str):
fp = io.open(fp, encoding="utf-8")
# read the lines
section = default
current_section = {}
current_section_name = ""
key_indent = 0 for linenum, line in enumerate(fp.read().splitlines(), start=1):
stripped = line.strip()
# ignore blank lines ifnot stripped: # reset key and value to avoid continuation lines
key = value = None continue
# ignore comment lines if any(stripped.startswith(c) for c in comments): continue
# strip inline comments (borrowed from configparser)
comment_start = sys.maxsize
inline_prefixes = {p: -1 for p in comments} while comment_start == sys.maxsize and inline_prefixes:
next_prefixes = {} for prefix, i in inline_prefixes.items():
index = stripped.find(prefix, i + 1) if index == -1: continue
next_prefixes[prefix] = index if index == 0 or (index > 0 and stripped[index - 1].isspace()):
comment_start = min(comment_start, index)
inline_prefixes = next_prefixes
if comment_start != sys.maxsize:
stripped = stripped[:comment_start].rstrip()
# check for a new section if len(stripped) > 2 and stripped[0] == "["and stripped[-1] == "]":
section = stripped[1:-1].strip()
key = value = None
key_indent = 0
# deal with DEFAULT section if section.lower() == default.lower(): if strict: assert default notin section_names
section_names.add(default)
current_section = default_section
current_section_name = "DEFAULT" continue
if strict: # make sure this section doesn't already exist assert (
section notin section_names
), "Section '%s' already found in '%s'" % (section, section_names)
# if there aren't any sections yet, something bad happen ifnot section_names: raise IniParseError(
fp,
linenum, "Expected a comment or section, ""instead found '{}'".format(stripped),
)
# continuation line ?
line_indent = len(line) - len(line.lstrip(" ")) if key and line_indent > key_indent:
value = "%s%s%s" % (value, os.linesep, stripped) if strict: # make sure the value doesn't contain assignments if" = "in value: raise IniParseError(
fp,
linenum, "Should not assign in {} condition for {}".format(
key, current_section_name
),
)
current_section[key] = value continue
# (key, value) pair for separator in separators: if separator in stripped:
key, value = stripped.split(separator, 1)
key = key.strip()
value = value.strip()
key_indent = line_indent
# make sure this key isn't already in the section if key: assert (
key notin current_section
), f"Found duplicate key {key} in section {section}"
if strict: # make sure this key isn't empty assert key # make sure the value doesn't contain assignments if" = "in value: raise IniParseError(
fp,
linenum, "Should not assign in {} condition for {}".format(
key, current_section_name
),
)
current_section[key] = value break else: # something bad happened! raise IniParseError(fp, linenum, "Unexpected line '{}'".format(stripped))
# merge global defaults with the DEFAULT section
defaults = combine_fields(defaults, default_section) if handle_defaults: # merge combined defaults into each section
sections = [(i, combine_fields(defaults, j)) for i, j in sections] return sections, defaults, None
def combine_fields(global_vars, local_vars): """
Combine the given manifest entries according to the semantics of specific fields.
This is used to combine manifest level defaults with a per-test definition. """ ifnot global_vars: return local_vars ifnot local_vars: return global_vars.copy()
field_patterns = { "args": "%s %s", "prefs": "%s %s", "skip-if": "%s\n%s", # consider implicit logical OR: "%s ||\n%s" "support-files": "%s %s", "tags": "%s %s",
}
final_mapping = global_vars.copy() for field_name, value in local_vars.items(): if field_name notin field_patterns or field_name notin global_vars:
final_mapping[field_name] = value continue
global_value = global_vars[field_name]
pattern = field_patterns[field_name]
final_mapping[field_name] = pattern % (global_value, value)
return final_mapping
Messung V0.5
¤ Dauer der Verarbeitung: 0.25 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.