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 read_file:
... kv = Keyvalues.parse(read_file, 'filename.txt')
... with open('filename_2.txt', 'w') as write_file:
... kv.serialise(write_file)
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.
See the base class
TokenSyntaxError
for available attributes.
- exception srctools.keyvalues.NoKeyError(key: str)
Raised if a key is not found when searching with
find_key()
,find_block()
, etc.
- exception srctools.keyvalues.LeafKeyvalueError( )
Raised when a method requiring a keyvalue block is run on a leaf keyvalue.
Leaf keyvalues only have a string value, so this operation is not valid.
- 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 value: str
Return the value of a leaf keyvalue.
- Deprecated:
Accessing the internal list for keyvalue blocks.
- property name: str
Produces a
str.casefold()
-ed version of the keyvalue’s name. Usually names are case-insensitive.Assigning to this automatically updates both this and
real_name
.- Deprecated:
‘Root’ keyvalues have a name of
None
. This will be replaced by a blank string, useis_root()
instead.
- property real_name: str
The original, case-sensitive version of this name.
Assigning to this automatically updates both this and
name
.- Deprecated:
‘Root’ keyvalues have a name of
None
. This will be replaced by a blank string, useis_root()
instead.
- classmethod root(
- *children: Keyvalues,
Return a new ‘root’ keyvalue. These have no name, and are returned from
parse()
.When serialised, their children are directly written with no indents, allowing multiple keyvalues blocks to exist on the topmost level.
- static parse(
- file_contents: str | BaseTokenizer | Iterator[str],
- filename: 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.
- find_all(
- *keys: str,
Search through the tree, yielding all properties that match a particular path.
- find_children(
- *keys: str,
Search through the tree, yielding children of properties in a path.
- find_key(
- key: str,
- 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 new
Keyvalue
. If or_blank is set, it will be a blank block instead. If neither default is provided this will raiseNoKeyError
.This prefers keys located closer to the end of the value list.
- find_block( ) 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 blankKeyvalues
block will be returned. Otherwise,NoKeyError
will be raised.This prefers keys located closer to the end of the value list.
- int( ) 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( ) 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( ) bool | T
Return the value of a 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() str | Dict[str, str | Dict[str, _As_Dict_Ret]]
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'>) 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,
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.
- 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. Direct leaf keyvalues will be left unchanged, even if they happen to match the given names.
- ensure_exists(
- key: str,
Ensure a Keyvalue block exists with this name, and return it.
- is_root() bool
Check if the keyvalue is a root, returned from the
parse()
orroot()
methods.See
root()
for more information.
- serialise( ) str | None
Serialise the keyvalues data to a file, or return as a string.
Recursive trees are not permitted.
- Parameters:
file – The file to write to. If omitted, the data is returned instead.
indent – The characters to use for each indentation.
indent_braces – If enabled, indent the braces to match the block contents, instead of the name.
- serialize( ) str | None
Serialise the keyvalues data to a file, or return as a string.
Recursive trees are not permitted.
- Parameters:
file – The file to write to. If omitted, the data is returned instead.
indent – The characters to use for each indentation.
indent_braces – If enabled, indent the braces to match the block contents, instead of the name.
- export() Iterator[str]
Generate the set of strings for a keyvalues file.
Recursively calls itself for all child properties.
- Deprecated:
Use
serialise()
instead.
- 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')])