Fix pattern equivalence doc style for consistency

pull/1/head
Chris Lenk 2020-11-20 15:59:55 -05:00
parent f9e9c50db9
commit b55c3bb1df
7 changed files with 181 additions and 97 deletions

View File

@ -30,7 +30,8 @@ def _get_pattern_canonicalizer():
"""
Get a canonicalization transformer for STIX patterns.
:return: The transformer
Returns:
The transformer
"""
# The transformers are either stateless or contain no state which changes
@ -64,11 +65,14 @@ def equivalent_patterns(pattern1, pattern2, stix_version=stix2.DEFAULT_VERSION):
"""
Determine whether two STIX patterns are semantically equivalent.
:param pattern1: The first STIX pattern
:param pattern2: The second STIX pattern
:param stix_version: The STIX version to use for pattern parsing, as a
string ("2.0", "2.1", etc). Defaults to library-wide default version.
:return: True if the patterns are semantically equivalent; False if not
Args:
pattern1: The first STIX pattern
pattern2: The second STIX pattern
stix_version: The STIX version to use for pattern parsing, as a string
("2.0", "2.1", etc). Defaults to library-wide default version.
Returns:
True if the patterns are semantically equivalent; False if not
"""
patt_ast1 = stix2.pattern_visitor.create_pattern_object(
pattern1, version=stix_version,
@ -96,12 +100,14 @@ def find_equivalent_patterns(
on an input iterable and is implemented as a generator of matches. So you
can "stream" patterns in and matching patterns will be streamed out.
:param search_pattern: A search pattern as a string
:param patterns: An iterable over patterns as strings
:param stix_version: The STIX version to use for pattern parsing, as a
string ("2.0", "2.1", etc). Defaults to library-wide default version.
:return: A generator iterator producing the semantically equivalent
patterns
Args:
search_pattern: A search pattern as a string
patterns: An iterable over patterns as strings
stix_version: The STIX version to use for pattern parsing, as a string
("2.0", "2.1", etc). Defaults to library-wide default version.
Returns:
A generator iterator producing the semantically equivalent patterns
"""
search_pattern_ast = stix2.pattern_visitor.create_pattern_object(
search_pattern, version=stix_version,

View File

@ -16,9 +16,12 @@ def generic_cmp(value1, value2):
Generic comparator of values which uses the builtin '<' and '>' operators.
Assumes the values can be compared that way.
:param value1: The first value
:param value2: The second value
:return: -1, 0, or 1 depending on whether value1 is less, equal, or greater
Args:
value1: The first value
value2: The second value
Returns:
-1, 0, or 1 depending on whether value1 is less, equal, or greater
than value2
"""
@ -30,12 +33,15 @@ def iter_lex_cmp(seq1, seq2, cmp):
Generic lexicographical compare function, which works on two iterables and
a comparator function.
:param seq1: The first iterable
:param seq2: The second iterable
:param cmp: a two-arg callable comparator for values iterated over. It
must behave analogously to this function, returning <0, 0, or >0 to
express the ordering of the two values.
:return: <0 if seq1 < seq2; >0 if seq1 > seq2; 0 if they're equal
Args:
seq1: The first iterable
seq2: The second iterable
cmp: a two-arg callable comparator for values iterated over. It
must behave analogously to this function, returning <0, 0, or >0 to
express the ordering of the two values.
Returns:
<0 if seq1 < seq2; >0 if seq1 > seq2; 0 if they're equal
"""
it1 = iter(seq1)
@ -84,11 +90,14 @@ def iter_in(value, seq, cmp):
a comparator function. This function checks whether the given value is
contained in the given iterable.
:param value: A value
:param seq: An iterable
:param cmp: A 2-arg comparator function which must return 0 if the args
are equal
:return: True if the value is found in the iterable, False if it is not
Args:
value: A value
seq: An iterable
cmp: A 2-arg comparator function which must return 0 if the args
are equal
Returns:
True if the value is found in the iterable, False if it is not
"""
result = False
for seq_val in seq:

View File

@ -32,9 +32,12 @@ def generic_constant_cmp(const1, const2):
Generic comparator for most _Constant instances. They must have a "value"
attribute whose value supports the builtin comparison operators.
:param const1: The first _Constant instance
:param const2: The second _Constant instance
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
const1: The first _Constant instance
const2: The second _Constant instance
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
return generic_cmp(const1.value, const2.value)
@ -44,9 +47,12 @@ def bool_cmp(value1, value2):
"""
Compare two boolean constants.
:param value1: The first BooleanConstant instance
:param value2: The second BooleanConstant instance
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
value1: The first BooleanConstant instance
value2: The second BooleanConstant instance
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
@ -72,9 +78,12 @@ def hex_cmp(value1, value2):
Compare two STIX "hex" values. This decodes to bytes and compares that.
It does *not* do a string compare on the hex representations.
:param value1: The first HexConstant
:param value2: The second HexConstant
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
value1: The first HexConstant
value2: The second HexConstant
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
bytes1 = bytes.fromhex(value1.value)
@ -88,9 +97,12 @@ def bin_cmp(value1, value2):
Compare two STIX "binary" values. This decodes to bytes and compares that.
It does *not* do a string compare on the base64 representations.
:param value1: The first BinaryConstant
:param value2: The second BinaryConstant
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
value1: The first BinaryConstant
value2: The second BinaryConstant
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
bytes1 = base64.standard_b64decode(value1.value)
@ -103,9 +115,12 @@ def list_cmp(value1, value2):
"""
Compare lists order-insensitively.
:param value1: The first ListConstant
:param value2: The second ListConstant
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
value1: The first ListConstant
value2: The second ListConstant
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
@ -144,9 +159,12 @@ def object_path_component_cmp(comp1, comp2):
Ints and strings compare as usual to each other; ints compare less than
strings.
:param comp1: An object path component (string or int)
:param comp2: An object path component (string or int)
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
comp1: An object path component (string or int)
comp2: An object path component (string or int)
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
@ -172,8 +190,11 @@ def object_path_to_raw_values(path):
properties; "*" index steps become that string; and numeric index steps
become integers.
:param path: An ObjectPath instance
:return: A generator iterator over the values
Args:
path: An ObjectPath instance
Returns:
A generator iterator over the values
"""
for comp in path.property_path:
@ -195,9 +216,12 @@ def object_path_cmp(path1, path2):
"""
Compare two object paths.
:param path1: The first ObjectPath instance
:param path2: The second ObjectPath instance
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
path1: The first ObjectPath instance
path2: The second ObjectPath instance
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
if path1.object_type_name < path2.object_type_name:
@ -224,9 +248,12 @@ def comparison_operator_cmp(op1, op2):
"""
Compare two comparison operators.
:param op1: The first comparison operator (a string)
:param op2: The second comparison operator (a string)
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
op1: The first comparison operator (a string)
op2: The second comparison operator (a string)
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
op1_idx = _COMPARISON_OP_ORDER.index(op1)
@ -241,9 +268,12 @@ def constant_cmp(value1, value2):
"""
Compare two constants.
:param value1: The first _Constant instance
:param value2: The second _Constant instance
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
value1: The first _Constant instance
value2: The second _Constant instance
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
@ -284,9 +314,12 @@ def simple_comparison_expression_cmp(expr1, expr2):
Compare "simple" comparison expressions: those which aren't AND/OR
combinations, just <path> <op> <value> comparisons.
:param expr1: first _ComparisonExpression instance
:param expr2: second _ComparisonExpression instance
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
expr1: first _ComparisonExpression instance
expr2: second _ComparisonExpression instance
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
@ -315,9 +348,12 @@ def comparison_expression_cmp(expr1, expr2):
expressions' sub-components. To achieve an order-insensitive comparison,
the ASTs must be canonically ordered first.
:param expr1: The first comparison expression
:param expr2: The second comparison expression
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
expr1: The first comparison expression
expr2: The second comparison expression
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
if isinstance(expr1, _ComparisonExpression) \

View File

@ -64,9 +64,12 @@ def observation_expression_cmp(expr1, expr2):
the expressions' sub-components. To achieve an order-insensitive
comparison, the ASTs must be canonically ordered first.
:param expr1: The first observation expression
:param expr2: The second observation expression
:return: <0, 0, or >0 depending on whether the first arg is less, equal or
Args:
expr1: The first observation expression
expr2: The second observation expression
Returns:
<0, 0, or >0 depending on whether the first arg is less, equal or
greater than the second
"""
type1 = type(expr1)

View File

@ -22,13 +22,17 @@ def _dupe_ast(ast):
"""
Create a duplicate of the given AST.
Note: the comparison expression "leaves", i.e. simple <path> <op> <value>
comparisons are currently not duplicated. I don't think it's necessary as
of this writing; they are never changed. But revisit this if/when
necessary.
Note:
The comparison expression "leaves", i.e. simple <path> <op> <value>
comparisons are currently not duplicated. I don't think it's necessary
as of this writing; they are never changed. But revisit this if/when
necessary.
:param ast: The AST to duplicate
:return: The duplicate AST
Args:
ast: The AST to duplicate
Returns:
The duplicate AST
"""
if isinstance(ast, AndBooleanExpression):
result = AndBooleanExpression([
@ -108,8 +112,11 @@ class ComparisonExpressionTransformer(Transformer):
Invoke a transformer callback method based on the given ast root node
type.
:param ast: The AST
:return: The callback's result
Args:
ast: The AST
Returns:
The callback's result
"""
if isinstance(ast, AndBooleanExpression):
@ -153,8 +160,11 @@ class OrderDedupeTransformer(
"""
Sort/dedupe children. AND and OR can be treated identically.
:param ast: The comparison expression AST
:return: The same AST node, but with sorted children
Args:
ast: The comparison expression AST
Returns:
The same AST node, but with sorted children
"""
sorted_children = sorted(
ast.operands, key=functools.cmp_to_key(comparison_expression_cmp),
@ -201,8 +211,11 @@ class FlattenTransformer(ComparisonExpressionTransformer):
little difference is that we can absorb AND children if we're an AND
ourselves; and OR for OR.
:param ast: The comparison expression AST
:return: The same AST node, but with flattened children
Args:
ast: The comparison expression AST
Returns:
The same AST node, but with flattened children
"""
changed = False

View File

@ -38,8 +38,11 @@ def _dupe_ast(ast):
observation expressions are currently not duplicated. I don't think it's
necessary as of this writing. But revisit this if/when necessary.
:param ast: The AST to duplicate
:return: The duplicate AST
Args:
ast: The AST to duplicate
Returns:
The duplicate AST
"""
if isinstance(ast, AndObservationExpression):
result = AndObservationExpression([
@ -160,8 +163,11 @@ class ObservationExpressionTransformer(Transformer):
Invoke a transformer callback method based on the given ast root node
type.
:param ast: The AST
:return: The callback's result
Args:
ast: The AST
Returns:
The callback's result
"""
dispatch_name = self._DISPATCH_NAME_MAP.get(type(ast))
@ -292,10 +298,12 @@ class AbsorptionTransformer(
the right does not "contain" the left. You would need two A's on the
right.
:param exprs_containee: The expressions we want to check for containment
:param exprs_container: The expressions acting as the "container"
:return: True if the containee is contained in the container; False if
not
Args:
exprs_containee: The expressions we want to check for containment
exprs_container: The expressions acting as the "container"
Returns:
True if the containee is contained in the container; False if not
"""
# make our own list we are free to manipulate without affecting the
@ -336,10 +344,12 @@ class AbsorptionTransformer(
in the container (rhs), B follows A, so it "contains" the lhs even
though there is other stuff mixed in.
:param exprs_containee: The expressions we want to check for containment
:param exprs_container: The expressions acting as the "container"
:return: True if the containee is contained in the container; False if
not
Args:
exprs_containee: The expressions we want to check for containment
exprs_container: The expressions acting as the "container"
Returns:
True if the containee is contained in the container; False if not
"""
ee_iter = iter(exprs_containee)

View File

@ -25,9 +25,12 @@ def _path_is(object_path, path_pattern):
index path step; _ANY_KEY matches any key path step, and _ANY matches any
path step.
:param object_path: An ObjectPath instance
:param path_pattern: An iterable giving the pattern path steps
:return: True if the path matches the pattern; False if not
Args:
object_path: An ObjectPath instance
path_pattern: An iterable giving the pattern path steps
Returns:
True if the path matches the pattern; False if not
"""
path_values = object_path_to_raw_values(object_path)
@ -70,8 +73,9 @@ def _mask_bytes(ip_bytes, prefix_size):
Retain the high-order 'prefix_size' bits from ip_bytes, and zero out the
remaining low-order bits. This side-effects ip_bytes.
:param ip_bytes: A mutable byte sequence (e.g. a bytearray)
:param prefix_size: An integer prefix size
Args:
ip_bytes: A mutable byte sequence (e.g. a bytearray)
prefix_size: An integer prefix size
"""
addr_size_bytes = len(ip_bytes)
addr_size_bits = 8 * addr_size_bytes
@ -99,8 +103,9 @@ def windows_reg_key(comp_expr):
being compared. This enables case-insensitive comparisons between two
patterns, for those values. This side-effects the given AST.
:param comp_expr: A _ComparisonExpression object whose type is
windows-registry-key
Args:
comp_expr: A _ComparisonExpression object whose type is
windows-registry-key
"""
if _path_is(comp_expr.lhs, ("key",)) \
or _path_is(comp_expr.lhs, ("values", _ANY_IDX, "name")):
@ -119,7 +124,8 @@ def ipv4_addr(comp_expr):
This side-effects the given AST.
:param comp_expr: A _ComparisonExpression object whose type is ipv4-addr.
Args:
comp_expr: A _ComparisonExpression object whose type is ipv4-addr.
"""
if _path_is(comp_expr.lhs, ("value",)):
value = comp_expr.rhs.value
@ -179,7 +185,8 @@ def ipv6_addr(comp_expr):
This side-effects the given AST.
:param comp_expr: A _ComparisonExpression object whose type is ipv6-addr.
Args:
comp_expr: A _ComparisonExpression object whose type is ipv6-addr.
"""
if _path_is(comp_expr.lhs, ("value",)):
value = comp_expr.rhs.value