From 6a5f013cfee0331587675f2d761291adc71de6ab Mon Sep 17 00:00:00 2001 From: sydneyli Date: Tue, 10 Dec 2019 12:03:45 -0800 Subject: [PATCH] Account for the case that there are multiple ancestors In the diamond-include case, where a file is included by multiple other files in the configuration tree, nodes can have multiple ancestors. Change interfaces and existing implementations to account for this case. --- certbot-apache/certbot_apache/apacheparser.py | 24 +++---- certbot-apache/certbot_apache/augeasparser.py | 22 +++---- certbot-apache/certbot_apache/configurator.py | 2 +- certbot-apache/certbot_apache/interfaces.py | 26 ++++---- .../certbot_apache/parsernode_util.py | 8 +-- .../certbot_apache/tests/augeasnode_test.py | 8 +-- .../certbot_apache/tests/dualnode_test.py | 64 +++++++++---------- .../tests/parsernode_util_test.py | 8 +-- 8 files changed, 83 insertions(+), 79 deletions(-) diff --git a/certbot-apache/certbot_apache/apacheparser.py b/certbot-apache/certbot_apache/apacheparser.py index 969a4ab69..bdfb1bc7b 100644 --- a/certbot-apache/certbot_apache/apacheparser.py +++ b/certbot-apache/certbot_apache/apacheparser.py @@ -13,9 +13,9 @@ class ApacheParserNode(interfaces.ParserNode): """ def __init__(self, **kwargs): - ancestor, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable + ancestors, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable super(ApacheParserNode, self).__init__(**kwargs) - self.ancestor = ancestor + self.ancestors = ancestors self.filepath = filepath self.dirty = dirty self.metadata = metadata @@ -28,7 +28,7 @@ class ApacheParserNode(interfaces.ParserNode): """Find ancestor BlockNodes with a given name""" return [ApacheBlockNode(name=assertions.PASS, parameters=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata)] @@ -45,7 +45,7 @@ class ApacheCommentNode(ApacheParserNode): if isinstance(other, self.__class__): return (self.comment == other.comment and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata and self.filepath == other.filepath) return False @@ -69,7 +69,7 @@ class ApacheDirectiveNode(ApacheParserNode): self.parameters == other.parameters and self.enabled == other.enabled and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata) return False @@ -93,7 +93,7 @@ class ApacheBlockNode(ApacheDirectiveNode): self.children == other.children and self.enabled == other.enabled and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata) return False @@ -101,7 +101,7 @@ class ApacheBlockNode(ApacheDirectiveNode): """Adds a new BlockNode to the sequence of children""" new_block = ApacheBlockNode(name=assertions.PASS, parameters=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata) self.children += (new_block,) @@ -111,7 +111,7 @@ class ApacheBlockNode(ApacheDirectiveNode): """Adds a new DirectiveNode to the sequence of children""" new_dir = ApacheDirectiveNode(name=assertions.PASS, parameters=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata) self.children += (new_dir,) @@ -122,7 +122,7 @@ class ApacheBlockNode(ApacheDirectiveNode): """Adds a new CommentNode to the sequence of children""" new_comment = ApacheCommentNode(comment=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata) self.children += (new_comment,) @@ -132,7 +132,7 @@ class ApacheBlockNode(ApacheDirectiveNode): """Recursive search of BlockNodes from the sequence of children""" return [ApacheBlockNode(name=assertions.PASS, parameters=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata)] @@ -140,14 +140,14 @@ class ApacheBlockNode(ApacheDirectiveNode): """Recursive search of DirectiveNodes from the sequence of children""" return [ApacheDirectiveNode(name=assertions.PASS, parameters=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata)] def find_comments(self, comment, exact=False): # pylint: disable=unused-argument """Recursive search of DirectiveNodes from the sequence of children""" return [ApacheCommentNode(comment=assertions.PASS, - ancestor=self, + ancestors=self, filepath=assertions.PASS, metadata=self.metadata)] diff --git a/certbot-apache/certbot_apache/augeasparser.py b/certbot-apache/certbot_apache/augeasparser.py index d2771c9d2..ad11958de 100644 --- a/certbot-apache/certbot_apache/augeasparser.py +++ b/certbot-apache/certbot_apache/augeasparser.py @@ -79,9 +79,9 @@ class AugeasParserNode(interfaces.ParserNode): """ Augeas implementation of ParserNode interface """ def __init__(self, **kwargs): - ancestor, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable + ancestors, dirty, filepath, metadata = util.parsernode_kwargs(kwargs) # pylint: disable=unused-variable super(AugeasParserNode, self).__init__(**kwargs) - self.ancestor = ancestor + self.ancestors = ancestors self.filepath = filepath self.dirty = dirty self.metadata = metadata @@ -135,7 +135,7 @@ class AugeasParserNode(interfaces.ParserNode): metadata = {"augeasparser": self.parser, "augeaspath": path} return AugeasBlockNode(name=name, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(path), metadata=metadata) @@ -171,7 +171,7 @@ class AugeasCommentNode(AugeasParserNode): return (self.comment == other.comment and self.filepath == other.filepath and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata) return False @@ -194,7 +194,7 @@ class AugeasDirectiveNode(AugeasParserNode): self.parameters == other.parameters and self.enabled == other.enabled and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata) return False @@ -249,7 +249,7 @@ class AugeasBlockNode(AugeasDirectiveNode): self.children == other.children and self.enabled == other.enabled and self.dirty == other.dirty and - self.ancestor == other.ancestor and + self.ancestors == other.ancestors and self.metadata == other.metadata) return False @@ -269,7 +269,7 @@ class AugeasBlockNode(AugeasDirectiveNode): # Parameters will be set at the initialization of the new object new_block = AugeasBlockNode(name=name, parameters=parameters, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(realpath), metadata=new_metadata) return new_block @@ -294,7 +294,7 @@ class AugeasBlockNode(AugeasDirectiveNode): new_dir = AugeasDirectiveNode(name=name, parameters=parameters, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(realpath), metadata=new_metadata) return new_dir @@ -314,7 +314,7 @@ class AugeasBlockNode(AugeasDirectiveNode): self.parser.aug.set(realpath, comment) new_comment = AugeasCommentNode(comment=comment, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(realpath), metadata=new_metadata) return new_comment @@ -406,7 +406,7 @@ class AugeasBlockNode(AugeasDirectiveNode): # Because of the dynamic nature of AugeasParser and the fact that we're # not populating the complete node tree, the ancestor has a dummy value return AugeasCommentNode(comment=comment, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(path), metadata=metadata) @@ -419,7 +419,7 @@ class AugeasBlockNode(AugeasDirectiveNode): # Because of the dynamic nature, and the fact that we're not populating # the complete ParserNode tree, we use the search parent as ancestor return AugeasDirectiveNode(name=name, - ancestor=assertions.PASS, + ancestors=assertions.PASS, filepath=apache_util.get_file_path(path), metadata=metadata) diff --git a/certbot-apache/certbot_apache/configurator.py b/certbot-apache/certbot_apache/configurator.py index 9a9dec7a8..b5ae5b18f 100644 --- a/certbot-apache/certbot_apache/configurator.py +++ b/certbot-apache/certbot_apache/configurator.py @@ -368,7 +368,7 @@ class ApacheConfigurator(common.Installer): return dualparser.DualBlockNode( name=assertions.PASS, - ancestor=None, + ancestors=tuple(), filepath=self.parser.loc["root"], metadata=metadata ) diff --git a/certbot-apache/certbot_apache/interfaces.py b/certbot-apache/certbot_apache/interfaces.py index 1b67be5c8..9762974a8 100644 --- a/certbot-apache/certbot_apache/interfaces.py +++ b/certbot-apache/certbot_apache/interfaces.py @@ -131,9 +131,10 @@ class ParserNode(object): ParserNode objects should have the following attributes: - # Reference to ancestor node, or None if the node is the root node of the - # configuration tree. - ancestor: Optional[ParserNode] + # Reference to ancestor node(s), empty if the node is the root node of the + # configuration tree. This node can have multiple ancestors in the case + # that it is the root of a file included by multiple files. + ancestors: Tuple[ParserNode] # True if this node has been modified since last save. dirty: bool @@ -156,8 +157,8 @@ class ParserNode(object): instance variables. This is not meant to be used directly, but through specific classes implementing ParserNode interface. - :param ancestor: BlockNode ancestor for this CommentNode. Required. - :type ancestor: BlockNode or None + :param ancestors: BlockNode ancestors for this CommentNode. Required. + :type ancestors: tuple of BlockNodes :param filepath: Filesystem path for the file where this CommentNode does or should exist in the filesystem. Required. @@ -198,6 +199,9 @@ class ParserNode(object): Traverses the ancestor tree up, searching for BlockNodes with a specific name. + When a node has multiple lineages (when it is included by multiple files), + this method should search through all possible ancestor paths. + :param str name: Name of the ancestor BlockNode to search for :returns: A list of ancestor BlockNodes that match the name @@ -233,8 +237,8 @@ class CommentNode(ParserNode): :param comment: Contents of the comment. Required. :type comment: str - :param ancestor: BlockNode ancestor for this CommentNode. Required. - :type ancestor: BlockNode or None + :param ancestors: BlockNode ancestors for this CommentNode. Required. + :type ancestors: tuple of BlockNodes :param filepath: Filesystem path for the file where this CommentNode does or should exist in the filesystem. Required. @@ -244,7 +248,7 @@ class CommentNode(ParserNode): created or changed after the last save. Default: False. :type dirty: bool """ - super(CommentNode, self).__init__(ancestor=kwargs['ancestor'], + super(CommentNode, self).__init__(ancestors=kwargs['ancestors'], dirty=kwargs.get('dirty', False), filepath=kwargs['filepath'], metadata=kwargs.get('metadata', {})) # pragma: no cover @@ -290,9 +294,9 @@ class DirectiveNode(ParserNode): Default: (). :type parameters: tuple - :param ancestor: BlockNode ancestor for this DirectiveNode, or None for + :param ancestors: BlockNode ancestors for this DirectiveNode. Empty for root configuration node. Required. - :type ancestor: BlockNode or None + :type ancestor: tuple of BlockNodes :param filepath: Filesystem path for the file where this DirectiveNode does or should exist in the filesystem, or None for directives introduced @@ -309,7 +313,7 @@ class DirectiveNode(ParserNode): :type enabled: bool """ - super(DirectiveNode, self).__init__(ancestor=kwargs['ancestor'], + super(DirectiveNode, self).__init__(ancestors=kwargs['ancestors'], dirty=kwargs.get('dirty', False), filepath=kwargs['filepath'], metadata=kwargs.get('metadata', {})) # pragma: no cover diff --git a/certbot-apache/certbot_apache/parsernode_util.py b/certbot-apache/certbot_apache/parsernode_util.py index d9646862a..5bd9ca63c 100644 --- a/certbot-apache/certbot_apache/parsernode_util.py +++ b/certbot-apache/certbot_apache/parsernode_util.py @@ -51,8 +51,8 @@ def parsernode_kwargs(kwargs): kwargs.setdefault("dirty", False) kwargs.setdefault("metadata", {}) - kwargs = validate_kwargs(kwargs, ["ancestor", "dirty", "filepath", "metadata"]) - return kwargs["ancestor"], kwargs["dirty"], kwargs["filepath"], kwargs["metadata"] + kwargs = validate_kwargs(kwargs, ["ancestors", "dirty", "filepath", "metadata"]) + return kwargs["ancestors"], kwargs["dirty"], kwargs["filepath"], kwargs["metadata"] def commentnode_kwargs(kwargs): @@ -83,7 +83,7 @@ def commentnode_kwargs(kwargs): kwargs.setdefault("dirty", False) kwargs.setdefault("metadata", {}) - kwargs = validate_kwargs(kwargs, ["ancestor", "dirty", "filepath", "comment", + kwargs = validate_kwargs(kwargs, ["ancestors", "dirty", "filepath", "comment", "metadata"]) comment = kwargs.pop("comment") @@ -120,7 +120,7 @@ def directivenode_kwargs(kwargs): kwargs.setdefault("parameters", ()) kwargs.setdefault("metadata", {}) - kwargs = validate_kwargs(kwargs, ["ancestor", "dirty", "filepath", "name", + kwargs = validate_kwargs(kwargs, ["ancestors", "dirty", "filepath", "name", "parameters", "enabled", "metadata"]) name = kwargs.pop("name") diff --git a/certbot-apache/certbot_apache/tests/augeasnode_test.py b/certbot-apache/certbot_apache/tests/augeasnode_test.py index 849a468c9..34d8a8505 100644 --- a/certbot-apache/certbot_apache/tests/augeasnode_test.py +++ b/certbot-apache/certbot_apache/tests/augeasnode_test.py @@ -36,7 +36,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- from certbot_apache.augeasparser import AugeasBlockNode block = AugeasBlockNode( name=assertions.PASS, - ancestor=None, + ancestors=tuple(), filepath=assertions.PASS, metadata={"augeasparser": mock.Mock(), "augeaspath": "/files/anything"} ) @@ -109,7 +109,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- AugeasDirectiveNode( name=servernames[0].name, parameters=["test", "setting", "these"], - ancestor=assertions.PASS, + ancestors=assertions.PASS, metadata=servernames[0].primary.metadata ) self.assertTrue(mock_set.called) @@ -244,7 +244,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- from certbot_apache.augeasparser import AugeasBlockNode parameters = { "name": assertions.PASS, - "ancestor": None, + "ancestors": tuple(), "filepath": assertions.PASS, "metadata": { "augeasparser": mock.Mock(), @@ -261,7 +261,7 @@ class AugeasParserNodeTest(util.ApacheTest): # pylint: disable=too-many-public- from certbot_apache.augeasparser import AugeasBlockNode parameters = { "name": assertions.PASS, - "ancestor": None, + "ancestors": tuple(), "filepath": assertions.PASS, "metadata": { "augeasparser": mock.Mock(), diff --git a/certbot-apache/certbot_apache/tests/dualnode_test.py b/certbot-apache/certbot_apache/tests/dualnode_test.py index b5ab588f0..92fd7485d 100644 --- a/certbot-apache/certbot_apache/tests/dualnode_test.py +++ b/certbot-apache/certbot_apache/tests/dualnode_test.py @@ -17,35 +17,35 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- parser_mock.get_arg.return_value = [] self.metadata = {"augeasparser": parser_mock, "augeaspath": "/invalid", "ac_ast": None} self.block = dualparser.DualBlockNode(name="block", - ancestor=None, + ancestors=tuple(), filepath="/tmp/something", metadata=self.metadata) self.block_two = dualparser.DualBlockNode(name="block", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", metadata=self.metadata) self.directive = dualparser.DualDirectiveNode(name="directive", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", metadata=self.metadata) self.comment = dualparser.DualCommentNode(comment="comment", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", metadata=self.metadata) def test_create_with_precreated(self): cnode = dualparser.DualCommentNode(comment="comment", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", primary=self.comment.secondary, secondary=self.comment.primary) dnode = dualparser.DualDirectiveNode(name="directive", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", primary=self.directive.secondary, secondary=self.directive.primary) bnode = dualparser.DualBlockNode(name="block", - ancestor=self.block, + ancestors=(self.block), filepath="/tmp/something", primary=self.block.secondary, secondary=self.block.primary) @@ -160,11 +160,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_comments(self): pri_comments = [augeasparser.AugeasCommentNode(comment="some comment", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] sec_comments = [augeasparser.AugeasCommentNode(comment=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_coms_primary = mock.MagicMock(return_value=pri_comments) @@ -186,11 +186,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_blocks_first_passing(self): youshallnotpass = [augeasparser.AugeasBlockNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] youshallpass = [augeasparser.AugeasBlockNode(name=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_blocks_primary = mock.MagicMock(return_value=youshallpass) @@ -209,11 +209,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_blocks_second_passing(self): youshallnotpass = [augeasparser.AugeasBlockNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] youshallpass = [augeasparser.AugeasBlockNode(name=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_blocks_primary = mock.MagicMock(return_value=youshallnotpass) @@ -232,11 +232,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_dirs_first_passing(self): notpassing = [augeasparser.AugeasDirectiveNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] passing = [augeasparser.AugeasDirectiveNode(name=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_dirs_primary = mock.MagicMock(return_value=passing) @@ -255,11 +255,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_dirs_second_passing(self): notpassing = [augeasparser.AugeasDirectiveNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] passing = [augeasparser.AugeasDirectiveNode(name=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_dirs_primary = mock.MagicMock(return_value=notpassing) @@ -278,11 +278,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_coms_first_passing(self): notpassing = [augeasparser.AugeasCommentNode(comment="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] passing = [augeasparser.AugeasCommentNode(comment=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_coms_primary = mock.MagicMock(return_value=passing) @@ -301,11 +301,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_coms_second_passing(self): notpassing = [augeasparser.AugeasCommentNode(comment="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] passing = [augeasparser.AugeasCommentNode(comment=assertions.PASS, - ancestor=self.block, + ancestors=(self.block), filepath=assertions.PASS, metadata=self.metadata)] find_coms_primary = mock.MagicMock(return_value=notpassing) @@ -324,11 +324,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_blocks_no_pass_equal(self): notpassing1 = [augeasparser.AugeasBlockNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] notpassing2 = [augeasparser.AugeasBlockNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] find_blocks_primary = mock.MagicMock(return_value=notpassing1) @@ -343,11 +343,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_dirs_no_pass_equal(self): notpassing1 = [augeasparser.AugeasDirectiveNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] notpassing2 = [augeasparser.AugeasDirectiveNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] find_dirs_primary = mock.MagicMock(return_value=notpassing1) @@ -362,11 +362,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_comments_no_pass_equal(self): notpassing1 = [augeasparser.AugeasCommentNode(comment="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] notpassing2 = [augeasparser.AugeasCommentNode(comment="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] find_coms_primary = mock.MagicMock(return_value=notpassing1) @@ -381,11 +381,11 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_find_blocks_no_pass_notequal(self): notpassing1 = [augeasparser.AugeasBlockNode(name="notpassing", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] notpassing2 = [augeasparser.AugeasBlockNode(name="different", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata)] find_blocks_primary = mock.MagicMock(return_value=notpassing1) @@ -398,15 +398,15 @@ class DualParserNodeTest(unittest.TestCase): # pylint: disable=too-many-public- def test_parsernode_notequal(self): ne_block = augeasparser.AugeasBlockNode(name="different", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata) ne_directive = augeasparser.AugeasDirectiveNode(name="different", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata) ne_comment = augeasparser.AugeasCommentNode(comment="different", - ancestor=self.block, + ancestors=(self.block), filepath="/path/to/whatever", metadata=self.metadata) self.assertFalse(self.block == ne_block) diff --git a/certbot-apache/certbot_apache/tests/parsernode_util_test.py b/certbot-apache/certbot_apache/tests/parsernode_util_test.py index a079759ee..93b98a94f 100644 --- a/certbot-apache/certbot_apache/tests/parsernode_util_test.py +++ b/certbot-apache/certbot_apache/tests/parsernode_util_test.py @@ -10,7 +10,7 @@ class ParserNodeUtilTest(unittest.TestCase): def _setup_parsernode(self): """ Sets up kwargs dict for ParserNode """ return { - "ancestor": None, + "ancestors": tuple(), "dirty": False, "filepath": "/tmp", } @@ -48,8 +48,8 @@ class ParserNodeUtilTest(unittest.TestCase): params = self._setup_parsernode() ctrl = self._setup_parsernode() - ancestor, dirty, filepath, metadata = util.parsernode_kwargs(params) - self.assertEqual(ancestor, ctrl["ancestor"]) + ancestors, dirty, filepath, metadata = util.parsernode_kwargs(params) + self.assertEqual(ancestors, ctrl["ancestors"]) self.assertEqual(dirty, ctrl["dirty"]) self.assertEqual(filepath, ctrl["filepath"]) self.assertEqual(metadata, {}) @@ -103,7 +103,7 @@ class ParserNodeUtilTest(unittest.TestCase): self.assertRaises(TypeError, util.commentnode_kwargs, c_params) d_params = self._setup_directivenode() - d_params.pop("ancestor") + d_params.pop("ancestors") self.assertRaises(TypeError, util.directivenode_kwargs, d_params) p_params = self._setup_parsernode()