srctools.keyvalues
Reads and parses Valve’s KeyValues files.
These files follow the following general format:
"Name"
{
"Name" "Value" // Comment
"Name"
{
"Name" "Value"
}
"Name" "Value"
"SecondName" "ps3-only value" [ps3]
"Third_Name" "never on Linux" [!linux]
"Name" "multi-line values
are supported like this.
They end with a quote."
}
The names are usually case-insensitive.
Call Keyvalues(name, value)
to get a keyvalues object, or Keyvalues.parse(file, 'filename')
to parse a file.
This will perform a round-trip file read:
>>> with open('filename.txt', 'r') as f:
... kv = Keyvalues.parse(f, 'filename.txt')
... with open('filename_2.txt', 'w') as f:
... for line in kv.export():
... f.write(line)
Keyvalue values
should be either a string, or a list of children Properties.
Names will be converted to lowercase automatically; use Prop.real_name to
obtain the original spelling. To allow multiple root blocks in a file, the
returned keyvalues from Keyvalues.parse() is special and will export with
un-indented children.
Properties with children can be indexed by their names, or by a (‘name’, default) tuple:
>>> kv = Keyvalues('Top', [
... Keyvalues('child1', '1'),
... Keyvalues('child2', '0'),
... ])
>>> kv['child1']
'1'
>>> kv['child3']
Traceback (most recent call last):
...
IndexError: No key child3!
>>> kv['child3', 'default']
'default'
>>> kv['child4', object()]
<object object at 0x...>
>>> del kv['child2']
>>> kv['child3'] = 'new value'
>>> kv
Keyvalues('Top', [Keyvalues('child1', '1'), Keyvalues('child3', 'new value')])
Handling \n, \t, \”, and \\ escape characters can be enabled.
-
exception
srctools.keyvalues.
KeyValError
() An error that occurred when parsing a Valve KeyValues file.
mess = The error message that occurred. file = The filename passed to Keyvalues.parse(), if it exists line_num = The line where the error occurred.
-
exception
srctools.keyvalues.
NoKeyError
(key: str) Raised if a key is not found when searching from find_key().
key = The missing key that was asked for.
-
class
srctools.keyvalues.
Keyvalues
() Represents Valve’s Keyvalues 1 file format.
Value should be a string (for leaf properties), or a list of children Keyvalues objects. The name should be a string, or None for a root object. Root objects export each child at the topmost indent level. This is produced from
Keyvalues.parse()
calls.-
property
name
: str Name automatically casefolds() any given names.
This ensures comparisons are always case-insensitive. Read .real_name to get the original value.
-
static
parse
(file_contents: Union[str, BaseTokenizer, Iterator[str]],) Keyvalues
filename: Union[str, _os.PathLike[str]] = '',
*,
flags: Mapping[str, bool] = srctools.EmptyMapping,
newline_keys: bool = False,
newline_values: bool = True,
allow_escapes: bool = True,
single_line: bool = False, Returns a Keyvalues tree parsed from given text.
Parameters: - file_contents – should be an iterable of strings or a single string. Alternatively, file_contents may be an already created tokenizer. In this case
allow_escapes
is ignored. - filename – If set this should be the source of the text for debug purposes. If not supplied,
file_contents.name
will be used if present. - flags – This should be a mapping for additional
[flag]
suffixes to accept. - allow_escapes – This allows choosing if
\t
or similar escapes are parsed. - single_line – If this is set, allow multiple properties to be on the same line. This means unterminated strings will be caught late (if at all), but it allows parsing some ‘internal’ data blocks.
- newline_keys – This specifies if newline characters are allowed in keys. Keys are prohibited by default, since this is fairly useless, but if quote characters are mismatched it’ll catch the mistake early.
- newline_values – This specifies if newline characters are allowed in string values.
- file_contents – should be an iterable of strings or a single string. Alternatively, file_contents may be an already created tokenizer. In this case
-
find_all
(*keys: str) Iterator[Keyvalues] Search through the tree, yielding all properties that match a particular path.
-
find_children
(*keys: str) Iterator[Keyvalues] Search through the tree, yielding children of properties in a path.
-
find_key
(key: str,) Keyvalues
def_: str = <object object>,
*,
or_blank: bool = False, Obtain the child Keyvalue with a given name.
- If no child is found with the given name, this will return the default value wrapped in a Keyvalue. If or_blank is set, it will be a blank block instead. If neither default is provided this will raise NoKeyError.
- This prefers keys located closer to the end of the value list.
-
find_block
(key: str, or_blank: bool = False) Keyvalues Obtain the child Keyvalue block with a given name.
- If no child is found with the given name and or_blank is true, a blank Keyvalue block will be returned. Otherwise NoKeyError will be raised.
- This prefers keys located closer to the end of the value list.
-
int
(key: str, def_: Union[int, T] = 0) Union[int, T] Return the value of an integer key.
Equivalent to int(prop[key]), but with a default value if missing or invalid. If multiple keys with the same name are present, this will use the last only.
-
float
(key: str, def_: Union[float, T] = 0.0) Union[float, T] Return the value of an integer key.
Equivalent to float(prop[key]), but with a default value if missing or invalid. If multiple keys with the same name are present, this will use the last only.
-
bool
(key: str, def_: Union[bool, T] = False) Union[bool, T] Return the value of an boolean key.
The value may be case-insensitively ‘true’, ‘false’, ‘1’, ‘0’, ‘T’, ‘F’, ‘y’, ‘n’, ‘yes’, or ‘no’. If multiple keys with the same name are present, this will use the last only.
-
vec
() Vec Return the given keyvalue, converted to a vector.
If multiple keys with the same name are present, this will use the last only.
-
set_key
() None Set the value of a key deep in the tree hierarchy.
- If any of the hierarchy do not exist (or do not have children), blank properties will be
- added automatically.
- path should be a tuple of names, or a single string.
-
as_dict
() Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Union[str, Dict[str, Any]]]]]]]]]]]]]]]]]] Convert this keyvalue tree into a tree of dictionaries.
This keeps only the last if multiple items have the same name.
-
as_array
(*, conv: ~typing.Callable[[str], ~srctools.keyvalues.T] = <class 'str'>,) Union[List[T], List[str]] Convert a keyvalue block into a list of values.
If the keyvalue is a single keyvalue, the single value will be yielded. Otherwise, each child must be a single value and each of those will be yielded. The name is ignored.
-
iter_tree
(blocks: bool = False) Iterator[Keyvalues] Iterate through all keyvalues in this tree.
This goes through keyvalues in the same order that they will serialise into. If blocks is True, the keyvalue blocks will be returned as well as keyvalues. If false, only keyvalues will be yielded.
-
append
() None Append another keyvalue to this one.
Deprecated behaviour: Accept an iterable of properties or a root keyvalue which are merged into this one.
-
extend
(other: Iterable[Keyvalues]) None Extend this keyvalue with the contents of another, or an iterable.
-
merge_children
(*names: str) None Merge together any children of ours with the given names.
After execution, this tree will have only one sub-Keyvalue for each of the given names. This ignores leaf Properties.
-
is_root
() bool Check if the keyvalue is a root, returned from the parse() method.
The root when exported produces its children, allowing multiple properties to be at the topmost indent level in a file.
-
export
() Iterator[str] Generate the set of strings for a keyvalues file.
Recursively calls itself for all child properties.
-
build
() _Builder Allows appending a tree to this keyvalue in a convenient way.
Use as follows:
# doctest: +NORMALIZE_WHITESPACE >>> kv = Keyvalues('name', []) >>> with kv.build() as builder: ... builder.root1('blah') ... builder.root2('blah') ... with builder.subprop: ... subprop = builder.config('value') ... builder['unusual name']('value') Keyvalues('root1', 'blah') Keyvalues('root2', 'blah') Keyvalues('unusual name', 'value') >>> print(subprop) # doctest: +NORMALIZE_WHITESPACE "config" "value" >>> print(''.join(kv.export())) # doctest: +NORMALIZE_WHITESPACE "name" { "root1" "blah" "root2" "blah" "subprop" { "config" "value" "unusual name" "value" } }
The return values/results of the context manager are the properties. Set names by
builder.name
,builder['name']
. For keywords append_
.Alternatively:
>>> with Keyvalues('name', []).build() as builder: ... builder.root1('blah') ... builder.root2('blah') Keyvalues('root1', 'blah') Keyvalues('root2', 'blah') >>> kv = builder() >>> print(repr(kv)) Keyvalues('name', [Keyvalues('root1', 'blah'), Keyvalues('root2', 'blah')])
-
property