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 |
FileTypeJSON |
JSON File Type |
FileTypeXML |
XML File Type |
FileTypeYAML |
YAML File Type |
Functions:
Name | Description |
---|---|
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 |
FileTypeJSON ¶
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 ¶
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'}]}]}
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
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
>>> Ruleset(ruleset=[x, {"rule": lambda: None}])
... # doctest: +ELLIPSIS
Ruleset(ruleset=[Rule(...), 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
>>> Ruleset(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
>>> Ruleset(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
>>> Ruleset(ruleset=[always_none, more_always_none]).apply(val=5)
[]
If nothing matched, and take_first=True
, None
is returned
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
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
|
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 = Ruleset(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 |