ksconf.conf package


ksconf.conf.delta module

class ksconf.conf.delta.DiffGlobal(type)

Bases: tuple


Alias for field number 0

class ksconf.conf.delta.DiffHeader(name, mtime=None)

Bases: object

class ksconf.conf.delta.DiffOp(tag, location, a, b)

Bases: tuple


Alias for field number 2


Alias for field number 3


Alias for field number 1


Alias for field number 0

class ksconf.conf.delta.DiffStanza(type, stanza)

Bases: tuple


Alias for field number 1


Alias for field number 0

class ksconf.conf.delta.DiffStzKey(type, stanza, key)

Bases: tuple


Alias for field number 2


Alias for field number 1


Alias for field number 0

ksconf.conf.delta.compare_cfgs(a, b, replace_level='global')

Calculate a set of deltas which describes how to transform a into b.

  • a (dict) – the first/original configuration entity
  • b (dict) – the second/target configuration entity
  • replace_level (str: global, stanza, or key) –

    The highest level ‘replace’ event that can be returned. Acceptable values are global, stanza, and key. These examples may help:

    • Using ‘global’ with identical inputs will report a single global-level equal op.
    • Using ‘stanza’ with identical inputs will return all stanzas as equal.
    • Using ‘key’ will ensure that two stanzas with no common keys will be reported in terms of key changes. Whereas ‘global’ or ‘stanza’ would result in a single giant replace op.

a sequence of differences in tuples

Return type:



The DiffOp output idea was borrowed from SequenceMatcher class in the difflib in the standard Python module.

This function returns a sequence of 5 element tuples describing the transformation based on the detail level specified in replace_level.

Each DiffOp (named tuple) takes the form:

(tag, location, a, b)


Value Meaning
‘replace’ same element in both, but different values.
‘delete’ remove value b
‘insert’ insert value a
‘equal’ same values in both

location is a namedtuple that can take the following forms:

Tuple form Type Description
(“global”) DiffGlobal Global file level context (e.g., both files are the same)
(“stanza”, stanza) DiffStanza Stanzas are the same, or completely different (no shared keys)
(“key”, stanza, key) DiffStzKey Key level change

Changed in version v0.8.8: The preserve_empty argument was origionally introduced to preserve backwards compatibility, but it ended up introducing new bugs. Additionally, no use cases were found where better to automatically discarding empty stanzas.

Changed in version v0.8.8: The allow_level0 argument was replaced with replace_level. Instead of using allow_level0=False use replace_level="stanza". At the same time an new feature was added to support replace_level="key". The default behavior remains the same.

ksconf.conf.delta.compare_stanzas(a, b, stanza_name, replace_level='global')
Parameters:replace_level (bool) – If a and b have no common keys, is a single stanza-level ‘replace’ is issue unless replace_level="key"

Is the delta output show that the compared objects are identical

ksconf.conf.delta.reduce_stanza(stanza, keep_attrs)

Pre-process a stanzas so that only a common set of keys will be compared.

  • stanza (dict) – Stanzas containing attributes and values
  • keep_attrs ((list, set, tuple, dict)) – Listing of attributes to preserve

a reduced copy of stanza.

ksconf.conf.delta.show_diff(stream, diffs, headers=None)
ksconf.conf.delta.show_text_diff(stream, a, b)
ksconf.conf.delta.summarize_cfg_diffs(delta, stream)

Summarize a delta into a human readable format. The input delta is in the format produced by the compare_cfgs() function.

ksconf.conf.delta.write_diff_as_json(delta, stream, **dump_args)

ksconf.conf.merge module

ksconf.conf.merge.merge_app_local(app_folder, cleanup=True)

Find everything in local, if it has a corresponding file in default, merge. This function assumes standard Splunk app path names.

ksconf.conf.merge.merge_conf_files(dest, configs, dry_run=False, banner_comment=None)
ksconf.conf.merge.merge_update_any_file(dest, sources, remove_source=False)
ksconf.conf.merge.merge_update_conf_file(dest, sources, remove_source=False)

Dest is treated as both the output, and the highest priority source.

ksconf.conf.meta module

Incomplete documentation available here:


Specifically, attribute-level ACls aren’t discussed nor is the magic “import” directive.


0 - global (or 1 stanza=”default”) 1 - conf 2 - stanzas 3 - attribute
class ksconf.conf.meta.MetaData

Bases: object

static expand_layers(layers)
Parameters:layers (list(dict)) – layer of stanzas, starting with the global ending with conf/stanza/attr
Returns:Expanded layer
Return type:dict


classmethod parse_meta(stanza)

