-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Filter object #155
Merged
dbarrosop
merged 8 commits into
nornir-automation:filter_object
from
targuan:feature/filter_helper
Jul 10, 2018
Merged
Filter object #155
Changes from 3 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
6cc1a5d
Add filter helper object
targuan 5bd8def
Black
targuan 7948b49
Add more operations
targuan 2ebb6bd
Move filter to core
targuan c619ebc
Rename filter
targuan 7acb778
Change test pattern
targuan 537ee1a
Formating
targuan e211525
Add combined test
targuan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import copy | ||
|
||
|
||
class F(object): | ||
AND = "AND" | ||
OR = "OR" | ||
|
||
def __init__(self, **kwargs): | ||
self.operator = self.AND | ||
self.operands = [] | ||
self.filters = list(kwargs.items()) | ||
self.negate = False | ||
|
||
def __call__(self, object): | ||
if self.operator == self.AND: | ||
reducer_func = all | ||
elif self.operator == self.OR: | ||
reducer_func = any | ||
matching_result = [o(object) for o in self.operands] | ||
matching_result += [ | ||
F._verify_rules(object, k.split("__"), v) for k, v in self.filters | ||
] | ||
if self.negate: | ||
return not reducer_func(matching_result) | ||
|
||
else: | ||
return reducer_func(matching_result) | ||
|
||
def __and__(self, other): | ||
res = F() | ||
if self.operator == self.AND and other.operator == self.AND: | ||
res.operator = self.AND | ||
res.operands = self.operands + other.operands | ||
res.filters = self.filters + other.filters | ||
else: | ||
res.operator = self.AND | ||
res.operands = [self, other] | ||
return res | ||
|
||
def __or__(self, other): | ||
res = F() | ||
if self.operator == self.OR and other.operator == self.OR: | ||
res.operator = self.OR | ||
res.oprands = self.operands + other.operands | ||
res.filters = self.filters + other.filters | ||
else: | ||
res.operator = self.OR | ||
res.operands = [self, other] | ||
return res | ||
|
||
def __invert__(self): | ||
res = copy.deepcopy(self) | ||
res.negate = ~res.negate | ||
return res | ||
|
||
def __repr__(self): | ||
if self.negate: | ||
template = "<Filter NOT {} {}>" | ||
else: | ||
template = "<Filter {} {}>" | ||
return template.format(self.operator, self.operands + self.filters) | ||
|
||
@staticmethod | ||
def _verify_rules(data, rule, value): | ||
if len(rule) > 1: | ||
return F._verify_rules(data.get(rule[0], {}), rule[1:], value) | ||
|
||
elif len(rule) == 1: | ||
operator = "__{}__".format(rule[0]) | ||
if hasattr(data, operator): | ||
return getattr(data, operator)(value) | ||
|
||
else: | ||
return data.get(rule[0]) == value | ||
|
||
else: | ||
raise Exception( | ||
"I don't know how I got here:\n{}\n{}\n{}".format(data, rule, value) | ||
) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from nornir.plugins.inventory.helpers.filters import F | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As per above comment this should be "tests/core/test_filter.py". Also, please, follow the same pattern as with the rest of the tests, please. |
||
|
||
|
||
def test_simple(nornir): | ||
f = F(site="site1") | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev1.group_1", "dev2.group_1"] | ||
|
||
|
||
def test_and(nornir): | ||
f = F(site="site1") & F(role="www") | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev1.group_1"] | ||
|
||
|
||
def test_or(nornir): | ||
f = F(site="site1") | F(role="www") | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev1.group_1", "dev2.group_1", "dev3.group_2"] | ||
|
||
|
||
def test_combined(nornir): | ||
f = F(site="site2") | (F(role="www") & F(my_var="comes_from_dev1.group_1")) | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev1.group_1", "dev3.group_2", "dev4.group_2"] | ||
|
||
|
||
def test_contains(nornir): | ||
f = F(groups__contains="group_1") | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev1.group_1", "dev2.group_1"] | ||
|
||
|
||
def test_negate(nornir): | ||
f = ~F(groups__contains="group_1") | ||
filtered = sorted(list((nornir.filter(filter_func=f).inventory.hosts.keys()))) | ||
|
||
assert filtered == ["dev3.group_2", "dev4.group_2"] |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should consider this core functionality so I'd place it under
nornir/core/filter.py