diff --git a/setools/policyrep/constraint.pxi b/setools/policyrep/constraint.pxi index 9e1f6aa..1277c32 100644 --- a/setools/policyrep/constraint.pxi +++ b/setools/policyrep/constraint.pxi @@ -202,7 +202,7 @@ cdef class Constraint(BaseConstraint): elif expr_node.users: users.extend(expr_node.names) - c._postfix_expression.extend(expr_node()) + c._postfix_expression.extend(expr_node) c.users = frozenset(users) c.roles = frozenset(roles) @@ -256,7 +256,7 @@ cdef class Validatetrans(BaseConstraint): elif expr_node.users: users.extend(expr_node.names) - v._postfix_expression.extend(expr_node()) + v._postfix_expression.extend(expr_node) v.users = frozenset(users) v.roles = frozenset(roles) @@ -275,7 +275,14 @@ cdef class Validatetrans(BaseConstraint): cdef class ConstraintExprNode(PolicySymbol): - """A node of a constraint expression.""" + """ + A node of a constraint expression. + + This is an immutable list-like object that contains one node + of a constraint in postfix notation, e.g.: + + ["u1", "u2", "=="] + """ cdef: sepol.constraint_expr_t *handle @@ -378,33 +385,42 @@ cdef class ConstraintExprNode(PolicySymbol): except AttributeError: pass - return n - - def __call__(self): - expression = [] - - if self.expression_type == sepol.CEXPR_ATTR: + # + # Build expression + # + if n.expression_type == sepol.CEXPR_ATTR: # logical operator with symbols (e.g. u1 == u2) - operand1 = self._sym_to_text[self.symbol_type] - operand2 = self._sym_to_text[self.symbol_type + sepol.CEXPR_TARGET] - operator = self._expr_op_to_text[self.operator] + operand1 = n._sym_to_text[n.symbol_type] + operand2 = n._sym_to_text[n.symbol_type + sepol.CEXPR_TARGET] + operator = n._expr_op_to_text[n.operator] - expression.extend([operand1, operand2, operator]) + n._expression = [operand1, operand2, operator] - elif self.expression_type == sepol.CEXPR_NAMES: + elif n.expression_type == sepol.CEXPR_NAMES: # logical operator with type or attribute list (e.g. t1 == { spam_t eggs_t }) - operand1 = self._sym_to_text[self.symbol_type] - operator = self._expr_op_to_text[self.operator] - operand2 = self.names + operand1 = n._sym_to_text[n.symbol_type] + operand2 = n.names + operator = n._expr_op_to_text[n.operator] - expression.extend([operand1, operand2, operator]) + n._expression = [operand1, operand2, operator] else: # individual operators (and/or/not) - expression.append(self._expr_type_to_text[self.expression_type]) + n._expression = [n._expr_type_to_text[n.expression_type]] - return expression + return n + def __iter__(self): + return iter(self._expression) + + def __contains__(self, item): + return item in self._expression + + def __len__(self): + return len(self._expression) + + def __getitem__(self, idx): + return self._expression[idx] @property def names(self):