model#
Submodules:
This module presents ndf entities in a form of easy(ish)-to-work structures.
How NDF is Represented By The model#
List with ListRows#
NDF |
python |
---|---|
// as list
ListType[
export Namespace is "Value", 12
]
// as source
export Namespace is "Value"
12
|
lst = model.List(type='ListType')
lst.add(
model.ListRow(
visibility = 'export',
namespace = 'Namespace',
value = '"Value"'
),
model.ListRow(
visibility = None,
namespace = None,
value = '12'
)
)
|
Source List is the same as ordinary List but with lst.is_root = True
.
Object (and Template) with MemberRows#
NDF |
python |
---|---|
ObjType(
memb_name : int = export Ns is 12
)
|
obj = model.Object(type='ObjType')
obj.add(
model.MemberRow(
member = 'memb_name',
type = 'int',
visibility = 'export',
namespace = 'Ns',
value = '12'
)
)
|
Template
derives from Object
so it has the same row type plus
an additional property described below:
Template’s Param with ParamRow#
NDF |
python |
---|---|
template Ns
[
param_name : int = 12
] is ObjType()
|
tpl = model.Template(type='ObjType')
tpl.params.add(
model.ParamRow(
param='param_name',
type ='int',
value='12'
)
)
|
Usage Examples#
Here is a basic example of working with this module’s classes:
>>> import ndf_parse as ndf
>>> source = ndf.convert(b"Test is TObject(Member1: int = 1)")
>>> obj = source[0].v # `v` is an alias for `value`
>>> ndf.printer.print(obj)
TObject
(
Member1: int = 1
)
>>> # note there was no "Test is", because we've printed only the value, not the row
>>> m1 = obj[0]
>>> print(m1) # check the row
MemberRow[0](value='1', member='Member1', type='int', visibility=None, namespace=None)
>>> expr = ndf.expression("MemberRenamed = Namespace is 2")
>>> print(expr)
{'value': '2', 'namespace': 'Namespace', 'member': 'MemberRenamed'}
>>> m1.edit(**expr) # edit row via dict decomposition
MemberRow[0](value='2', member='MemberRenamed', type='int', visibility=None, namespace='Namespace')
>>> ndf.printer.print(obj)
TObject
(
MemberRenamed: int = Namespace is 2
)
>>> m1.edit(v='3', n='Ns', vis="export") # edit using aliases
MemberRow[0](value='3', member='MemberRenamed', type='int', visibility='export', namespace='Ns')
>>> m1.edit(nonexistent="4", _strict=False) # silently ignores
MemberRow[0](value='3', member='MemberRenamed', type='int', visibility='export', namespace='Ns')
>>> m1.edit(nonexistent="4") # Raises an error
Traceback (most recent call last):
...
TypeError: Cannot set MemberRow.nonexistent, attribute does not exist.
>>> obj.add(m1) # add a copy of a row (will copy it under the hood)
MemberRow[1](value='3', member='MemberRenamed', type='int', visibility='export', namespace='Ns')
>>> obj.by_member('MemberRenamed') # will find the first matching row
MemberRow[0](value='3', member='MemberRenamed', type='int', visibility='export', namespace='Ns')
Row Classes#
- class ListRow(value, visibility=None, namespace=None)#
Bases:
Row
Row of data from a
List
object.- property index: int | None#
(readonly) – Returns an index of this row in it’s parent or
None
if dangling.- Raises:
LookupError – Errors out if has a parent but was not found in it (this should never happen unless there is a serious bug in parent/unparent routines or it was manually deleted from
List.__inner
).
- property visibility str | None #
Visibility modifier of the assignment. Should be one of these:
'unnamed'
|'export'
|'private'
|'public'
Keep in mind that it won’t protect from'unnamed'
actually having a name or appearing multiple times the List, see notes on checking strictness.- property vis#
An alias for
visibility
.
- property namespace str | None #
Namespace name of the assignment.
- property n#
An alias for
namespace
.
- classmethod from_ndf(code) ListRow #
Create a row from an ndf code snippet. More details:
abc.Row.from_ndf()
.
- copy() ListRow #
Performs a deep copy of a row. More details:
abc.Row.copy()
.
- compare(other: object, existing_only: bool = True) bool #
Compares this row with a given row or a row representation. existing_only affects comparison mode (pattern matching if
True
, strict comparison ifFalse
) More details with examples:abc.Row.compare()
.
- edit(_strict: bool = True, **kwargs) self #
Edit several parameters at a time. Supports parameter aliases. More details:
abc.Row.edit()
.
- edit_ndf(code) self #
Edit row with an ndf code snippet. More details with an example:
abc.Row.edit_ndf()
.
- as_dict() dict #
Outputs given row in a form of a dict.
Note
It does not perform copy for it’s value. If you edit value key in the dict, it will be also edited in the original row (they literally point to the same object in memory). Creating a new row from such dict via decomposition (
new_row = model.ListRow( **old_row.as_dict() )
) is fine as long as source is parented to something. If it is a dangling row then you WILL get 2 rows referencing the same data in memory (because of specific optimizations aimed at avoiding excessive data copying on row moves) and will have unexpected side effects! Copying usingRow.copy()
is recommended in most cases. It’s easier and guarantees no such side effects.
- class MapRow(key, value)#
Bases:
Row
Row of data from a
Map
object.- property index: int | None#
(readonly) – Returns an index of this row in it’s parent or
None
if dangling.- Raises:
LookupError – Errors out if has a parent but was not found in it (this should never happen unless there is a serious bug in parent/unparent routines or it was manually deleted from
List.__inner
).
- classmethod from_ndf(code) MapRow #
Create a row from an ndf code snippet. More details:
abc.Row.from_ndf()
.
- copy() MapRow #
Performs a deep copy of a row. More details:
abc.Row.copy()
.
- compare(other: object, existing_only: bool = True) bool #
Extends
original method
by adding comparisons against tuple pairs.
- edit(_strict: bool = True, **kwargs) self #
Extends
original method
by adding editing with a tuple pair:>>> from ndf_parse.model import MapRow >>> row = MapRow("k1", "v1") >>> row MapRow[DANGLING](key='k1', value='v1') >>> row.edit(('k2', 'v2')) # editing with a tuple MapRow[DANGLING](key='k2', value='v2') >>> row.edit(k='k3', v='v3') # normal editing mode MapRow[DANGLING](key='k3', value='v3')
- edit_ndf(code) self #
Edit row with an ndf code snippet. More details with an example:
abc.Row.edit_ndf()
.
- as_dict() dict #
Outputs given row in a form of a dict.
Note
It does not perform copy for it’s value. If you edit value key in the dict, it will be also edited in the original row (they literally point to the same object in memory). Creating a new row from such dict via decomposition (
new_row = model.ListRow( **old_row.as_dict() )
) is fine as long as source is parented to something. If it is a dangling row then you WILL get 2 rows referencing the same data in memory (because of specific optimizations aimed at avoiding excessive data copying on row moves) and will have unexpected side effects! Copying usingRow.copy()
is recommended in most cases. It’s easier and guarantees no such side effects.
- class MemberRow(value, member=None, type=None, visibility=None, namespace=None)#
Bases:
Row
Row of data from
Object
andTemplate
objects.- property index: int | None#
(readonly) – Returns an index of this row in it’s parent or
None
if dangling.- Raises:
LookupError – Errors out if has a parent but was not found in it (this should never happen unless there is a serious bug in parent/unparent routines or it was manually deleted from
List.__inner
).
- property type str | None #
Typing data for this object. Keep in mind, not all types are stored here.
- property visibility str | None #
Visibility modifier of the assignment. Should be one of these:
'export'
|'private'
|'public'
- property vis#
An alias for
visibility
.
- classmethod from_ndf(code) MemberRow #
Create a row from an ndf code snippet. More details:
abc.Row.from_ndf()
.
- copy() MemberRow #
Performs a deep copy of a row. More details:
abc.Row.copy()
.
- compare(other: object, existing_only: bool = True) bool #
Compares this row with a given row or a row representation. existing_only affects comparison mode (pattern matching if
True
, strict comparison ifFalse
) More details with examples:abc.Row.compare()
.
- edit(_strict: bool = True, **kwargs) self #
Edit several parameters at a time. Supports parameter aliases. More details:
abc.Row.edit()
.
- edit_ndf(code) self #
Edit row with an ndf code snippet. More details with an example:
abc.Row.edit_ndf()
.
- as_dict() dict #
Outputs given row in a form of a dict.
Note
It does not perform copy for it’s value. If you edit value key in the dict, it will be also edited in the original row (they literally point to the same object in memory). Creating a new row from such dict via decomposition (
new_row = model.ListRow( **old_row.as_dict() )
) is fine as long as source is parented to something. If it is a dangling row then you WILL get 2 rows referencing the same data in memory (because of specific optimizations aimed at avoiding excessive data copying on row moves) and will have unexpected side effects! Copying usingRow.copy()
is recommended in most cases. It’s easier and guarantees no such side effects.
- class ParamRow(param, type=None, value=None)#
Bases:
Row
Row of data from a
Params
object.- property index: int | None#
(readonly) – Returns an index of this row in it’s parent or
None
if dangling.- Raises:
LookupError – Errors out if has a parent but was not found in it (this should never happen unless there is a serious bug in parent/unparent routines or it was manually deleted from
List.__inner
).
- classmethod from_ndf(code) ParamRow #
Create a row from an ndf code snippet. More details:
abc.Row.from_ndf()
.
- copy() ParamRow #
Performs a deep copy of a row. More details:
abc.Row.copy()
.
- compare(other: object, existing_only: bool = True) bool #
Compares this row with a given row or a row representation. existing_only affects comparison mode (pattern matching if
True
, strict comparison ifFalse
) More details with examples:abc.Row.compare()
.
- edit(_strict: bool = True, **kwargs) self #
Edit several parameters at a time. Supports parameter aliases. More details:
abc.Row.edit()
.
- edit_ndf(code) self #
Edit row with an ndf code snippet. More details with an example:
abc.Row.edit_ndf()
.
- as_dict() dict #
Outputs given row in a form of a dict.
Note
It does not perform copy for it’s value. If you edit value key in the dict, it will be also edited in the original row (they literally point to the same object in memory). Creating a new row from such dict via decomposition (
new_row = model.ListRow( **old_row.as_dict() )
) is fine as long as source is parented to something. If it is a dangling row then you WILL get 2 rows referencing the same data in memory (because of specific optimizations aimed at avoiding excessive data copying on row moves) and will have unexpected side effects! Copying usingRow.copy()
is recommended in most cases. It’s easier and guarantees no such side effects.
List-like Classes#
- class List(is_root: bool = False, type: str | None = None)#
-
List represents ndf lists (
[]
), vector types (typename[]
) and a collection of root level statements (source root).- is_root: bool = False#
Indicates whether this is a source root or any other nested item. Needed for
printer
format them differently.
- type: str | None = None#
Stores type for vector types (like
RGBA[0, 0, 0, 1]
). See Typing Ambiguity in main documentation for more info.
- by_n(namespace: str) ListRow #
- by_n(namespace: str, strict: bool) ListRow | None
- by_name(namespace: str) ListRow #
- by_name(namespace: str, strict: bool) ListRow | None
- by_namespace(namespace: str, strict: bool = True) ListRow | None #
Find row by it’s namespace. Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_namespace(namespace: str, strict: bool = True) ListRow | None #
Find and remove row by it’s namespace. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
Inherited Methods
- add(input: DictWrapped | ListRow) ListRow
- add(input: Iterable[DictWrapped | ListRow | str]) list[ListRow]
- add(*input: DictWrapped | ListRow | str) list[ListRow]
Detailed description and examples:
abc.List.add()
- insert(key: int, input: DictWrapped | ListRow) ListRow
- insert(key: int, *input: DictWrapped | ListRow | str) list[ListRow]
Detailed description and examples:
abc.List.insert()
- replace(key: int | slice, input: DictWrapped | ListRow) ListRow
- replace(key: int | slice, *input: DictWrapped | ListRow | str) list[ListRow]
Detailed description and examples:
abc.List.replace()
- remove(self, key: slice) list[ListRow]
Detailed description and examples:
abc.List.remove()
- match_pattern(row: str | ListRow | DictWrapped) Iterable[ListRow] #
Detailed description and examples:
abc.List.match_pattern()
- find_by_cond(condition: callable[[ListRow], bool], strict: bool = True) ListRow | None #
Detailed description and examples:
abc.List.find_by_cond()
- compare(other: object, existing_only: bool = True) bool #
Detailed description and examples:
abc.List.compare()
- copy() Self #
Performs a deep copy of a list. It’s an alias to a
__deepcopy__()
method (shallow copying is disabled intentionally).
- class Object(type: str | None = None)#
-
Object represents ndf objects as a list of members.
- type: str | None = None#
Stores object’s type (for
TObject( /*...*/ )
it’s type will be equal toTObject
). See Typing Ambiguity in main documentation for more info.
- by_n(namespace: str) MemberRow #
- by_n(namespace: str, strict: bool) MemberRow | None
- by_name(namespace: str) MemberRow #
- by_name(namespace: str, strict: bool) MemberRow | None
- by_namespace(namespace: str, strict: bool = True) MemberRow | None #
Find row by it’s namespace. Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_namespace(namespace: str, strict: bool = True) MemberRow | None #
Find and remove row by it’s namespace. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
- by_member(member: str, strict: bool = True) MemberRow | None #
Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_member(member: str, strict: bool = True) MemberRow | None #
Find and remove row by it’s member. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
Inherited Methods
- add(input: DictWrapped | MemberRow) MemberRow
- add(input: Iterable[DictWrapped | MemberRow | str]) list[MemberRow]
- add(*input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.add()
- insert(key: int, input: DictWrapped | MemberRow) MemberRow
- insert(key: int, *input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.insert()
- replace(key: int | slice, input: DictWrapped | MemberRow) MemberRow
- replace(key: int | slice, *input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.replace()
- remove(self, key: slice) list[MemberRow]
Detailed description and examples:
abc.List.remove()
- match_pattern(row: str | MemberRow | DictWrapped) Iterable[MemberRow] #
Detailed description and examples:
abc.List.match_pattern()
- find_by_cond(condition: callable[[MemberRow], bool], strict: bool = True) MemberRow | None #
Detailed description and examples:
abc.List.find_by_cond()
- compare(other: object, existing_only: bool = True) bool #
Detailed description and examples:
abc.List.compare()
- copy() Self #
Performs a deep copy of a list. It’s an alias to a
__deepcopy__()
method (shallow copying is disabled intentionally).
- class Template(type: str | None = None)#
Bases:
Object
Template represents ndf templates as a list of members and template params.
- by_n(namespace: str) MemberRow #
- by_n(namespace: str, strict: bool) MemberRow | None
- by_name(namespace: str) MemberRow #
- by_name(namespace: str, strict: bool) MemberRow | None
- by_namespace(namespace: str, strict: bool = True) MemberRow | None #
Find row by it’s namespace. Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_namespace(namespace: str, strict: bool = True) MemberRow | None #
Find and remove row by it’s namespace. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
- by_member(member: str, strict: bool = True) MemberRow | None #
Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_member(member: str, strict: bool = True) MemberRow | None #
Find and remove row by it’s member. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
Inherited Methods
- add(input: DictWrapped | MemberRow) MemberRow
- add(input: Iterable[DictWrapped | MemberRow | str]) list[MemberRow]
- add(*input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.add()
- insert(key: int, input: DictWrapped | MemberRow) MemberRow
- insert(key: int, *input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.insert()
- replace(key: int | slice, input: DictWrapped | MemberRow) MemberRow
- replace(key: int | slice, *input: DictWrapped | MemberRow | str) list[MemberRow]
Detailed description and examples:
abc.List.replace()
- remove(self, key: slice) list[MemberRow]
Detailed description and examples:
abc.List.remove()
- match_pattern(row: str | MemberRow | DictWrapped) Iterable[MemberRow] #
Detailed description and examples:
abc.List.match_pattern()
- find_by_cond(condition: callable[[MemberRow], bool], strict: bool = True) MemberRow | None #
Detailed description and examples:
abc.List.find_by_cond()
- compare(other: object, existing_only: bool = True) bool #
Detailed description and examples:
abc.List.compare()
- copy() Self #
Performs a deep copy of a list. It’s an alias to a
__deepcopy__()
method (shallow copying is disabled intentionally).
- class Params#
-
Params represents a list of generic parameters to be used in a template.
- type: str | None = None#
Stores object’s type (for
TObject( /*...*/ )
it’s type will be equal toTObject
). See Typing Ambiguity in main documentation for more info.
- by_param(param: str, strict: bool = True) ParamRow | None #
Find row by it’s namespace. Returns first match that is found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_param(param: str, strict: bool = True) ParamRow | None #
Find and remove row by it’s param. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
Inherited Methods
- add(input: DictWrapped | ParamRow) ParamRow
- add(input: Iterable[DictWrapped | ParamRow | str]) list[ParamRow]
- add(*input: DictWrapped | ParamRow | str) list[ParamRow]
Detailed description and examples:
abc.List.add()
- insert(key: int, input: DictWrapped | ParamRow) ParamRow
- insert(key: int, *input: DictWrapped | ParamRow | str) list[ParamRow]
Detailed description and examples:
abc.List.insert()
- replace(key: int | slice, input: DictWrapped | ParamRow) ParamRow
- replace(key: int | slice, *input: DictWrapped | ParamRow | str) list[ParamRow]
Detailed description and examples:
abc.List.replace()
- remove(self, key: slice) list[ParamRow]
Detailed description and examples:
abc.List.remove()
- match_pattern(row: str | ParamRow | DictWrapped) Iterable[ParamRow] #
Detailed description and examples:
abc.List.match_pattern()
- find_by_cond(condition: callable[[ParamRow], bool], strict: bool = True) ParamRow | None #
Detailed description and examples:
abc.List.find_by_cond()
- compare(other: object, existing_only: bool = True) bool #
Detailed description and examples:
abc.List.compare()
- copy() Self #
Performs a deep copy of a list. It’s an alias to a
__deepcopy__()
method (shallow copying is disabled intentionally).
- class Map#
-
Map represents ndf maps as a list of pairs represented as a
MapRow
.Map has a couple things that set it apart from other list-like objects in this module. In ndf code pairs are represented in a way that lends itself perfectly into storing them as tuples in python (at least visually). But using them to set a row has a nuance. Here is an illustration of the issue, an explanation will follow:
>>> from ndf_parse.model import Map >>> map = Map() >>> map[:] = ("key", "value") # this will fail Traceback (most recent call last): ... ndf_parse.traverser.BadNdfError: Errors while parsing expression: 0: Syntax error at 0:0: key >>> map[:] = (("key", "value"), ) # a tuple wrapped in another iterable will work >>> map[0] = ("key2", "value2"), # same as above, just shorter (one extra comma) >>> map Map[MapRow[0](key='key2', value='value2')]
Explanation: when a list-like recieves an iterable as an insertion, it iterates it and treats each value inside as a row or row’s representation. In this case it iterates the pair and tries to interpret each string as an ndf code (which it obviously isn’t). To avoid such behaviour we wrap our pair into any other iterable (tuple in this case but it can be a list too). For brevity python allows to omit tuple’s brackets unless it’s ambiguous (inside a function call for exampe) so we get left with just an extra comma.
Map also supports checking if a key is inside of it in a pythonic way:
>>> from ndf_parse.model import Map, MapRow >>> pairs = Map() >>> pairs.add(k='test', v='some_value') MapRow[0](key='test', value='some_value') >>> 'test' in pairs True >>> 'test2' in pairs False >>> 'some_value' in pairs # checks only keys, not values! False >>> # it also retains ability to check for a row as other list-likes >>> pairs[0] in pairs True
- by_key(key: str, strict: bool = True) MapRow | None #
Find row by it’s key. Returns first match or None if not found. If none found and strict is
True
then raises an error. IfFalse
then returns None. If strict is not set then it’sTrue
by default.
- remove_by_key(key: str, strict: bool = True) MapRow | None #
Find and remove row by it’s key. Removes first occurence if found. Raises error if nothing found and strict is
True
, else returnsNone
.
Inherited Methods
- add(input: DictWrapped | MapRow | Pair) MapRow
- add(input: Iterable[DictWrapped | MapRow | str | Pair]) list[MapRow]
- add(*input: DictWrapped | MapRow | str | Pair) list[MapRow]
Detailed description and examples:
abc.List.add()
Note
Also accepts
Pair
as an input.
- insert(key: int, input: DictWrapped | MapRow | Pair) MapRow
- insert(key: int, *input: DictWrapped | MapRow | str | Pair) list[MapRow]
Detailed description and examples:
abc.List.insert()
Note
Also accepts
Pair
as an input.
- replace(key: int | slice, input: DictWrapped | MapRow | Pair) MapRow
- replace(key: int | slice, *input: DictWrapped | MapRow | str | Pair) list[MapRow]
Detailed description and examples:
abc.List.replace()
Note
Also accepts
Pair
as an input.
- remove(self, key: slice) list[MapRow]
Detailed description and examples:
abc.List.remove()
- match_pattern(row: str | MapRow | DictWrapped) Iterable[MapRow] #
Detailed description and examples:
abc.List.match_pattern()
- find_by_cond(condition: callable[[MapRow], bool], strict: bool = True) MapRow | None #
Detailed description and examples:
abc.List.find_by_cond()
- compare(other: object, existing_only: bool = True) bool #
Detailed description and examples:
abc.List.compare()
- copy() Self #
Performs a deep copy of a list. It’s an alias to a
__deepcopy__()
method (shallow copying is disabled intentionally).