ndf-parse#
This package is designed for prcessing Eugen Systems ndf files. It allows for easier code manipulations than out-of-the-box differ for Eugen mods.
- convert(data: str | bytes, ensure_no_errors: bool = True) List #
Converts string/byte data to a
List
object. Should be used to parse ndf files as a whole.- Parameters:
ensure_no_errors (bool, default=True) – If True then fail if ndf code contains syntax errors. Be mindful of checking strictness.
- Returns:
Model representation of a file.
- Return type:
- expression(data: str | bytes, ensure_no_errors: bool = True) Dict[str, Any] #
Converts string/byte data to a an expression wrapped in a dict. Should be used to parse individual expressions for further injection into an existing model.
- Parameters:
ensure_no_errors (bool, optional, default=True) – If True then fail if ndf code contains syntax errors. Be mindful of checking strictness.
- Returns:
A dict containing an item along with possible extra row attributes.
- Return type:
Examples
>>> import ndf_parse as ndf >>> src = '''Obj is Typ( ... Memb1 = "SomeStr" ... Memb2 = 12 ... )''' >>> source = ndf.convert(src) >>> arg = ndf.expression("export A is 12") >>> arg {'value': '12', 'namespace': 'A', 'visibility': 'export'} >>> source.add(**arg) # ** will deconstruct dict into method's parameters ListRow[1](value='12', visibility='export', namespace='A') >>> memb = ndf.expression("Memb3 = [1,2,3,Obj2(Memb1 = 5)]") >>> memb {'value': List[ListRow[0](value='1', visibility=None, namespace=None), ListRow[1](value='2', visibility=None, namespace=None), ListRow[2](value='3', visibility=None, namespace=None), ListRow[3](value=Object[MemberRow[0](value='5', member='Memb1', type=None, visibility=None, namespace=None)], visibility=None, namespace=None)], 'member': 'Memb3'} >>> source[0].value.add(**memb) MemberRow[2](value=List[ListRow[0](value='1', visibility=None, namespace=None), ListRow[1](value='2', visibility=None, namespace=None), ListRow[2](value='3', visibility=None, namespace=None), ListRow[3](value=Object[MemberRow[0](value='5', member='Memb1', type=None, visibility=None, namespace=None)], visibility=None, namespace=None)], member='Memb3', type=None, visibility=None, namespace=None) >>> ndf.printer.print(source) Obj is Typ ( Memb1 = "SomeStr" Memb2 = 12 Memb3 = [ 1, 2, 3, Obj2 ( Memb1 = 5 ) ] ) export A is 12
- expressions(data: str | bytes, ensure_no_errors: bool = True) List[Dict[str, Any]] #
Same as
expression()
, only outputs a list of expressions instead of only the first one.- datastr | bytes
ndf code to parse.
- ensure_no_errorsbool, optional, default=True
If True then fail if ndf code contains syntax errors. Be mindful of checking strictness.
- Returns:
A list of dict items containing expressions with additional data.
- Return type:
- walk(item, condition) Iterator #
Recursively walks a model representation of an ndf file.
- Parameters:
item (str |
DeclarationsList
|DeclListRow
) – Source to walk.condition (Callable[[Any], bool]) –
Function that is responsible for filtering items. Should return True if an item matches desired criteria.
Note
This function can accept multiple types so it’s a user’s responsibility to validate the item.
- Yields:
str |
DeclarationsList
|DeclListRow
– Items that match the condition criteria (i.e. on which the condition returns True).
Examples
Usage of this function is covered here
- class Mod(mod_src: str, mod_dst: str)#
This class holds links to source and destination mods. It also holds methods and wrappers designed to streamline editing, mainly the
edit()
method.- current_edit#
Currently active edit. In fact this is an alias to
Mod.edits[-1]
, i.e. it’s an edit at the top of the stack.- Type:
Edit | None
- current_tree#
Tree (a model representation of an ndf file) attribute of a currently active edit.
- Type:
model.List | None
Note
Paths are relative to an execution path, more on that here.
Examples
>>> import ndf_parse as ndf >>> mod = ndf.Mod('path/to/unedited/mod', 'path/to/generated/mod') >>> with mod.edit('GameData/path/to/file.ndf') as source: ... ... # edits to the source >>> # at the end of `with` file gets automatically written out None
- edit(file_path: str, save: bool = True, ensure_no_errors: bool = True) Mod #
Creates a new edit. It is designed to work with
with
clause. Avoid using it outside of thewith
unless you know what you are doing.- Parameters:
file_path (str) – File to be edited. Path should be relative to a mod root, i.e.
GameData/Generated/...
, more on that here.save (bool, default=True) – If True then file gets written out at the end of the
with
statement.ensure_no_errors (bool, default=True) – Ensures that original ndf code has no syntax errors. Fails if there are any and this parameter is True. Be mindful of checking strictness.
- Returns:
Returns it’s parent
Mod
object. Required forwith
statement to work correctly.- Return type:
- write_edit(edit: Edit, force: bool = True) bool #
Write given edit to the destination. Return True if data was written out.
An example of writing a bunch of edits if context manager (
with
statement) was not used:>>> import ndf_parse as ndf >>> mod = ndf.Mod('path/to/unedited/mod', 'path/to/generated/mod') >>> # load sources to be edited >>> ammo_src = Mod.edit('GameData/../Ammunition.ndf').current_tree >>> unit_src = Mod.edit('GameData/../UniteDescriptor.ndf').current_tree >>> # load decks for reference only, no need to write out later >>> decks_src = Mod.edit('GameData/../Decks.ndf', False).current_tree >>> ... # do stuff here >>> for edit in mod.edits: >>> mod.write_edit(edit, False) # disabled forced write so it >>> # does not write `decks_src` out
- check_if_src_is_newer() bool #
Nukes the destination mod and recreates a pristine copy of the destination mod if the source mod is newer (if modification date of the source is newer than of the destination).
- Returns:
True if the destination mod was rebuilt.
- Return type:
- update_dst()#
Forcefully rebuilds a clean version of the destination mod, no checks performed.
Warning
Must be used before any edits are applied otherwise they will be overwritten by data from source.
- parse_src(file_path: str, ensure_no_errors: bool = True) List #
Parses a file from a source mod.
This function does not write any modified data back to a destination file. It’s merely a convenience function for retrieving another mod file model to fetch some data without risking to write any modifications back out.
- Parameters:
file_path (str) – Relative path to a source file. Path should be relative to a mod root, i.e.
GameData/Generated/...
, more on that here.ensure_no_errors (bool, optional, default=True) – If on then fails in case there are any syntactic errors in the ndf code. Be mindful of checking strictness.
- Returns:
Model representation of the source mod file.
- Return type:
Examples
>>> import ndf_parse as ndf >>> mod = ndf.Mod('path/to/unedited/mod', 'path/to/generated/mod') >>> with mod.edit('GameData/path/to/units_file.ndf') as units: ... # This is a pseudocode, it does not match an actual mod ... # structure, it's intended to only show a possible use case. ... # We up the speed for any unit that has a 155mm weapon. ... weapons = mod.parse_src('GameData/path/to/weapons_file.ndf') ... for unit_row in units: ... weapon_class = unit_row.value.by_member('WeaponClass').value ... weapon_row = weapons.by_namespace(weapon_class) ... if weapon_row.value.by_member('Caliber').value == '155': ... unit = unit_row.value ... speed_row = unit.by_member('Speed') ... speed_row.value += ' * 2'
- parse_dst(file_path: str, ensure_no_errors: bool = True) List #
Parses a file from a destination mod.
This function is identical to
parse_src()
in it’s functionality and intent.- Parameters:
file_path (str) – Relative path to a destination file. Path should be relative to a mod root, i.e.
GameData/Generated/...
, more on that here.ensure_no_errors (bool, optional, default=True) – If on then fails in case there are any syntactic errors in the ndf code. Be mindful of checking strictness.
- Returns:
Model representation of the source mod file.
- Return type: