def test_reorder_automatic_with_start(self): """Verify items can be reordered with a given start.""" mock_item = Mock(level=Level('2.3')) mock_items = [Mock(level=Level('2.2')), mock_item, Mock(level=Level('2.3')), Mock(level=Level('2.7')), Mock(level=Level('3.2.2')), Mock(level=Level('3.4.2')), Mock(level=Level('3.5.0')), Mock(level=Level('3.5.0')), Mock(level=Level('3.6')), Mock(level=Level('5.0')), Mock(level=Level('5.9'))] expected = [Level('1.2'), Level('1.3'), Level('1.4'), Level('1.5'), Level('2.1.1'), Level('2.2.1'), Level('2.3.0'), Level('2.4.0'), Level('2.5'), Level('3.0'), Level('3.1')] Document._reorder_automatic(mock_items, start=(1, 2), keep=mock_item) actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_reorder_automatic(self): """Verify items can be reordered automatically.""" mock_items = [Mock(level=Level('2.3')), Mock(level=Level('2.3')), Mock(level=Level('2.7')), Mock(level=Level('3.2.2')), Mock(level=Level('3.4.2')), Mock(level=Level('3.5.0')), Mock(level=Level('3.5.0')), Mock(level=Level('3.6')), Mock(level=Level('5.0')), Mock(level=Level('5.9'))] expected = [Level('2.3'), Level('2.4'), Level('2.5'), Level('3.1.1'), Level('3.2.1'), Level('3.3.0'), Level('3.4.0'), Level('3.5'), Level('4.0'), Level('4.1')] Document._reorder_automatic(mock_items) actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_reorder_automatic(self): """Verify items can be reordered automatically.""" mock_items = [ Mock(level=Level('2.3')), Mock(level=Level('2.3')), Mock(level=Level('2.7')), Mock(level=Level('3.2.2')), Mock(level=Level('3.4.2')), Mock(level=Level('3.5.0')), Mock(level=Level('3.5.0')), Mock(level=Level('3.6')), Mock(level=Level('5.0')), Mock(level=Level('5.9')) ] expected = [ Level('2.3'), Level('2.4'), Level('2.5'), Level('3.1.1'), Level('3.2.1'), Level('3.3.0'), Level('3.4.0'), Level('3.5'), Level('4.0'), Level('4.1') ] Document._reorder_automatic(mock_items) actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_reorder_from_index_add(self): """Verify items can be added when reordering from an index.""" data = { 'initial': 2.0, 'outline': [ {'a': None}, { 'b': [ {'ba': [{'baa': None}, {'new': None}, {'bac': None}]}, {'bb': [{'new': [{'text': 'item_text'}]}]}, ] }, {'c': None}, ], } expected = [ Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.2'), Level('3.1.3'), Level('3.2.0'), Level('3.2.1'), Level('4'), ] # Act self.document._read_index = MagicMock(return_value=data) Document._reorder_from_index(self.document, 'mock_path') # Assert self.document._read_index.assert_called_once_with('mock_path') actual = [item.level for item in self.document.items] self.assertListEqual(expected, actual) self.assertEqual(self.document.items[-2].text, 'item_text')
def test_reorder_automatic_with_start(self): """Verify items can be reordered with a given start.""" mock_item = Mock(level=Level('2.3')) mock_items = [ Mock(level=Level('2.2')), mock_item, Mock(level=Level('2.3')), Mock(level=Level('2.7')), Mock(level=Level('3.2.2')), Mock(level=Level('3.4.2')), Mock(level=Level('3.5.0')), Mock(level=Level('3.5.0')), Mock(level=Level('3.6')), Mock(level=Level('5.0')), Mock(level=Level('5.9')) ] expected = [ Level('1.2'), Level('1.3'), Level('1.4'), Level('1.5'), Level('2.1.1'), Level('2.2.1'), Level('2.3.0'), Level('2.4.0'), Level('2.5'), Level('3.0'), Level('3.1') ] Document._reorder_automatic(mock_items, start=(1, 2), keep=mock_item) actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_reorder_from_index_add(self): """Verify items can be added when reordering from an index.""" data = {'initial': 2.0, 'outline': [ {'a': None}, {'b': [ {'ba': [ {'baa': None}, {'new': None}, {'bac': None}]}, {'bb': [ {'new': [{'text': 'item_text'}]}]}]}, {'c': None}]} expected = [Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.2'), Level('3.1.3'), Level('3.2.0'), Level('3.2.1'), Level('4')] # Act self.document._read_index = MagicMock(return_value=data) Document._reorder_from_index(self.document, 'mock_path') # Assert self.document._read_index.assert_called_once_with('mock_path') actual = [item.level for item in self.document.items] self.assertListEqual(expected, actual) self.assertEqual(self.document.items[-2].text, 'item_text')
def test_reorder_from_index(self): """Verify items can be reordered from an index.""" mock_items = [] def mock_find_item(uid): """Return a mock item and store it.""" mock_item = MagicMock() if uid == 'bb': mock_item.level = Level('3.2') elif uid == 'bab': raise DoorstopError("unknown UID: bab") mock_item.uid = uid mock_items.append(mock_item) return mock_item mock_document = Mock() mock_document.find_item = mock_find_item data = { 'initial': 2.0, 'outline': [{ 'a': None }, { 'b': [{ 'ba': [{ 'baa': None }, { 'bab': None }, { 'bac': None }] }, { 'bb': None }] }, { 'c': None }] } expected = [ Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.3'), Level('3.2'), Level('4') ] # Act with patch('doorstop.common.read_text') as mock_read_text: with patch('doorstop.common.load_yaml', Mock(return_value=data)): Document._reorder_from_index(mock_document, 'mock_path') # Assert mock_read_text.assert_called_once_with('mock_path') actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_reorder_from_index_delete(self): """Verify items can be deleted when reordering from an index.""" data = { 'initial': 2.0, 'outline': [{ 'a': None }, { 'b': [{ 'ba': [{ 'baa': None }, { 'bab': None }, { 'bac': None }] }, { 'bb': [{ 'bba': None }] }] }, { 'c': None }] } expected = [ Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.2'), Level('3.1.3'), Level('3.2.0'), Level('3.2.1'), Level('4') ] mock_item = self.document.add_item() # Act self.document._read_index = MagicMock(return_value=data) Document._reorder_from_index(self.document, 'mock_path') # Assert self.document._read_index.assert_called_once_with('mock_path') items = [] for item in self.document.items: if item is not mock_item: items.append(item) actual = [item.level for item in items] self.assertListEqual(expected, actual) self.assertEqual(mock_item.method_calls, [call.delete()])
def test_reorder_automatic_no_change(self): """Verify already ordered items can be reordered.""" mock_items = [Mock(level=Level('1.1')), Mock(level=Level('1.1.1.1')), Mock(level=Level('2')), Mock(level=Level('3')), Mock(level=Level('4.1.1'))] expected = [Level('1.1'), Level('1.1.1.1'), Level('2'), Level('3'), Level('4.1.1')] Document._reorder_automatic(mock_items) actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def create_document(self, path, value, sep=None, digits=None, parent=None): # pylint: disable=R0913 """Create a new document and add it to the tree. :param path: directory path for the new document :param value: document or prefix :param sep: separator between prefix and numbers :param digits: number of digits for the document's numbers :param parent: parent document's prefix :raises: :class:`~doorstop.common.DoorstopError` if the document cannot be created :return: newly created and placed document :class:`~doorstop.core.document.Document` """ prefix = Prefix(value) document = Document.new(self, path, self.root, prefix, sep=sep, digits=digits, parent=parent) try: self._place(document) except DoorstopError: msg = "deleting unplaced directory {}...".format(document.path) log.debug(msg) document.delete() raise else: log.info("added to tree: {}".format(document)) return document
def create_document(prefix, path, parent=None, tree=None): """Create a Doorstop document from existing document information. :param prefix: existing document's prefix (for new items) :param path: new directory path to store this document's items :param parent: parent document's prefix (if one will exist) :param tree: explicit tree to add the document :return: imported Document """ if not tree: tree = _get_tree() # Attempt to create a document with the given parent log.info("importing document '{}'...".format(prefix)) try: document = tree.create_document(path, prefix, parent=parent) except DoorstopError as exc: if not parent: raise exc from None # Create the document despite an unavailable parent document = Document.new(tree, path, tree.root, prefix, parent=parent) log.warning(exc) _documents.append(document) # TODO: attempt to place unplaced documents? log.info("imported: {}".format(document)) return document
def test_reorder_from_index(self): """Verify items can be reordered from an index.""" mock_items = [] def mock_find_item(uid): """Return a mock item and store it.""" mock_item = MagicMock() if uid == 'bb': mock_item.level = Level('3.2') elif uid == 'bab': raise DoorstopError("unknown UID: bab") mock_item.uid = uid mock_items.append(mock_item) return mock_item mock_document = Mock() mock_document.find_item = mock_find_item data = {'initial': 2.0, 'outline': [ {'a': None}, {'b': [ {'ba': [ {'baa': None}, {'bab': None}, {'bac': None}]}, {'bb': None}]}, {'c': None}]} expected = [Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.3'), Level('3.2'), Level('4')] # Act with patch('doorstop.common.read_text') as mock_read_text: with patch('doorstop.common.load_yaml', Mock(return_value=data)): Document._reorder_from_index(mock_document, 'mock_path') # Assert mock_read_text.assert_called_once_with('mock_path') actual = [item.level for item in mock_items] self.assertListEqual(expected, actual)
def test_publish_document_template(self, mock_publish): """Verify 'doorstop publish' is called with template.""" path = os.path.join(self.temp, 'req.html') self.assertIs( None, main(['publish', '--template', 'my_template.html', 'req', path]) ) mock_publish.assert_called_once_with( Document(os.path.abspath(REQS)), path, '.html', template='my_template.html' )
def setUp(self): document = Document(SYS) self.tree = Tree(document) document.tree = self.tree document = Document(FILES) self.tree._place(document) # pylint: disable=W0212 document.tree = self.tree
def test_reorder_from_index_delete(self): """Verify items can be deleted when reordering from an index.""" data = {'initial': 2.0, 'outline': [ {'a': None}, {'b': [ {'ba': [ {'baa': None}, {'bab': None}, {'bac': None}]}, {'bb': [ {'bba': None}]}]}, {'c': None}]} expected = [Level('2'), Level('3.0'), Level('3.1.0'), Level('3.1.1'), Level('3.1.2'), Level('3.1.3'), Level('3.2.0'), Level('3.2.1'), Level('4')] mock_item = self.document.add_item() # Act self.document._read_index = MagicMock(return_value=data) Document._reorder_from_index(self.document, 'mock_path') # Assert self.document._read_index.assert_called_once_with('mock_path') items = [] for item in self.document.items: if item is not mock_item: items.append(item) actual = [item.level for item in items] self.assertListEqual(expected, actual) self.assertEqual(mock_item.method_calls, [call.delete()])
def _document_from_path(path, root, documents): """Attempt to create and append a document from the specified path. :param path: path to a potential document :param root: path to root of working copy :param documents: list of :class:`~doorstop.core.document.Document` to append results """ try: document = Document(path, root, tree=None) # tree attached later except DoorstopError: pass # no document in directory else: if document.skip: log.debug("skipped document: {}".format(document)) else: log.info("found document: {}".format(document)) documents.append(document)
def test_publish_document_to_stdout(self, mock_publish_lines): """Verify 'doorstop publish_lines' is called when no output path specified""" self.assertIs(None, main(['publish', 'req'])) mock_publish_lines.assert_called_once_with( Document(os.path.abspath(REQS)), '.txt')