Translation¶
orbiter.rules.rulesets.TranslationRuleset ¶
A Ruleset is a collection of Rules that are
evaluated in priority order
A TranslationRuleset is a container for Rulesets,
which applies to a specific translation
>>> TranslationRuleset(
... file_type={FileTypeJSON}, # Has a file type
... translate_fn=fake_translate, # and can have a callable
... # translate_fn="orbiter.rules.translate.fake_translate", # or a qualified name to a function
... dag_filter_ruleset={"ruleset": [{"rule": lambda x: None}]}, # Rulesets can be dict within dicts
... dag_ruleset=DAGRuleset(ruleset=[Rule(rule=lambda x: None)]), # or objects within objects
... task_filter_ruleset=EMPTY_RULESET, # or a mix
... task_ruleset=EMPTY_RULESET,
... task_dependency_ruleset=EMPTY_RULESET, # Omitted for brevity
... post_processing_ruleset=EMPTY_RULESET,
... )
TranslationRuleset(...)
Parameters:
| Name | Type | Description |
|---|---|---|
file_type |
Set[Type[FileType]]
|
FileType to translate |
dag_filter_ruleset |
DAGFilterRuleset | dict
|
|
dag_ruleset |
DAGRuleset | dict
|
|
task_filter_ruleset |
TaskFilterRuleset | dict
|
|
task_ruleset |
TaskRuleset | dict
|
|
task_dependency_ruleset |
TaskDependencyRuleset | dict
|
|
post_processing_ruleset |
PostProcessingRuleset | dict
|
|
translate_fn |
Callable[[TranslationRuleset, Path], OrbiterProject] | str | TranslateFn
|
Either a qualified name to a function (e.g. |
Methods:
| Name | Description |
|---|---|
dumps |
Convert Python dictionary back to source string form, useful for testing |
get_ext |
Get the first file extension for this ruleset |
get_files_with_extension |
A generator that yields files with a specific extension(s) in a directory |
loads |
Converts all files of type into a Python dictionary "intermediate representation" form, |
test |
Test an input against the whole ruleset. |
dumps ¶
Convert Python dictionary back to source string form, useful for testing
Parameters:
| Name | Type | Description |
|---|---|---|
input_dict |
dict
|
The dictionary to convert to a string |
ext |
str | None
|
The file type extension to dump as, defaults to first 'file_type' in the set |
Returns:
| Type | Description |
|---|---|
str
|
The string representation of the input_dict, in the file_type format |
Source code in orbiter/rules/rulesets.py
get_ext ¶
Get the first file extension for this ruleset
get_files_with_extension ¶
A generator that yields files with a specific extension(s) in a directory
Parameters:
| Name | Type | Description |
|---|---|---|
input_dir |
Path
|
The directory to search in |
Returns:
| Type | Description |
|---|---|
Generator[Path, dict]
|
Generator item of (Path, dict) for each file found |
Source code in orbiter/rules/rulesets.py
loads ¶
Converts all files of type into a Python dictionary "intermediate representation" form, prior to any rulesets being applied.
Parameters:
| Name | Type | Description |
|---|---|---|
file |
Path
|
The file to load |
Returns:
| Type | Description |
|---|---|
dict
|
The dictionary representation of the input_str |
Source code in orbiter/rules/rulesets.py
test ¶
test(input_value: str | dict) -> OrbiterProject
Test an input against the whole ruleset. - 'input_dict' (a parsed python dict) - or 'input_str' (raw value) to test against the ruleset.
Parameters:
| Name | Type | Description |
|---|---|---|
input_value |
str | dict
|
The input to test can be either a dict (passed to |
Returns:
| Type | Description |
|---|---|
OrbiterProject
|
OrbiterProject produced after applying the ruleset |
Source code in orbiter/rules/rulesets.py
orbiter.file_types ¶
Classes:
| Name | Description |
|---|---|
FileType |
Abstract Base File Type |
FileTypeJIL |
JIL File Type |
FileTypeJSON |
JSON File Type |
FileTypePython |
Python File Type |
FileTypeXML |
XML File Type |
FileTypeYAML |
YAML File Type |
Functions:
| Name | Description |
|---|---|
parse_jil |
Parses JIL string into a dictionary. |
xmltodict_parse |
Calls |
FileType ¶
Abstract Base File Type
Parameters:
| Name | Type | Description |
|---|---|---|
extension |
Set[str]
|
The file extension(s) for this file type |
load_fn |
Callable[[str], dict]
|
The function to load the file into a dictionary for this file type |
dump_fn |
Callable[[dict], str]
|
The function to dump a dictionary to a string for this file type |
FileTypeJIL ¶
JIL File Type
Parameters:
| Name | Type | Description |
|---|---|---|
extension |
Set[str]
|
JIL |
load_fn |
Callable[[str], dict]
|
custom JIL loading function |
dump_fn |
Callable[[dict], str]
|
JIL dumping function not yet implemented, raises an error |
FileTypeJSON ¶
FileTypePython ¶
Python File Type
Parameters:
| Name | Type | Description |
|---|---|---|
extension |
Set[str]
|
PY |
load_fn |
Callable[[str], dict]
|
Python AST loading function (via |
dump_fn |
Callable[[dict], str]
|
Python dumping function not yet implemented, raises an error |
FileTypeXML ¶
XML File Type
Note
This class uses a custom xmltodict_parse method to standardize the output to a list of dictionaries
>>> out = FileTypeXML.dump_fn({'a': 1}); out
'<?xml version="1.0" encoding="utf-8"?>\n<a>1</a>'
>>> FileTypeXML.load_fn(out)
{'a': '1'}
Parameters:
| Name | Type | Description |
|---|---|---|
extension |
Set[str]
|
XML |
load_fn |
Callable[[str], dict]
|
xmltodict_parse |
dump_fn |
Callable[[dict], str]
|
xmltodict.unparse |
FileTypeYAML ¶
parse_jil ¶
Parses JIL string into a dictionary.
>>> parse_jil(r'''insert_job: TEST.ECHO job_type: CMD /* INLINE COMMENT */
... owner: foo
... /* MULTILINE
... COMMENT */
... machine: bar
... command: echo "Hello World"''')
{'jobs': [{'insert_job': 'TEST.ECHO', 'job_type': 'CMD', 'owner': 'foo', 'machine': 'bar', 'command': 'echo "Hello World"'}]}
Source code in orbiter/file_types.py
xmltodict_parse ¶
Calls xmltodict.parse and does post-processing fixes.
Note
The original xmltodict.parse method returns EITHER:
- a dict (one child element of type)
- or a list of dict (many child element of type)
This behavior can be confusing, and is an issue with the original xml spec being referenced.
This method deviates by standardizing to the latter case (always a list[dict]).
All XML elements will be a list of dictionaries, even if there's only one element.
>>> xmltodict_parse("")
Traceback (most recent call last):
xml.parsers.expat.ExpatError: no element found: line 1, column 0
>>> xmltodict_parse("<a></a>")
{'a': None}
>>> xmltodict_parse("<a foo='bar'></a>")
{'a': [{'@foo': 'bar'}]}
>>> xmltodict_parse("<a foo='bar'><foo bar='baz'></foo></a>") # Singleton - gets modified
{'a': [{'@foo': 'bar', 'foo': [{'@bar': 'baz'}]}]}
>>> xmltodict_parse("<a foo='bar'><foo bar='baz'><bar><bop></bop></bar></foo></a>") # Nested Singletons - modified
{'a': [{'@foo': 'bar', 'foo': [{'@bar': 'baz', 'bar': [{'bop': None}]}]}]}
>>> xmltodict_parse("<a foo='bar'><foo bar='baz'></foo><foo bing='bop'></foo></a>")
{'a': [{'@foo': 'bar', 'foo': [{'@bar': 'baz'}, {'@bing': 'bop'}]}]}
>>> xmltodict_parse("<a><?xml version='1.0' encoding='UTF-16'?><Properties version='1.1'></Properties></a>")
{'a': {'Properties': [{'@version': '1.1'}]}}
>>> xmltodict_parse('''<Source><Activity mc:Ignorable="sap sap2010 sads"
... x:Class="Activity" sap2010:WorkflowViewState.IdRef="Activity_1"
... xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities"
... xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
... <TextExpression.NamespacesForImplementation>
... <sco:Collection x:TypeArguments="x:String">
... <x:String>System</x:String>
... </sco:Collection>
... </TextExpression.NamespacesForImplementation>
... </Activity></Source>
... ''') # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
{'Source': {'Activity': [{'@mc:Ignorable': 'sap sap2010 sads',... 'TextExpression.NamespacesForImplementation': [{'sco:Collection': [{...}]}]}]}}
Parameters:
| Name | Type | Description |
|---|---|---|
input_str |
str
|
The XML string to parse |
Returns:
| Type | Description |
|---|---|
dict
|
The parsed XML |
Source code in orbiter/file_types.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | |
Rulesets¶
orbiter.rules.rulesets.Ruleset ¶
A list of rules, which are evaluated to generate different types of output
You must pass a Rule (or dict with the schema of Rule)
>>> from orbiter.rules import rule
>>> @rule
... def x(val):
... return None
>>> GenericRuleset(ruleset=[x, {"rule": lambda: None}])
... # doctest: +ELLIPSIS
GenericRuleset(ruleset=[Rule(...), ...])
Note
You can't pass non-Rules
Parameters:
| Name | Type | Description |
|---|---|---|
ruleset |
List[Rule | Callable[[Any], Any | None]]
|
Methods:
| Name | Description |
|---|---|
apply |
Apply all rules in ruleset to a single item, in priority order, removing any |
apply_many |
Apply a ruleset to each item in collection (such as |
apply ¶
Apply all rules in ruleset to a single item, in priority order, removing any None results.
A ruleset with one rule can produce up to one result
>>> from orbiter.rules import rule
>>> @rule
... def gt_4(val):
... return str(val) if val > 4 else None
>>> GenericRuleset(ruleset=[gt_4]).apply(val=5)
['5']
Many rules can produce many results, one for each rule.
>>> @rule
... def gt_3(val):
... return str(val) if val > 3 else None
>>> GenericRuleset(ruleset=[gt_4, gt_3]).apply(val=5)
['5', '5']
The take_first flag will evaluate rules in the ruleset and return the first match
If nothing matched, an empty list is returned
>>> @rule
... def always_none(val):
... return None
>>> @rule
... def more_always_none(val):
... return None
>>> GenericRuleset(ruleset=[always_none, more_always_none]).apply(val=5)
[]
If nothing matched, and take_first=True, None is returned
>>> GenericRuleset(ruleset=[always_none, more_always_none]).apply(val=5, take_first=True)
... # None
Tip
If no input is given, an error is returned
Parameters:
| Name | Type | Description |
|---|---|---|
take_first |
bool
|
only take the first (if any) result from the ruleset application |
kwargs |
key=val pairs to pass to the evaluated rule function |
Returns:
| Type | Description |
|---|---|
List[Any] | Any | None
|
List of rules that evaluated to |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the Ruleset is empty or input_val is None |
RuntimeError
|
if the Rule raises an exception |
Source code in orbiter/rules/rulesets.py
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | |
apply_many ¶
Apply a ruleset to each item in collection (such as dict().items())
and return any results that are not None
You can turn the output of apply_many into a dict, if the rule takes and returns a tuple
>>> from itertools import chain
>>> from orbiter.rules import rule
>>> @rule
... def filter_for_type_folder(val):
... (key, val) = val
... return (key, val) if val.get('Type', '') == 'Folder' else None
>>> ruleset = GenericRuleset(ruleset=[filter_for_type_folder])
>>> input_dict = {
... "a": {"Type": "Folder"},
... "b": {"Type": "File"},
... "c": {"Type": "Folder"},
... }
>>> dict(chain(*chain(ruleset.apply_many(input_dict.items()))))
... # use dict(chain(*chain(...))), if using `take_first=True`, to turn many results back into dict
{'a': {'Type': 'Folder'}, 'c': {'Type': 'Folder'}}
>>> dict(ruleset.apply_many(input_dict.items(), take_first=True))
... # use dict(...) directly, if using `take_first=True`, to turn results back into dict
{'a': {'Type': 'Folder'}, 'c': {'Type': 'Folder'}}
Tip
You cannot pass input without length
Parameters:
| Name | Type | Description |
|---|---|---|
input_val |
Collection[Any]
|
List to evaluate ruleset over |
take_first |
bool
|
Only take the first (if any) result from each ruleset application |
Returns:
| Type | Description |
|---|---|
List[List[Any]] | List[Any]
|
List of list with all non-null evaluations for each item |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
if the Ruleset or input_vals are empty |
RuntimeError
|
if the Rule raises an exception |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.DAGFilterRuleset ¶
Bases: Ruleset
Ruleset of DAGFilterRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from [DAG Filter Ruleset][orbiter.rules.ruleset.DAGFilterRuleset] to filter down to keys |
apply_ruleset ¶
Apply all rules from [DAG Filter Ruleset][orbiter.rules.ruleset.DAGFilterRuleset] to filter down to keys that look like they can be translated to a DAG, in priority order.
Note
The file is added under a __file key to both input and output dictionaries, for use in future rules.
The input dir is added under a __input_dir key to both input and output dictionaries, for use in future rules.
Parameters:
| Name | Type | Description |
|---|---|---|
input_dict |
dict
|
The input dictionary to filter, e.g. the file that was loaded and converted into a python dict |
file |
Path
|
The file relative to the input directory's parent (is added under '__file' key) |
input_dir |
Path
|
The input directory (is added under '__input_dir' key) |
Returns:
| Type | Description |
|---|---|
list[dict]
|
A list of dictionaries that look like they can be translated to a DAG |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.DAGRuleset ¶
Bases: Ruleset
Ruleset of DAGRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from |
apply_ruleset ¶
apply_ruleset(dag_dict: dict) -> OrbiterDAG | None
Apply all rules from DAGRuleset to convert the object to an OrbiterDAG,
in priority order, stopping when the first rule returns a match.
If no rule returns a match, the entry is filtered.
Note
The file is retained via OrbiterDAG.orbiter_kwargs['val']['__file'], for use in future rules.
Parameters:
| Name | Type | Description |
|---|---|---|
dag_dict |
dict
|
DAG Candidate, filtered via @dag_filter_rules |
Returns:
| Type | Description |
|---|---|
OrbiterDAG | None
|
An |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.TaskFilterRuleset ¶
Bases: Ruleset
Ruleset of TaskFilterRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from |
apply_ruleset ¶
Apply all rules from TaskFilterRuleset to filter down to keys that look like they can be translated
to a Task, in priority order.
Many entries in the dag_dict result in many task_dicts.
Parameters:
| Name | Type | Description |
|---|---|---|
dag_dict |
dict
|
The dict to filter - the same dict that was passed to the DAG ruleset |
Returns:
| Type | Description |
|---|---|
list[dict]
|
A list of dictionaries that look like they can be translated to a Task |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.TaskRuleset ¶
Bases: Ruleset
Ruleset of TaskRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from |
apply_ruleset ¶
apply_ruleset(
task_dict: dict,
) -> OrbiterOperator | OrbiterTaskGroup
Apply all rules from TaskRuleset to convert the object to a Task, in priority order,
stopping when the first rule returns a match.
One task_dict makes up to one task (unless it produces a TaskGroup, which can contain many tasks). If no rule returns a match, the entry is filtered.
Parameters:
| Name | Type | Description |
|---|---|---|
task_dict |
dict
|
A dict to translate - what was returned from the Task Filter ruleset |
Returns:
| Type | Description |
|---|---|
OrbiterOperator | OrbiterTaskGroup
|
An OrbiterOperator (or descendant) or [OrbiterTaskGroup][orbiter.objects.task.OrbiterTaskGroup] |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.TaskDependencyRuleset ¶
Bases: Ruleset
Ruleset of TaskDependencyRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from |
apply_ruleset ¶
apply_ruleset(
dag: OrbiterDAG,
) -> list[OrbiterTaskDependency]
Apply all rules from TaskDependencyRuleset to create a list of
OrbiterTaskDependency,
which are then added in-place to each task in the OrbiterDAG.
Parameters:
| Name | Type | Description |
|---|---|---|
dag |
OrbiterDAG
|
The DAG to add the task dependencies to |
Returns:
| Type | Description |
|---|---|
list[OrbiterTaskDependency]
|
A list of |
Source code in orbiter/rules/rulesets.py
orbiter.rules.rulesets.PostProcessingRuleset ¶
Bases: Ruleset
Ruleset of PostProcessingRule
Methods:
| Name | Description |
|---|---|
apply_ruleset |
Apply all rules from |
apply_ruleset ¶
apply_ruleset(project: OrbiterProject) -> None
Apply all rules from PostProcessingRuleset to modify project in-place
Parameters:
| Name | Type | Description |
|---|---|---|
project |
OrbiterProject
|
The OrbiterProject to modify |
Returns:
| Type | Description |
|---|---|
None
|
None |