Split out the values of ‘access’ (maybe more someday) :param stanza: content of a meta stanza :return: extended meta data :rtype: dict

regex_access = '(?:^|\\s*,\\s*)(?P<action>read|write)\\s*:\\s*\\[\\s*(?P<roles>[^\\]]+?)\\s*\\]'
write_stream(stream, sort=True)
class ksconf.conf.meta.MetaLayer(name)

Bases: object


Helpful when rebuilding the input file.

update(*args, **kwargs)

ksconf.conf.parser module

Parse and write Splunk’s .conf files

According to this doc:


  1. Comments must start at the beginning of a line (#)
  2. Comments may not be after a stanza name or on an attribute’s value
  3. Supporting encoding is UTF-8 (and therefore ASCII too)
exception ksconf.conf.parser.ConfParserException

Bases: Exception

exception ksconf.conf.parser.DuplicateKeyException

Bases: ksconf.conf.parser.ConfParserException

exception ksconf.conf.parser.DuplicateStanzaException

Bases: ksconf.conf.parser.ConfParserException

class ksconf.conf.parser.Token

Bases: object

Immutable token object. deepcopy returns the same object

ksconf.conf.parser.cont_handler(iterable, continue_re=re.compile('^(.*)\\\\$'), breaker='\n')

Look for trailing backslashes (”\”) which indicate a value for an attribute is split across multiple lines. This function will group such lines together, and pass all other lines through as-is. Note that the continuation character must be the very last character on the line, trailing whitespace is not allowed.

  • iterable (iter) – lines from a configuration file
  • continue_re – regular expression to detect the continuation character
  • breaker – joining string when combining continued lines into a single string. Default ‘\n

lines of text

Return type:


ksconf.conf.parser.inject_section_comments(section, prepend=None, append=None)
ksconf.conf.parser.parse_conf(stream, profile={'dup_key': 'overwrite', 'dup_stanza': 'exception', 'keep_comments': True, 'strict': True}, encoding=None)

Parse a .conf file. This is a wrapper around parse_conf_stream() that allows filenames or stream to be passed in.

  • stream (str, file) – the path to a configuration file or open file-like object to be parsed
  • profile – parsing configuration settings
  • encoding – Defaults to the system default, (Often “utf-8”)

a mapping of the stanza and attributes. The resulting output is accessible as [stanaza][attribute] -> value

Return type:


ksconf.conf.parser.parse_conf_stream(stream, keys_lower=False, handle_conts=True, keep_comments=False, dup_stanza='exception', dup_key='overwrite', strict=False)
ksconf.conf.parser.section_reader(stream, section_re=re.compile('^[\\s\\t]*\\[(.*)\\]\\s*$'))

This generator break a configuration file stream into sections. Each section contains a name and a list of text lines held within that section.

Sections that have no entries must be preserved. Any lines before the first section are send back with the section name of None.

  • stream (file) – configuration file input stream
  • section_re – regular expression for detecting stanza headers

sections in the form of (section_name, lines_of_text)

Return type:


ksconf.conf.parser.smart_write_conf(filename, conf, stanza_delim='\n', sort=True, temp_suffix='.tmp')
ksconf.conf.parser.splitup_kvpairs(lines, comments_re=re.compile('^\\s*[#;]'), keep_comments=False, strict=False)

Break up ‘attribute=value’ entries in a configuration file.

  • lines (iter) – the body of a stanza containing associated attributes and values
  • comments_re – Regular expression used to detect comments.
  • keep_comments (bool, optional) – Should comments be preserved in the output. Defaults to False.
  • strict (bool, optional) – Should unknown content in the stanza stop processing. Defaults to False allowing “junk” to be silently ignored for a best-effort parse.

iterable of (attribute,value) tuples

class ksconf.conf.parser.update_conf(conf_path, profile={'dup_key': 'overwrite', 'dup_stanza': 'exception', 'keep_comments': True, 'strict': True}, encoding=None, make_missing=False)

Bases: object

Context manager that allows for simple in-place updates to conf files. This provides a simple dict-like interface for easy updates.

Usage example:

with update_conf("app.conf") as conf:
    conf["launcher"]["version"] = "1.0.2"
    conf["install"]["build"] = 33
  • conf_path (str) – Path to .conf file to be edited.
  • profile (dict) – Parsing settings and strictness profile.
  • encoding (str) – encoding to use for file operations.
  • make_missing (bool) – When true, a new blank configuration file will be created with the updates rather than raising an exception.
update(*args, **kwargs)
ksconf.conf.parser.write_conf(stream, conf, stanza_delim='\n', sort=True)
ksconf.conf.parser.write_conf_stream(stream, conf, stanza_delim='\n', sort=True)

Module contents