def add_item(self, number=None, level=None, reorder=True): """Create a new item for the document and return it. :param number: desired item number :param level: desired item level :param reorder: update levels of document items :return: added :class:`~doorstop.core.item.Item` """ number = max(number or 0, self.next_number) log.debug("next number: {}".format(number)) try: last = self.items[-1] except IndexError: next_level = level else: if level: next_level = level elif last.level.heading: next_level = last.level >> 1 next_level.heading = False else: next_level = last.level + 1 log.debug("next level: {}".format(next_level)) uid = UID(self.prefix, self.sep, number, self.digits) item = Item.new(self.tree, self, self.path, self.root, uid, level=next_level) if level and reorder: self.reorder(keep=item) return item
def add_item(prefix, uid, attrs=None, document=None, request_next_number=None): """Create a Doorstop document from existing document information. :param prefix: previously imported document's prefix :param uid: existing item's UID :param attrs: dictionary of Doorstop and custom attributes :param document: explicit document to add the item :param request_next_number: server method to get a document's next number :return: imported Item """ if document: # Get an explicit tree tree = document.tree assert tree # tree should be set internally else: # Get an implicit tree and document tree = _get_tree(request_next_number=request_next_number) document = tree.find_document(prefix) # Add an item using the specified UID log.info("importing item '{}'...".format(uid)) item = Item.new(tree, document, document.path, document.root, uid, auto=False) for key, value in (attrs or {}).items(): item.set(key, value) item.save() log.info("imported: {}".format(item)) return item
def test_tree_skips_subdocuments_when_skipall_file_present(self): """Verify items can be found using a convenience function.""" temp = tempfile.mkdtemp() cwd = temp root = temp # Step 1: Create a new tree with one item in a document in a subfolder. tree = build(cwd, root) tree.create_document(cwd, 'TST') subfolder = os.path.join(temp, 'SUBFOLDER') os.makedirs(os.path.join(temp, subfolder)) sub_document = tree.create_document(subfolder, 'TST_SUB', parent='TST') item = Item.new(tree, sub_document, subfolder, cwd, "TST_SUB-001") item.save() # Step 2: Put a .doorstop.skip-all into the subfolder. path = os.path.join(subfolder, '.doorstop.skip-all') open(path, 'a').close() # Verify that building tree ignores subfolder's document. same_tree_again = build(cwd, root) self.assertEqual(1, len(same_tree_again.documents))
def test_tree_finds_subdocuments(self): """Verify items can be found using a convenience function.""" temp = tempfile.mkdtemp() cwd = temp root = temp # Step 1: Create a new tree with one item in a document in a subfolder. tree = build(cwd, root) document = tree.create_document(cwd, 'TST') subfolder = os.path.join(temp, 'SUBFOLDER') os.makedirs(os.path.join(temp, subfolder)) sub_document = tree.create_document(subfolder, 'TST_SUB', parent='TST') item = Item.new(tree, sub_document, subfolder, cwd, "TST_SUB-001") item.save() # Step 2: Read existing tree same_tree_again = build(cwd, root) # Verify that the tree has: # - both root-level and subfolder documents # - item in a subdocument self.assertEqual(2, len(same_tree_again.documents)) sub_document = same_tree_again.documents[1] self.assertIsNotNone(document) self.assertEqual(1, len(sub_document.items)) item = sub_document.items[0] self.assertEqual('TST_SUB-001', item.uid)
def add(self): """Create a new item for the document and return it.""" number = self.next logging.debug("next number: {}".format(number)) try: last = self.items[-1] except IndexError: level = None else: level = last.level[:-1] + (last.level[-1] + 1,) logging.debug("next level: {}".format(level)) item = Item.new(self.path, self.root, self.prefix, self.sep, self.digits, number, level=level) self._items.append(item) return item
def add_item(self, number=None, level=None, reorder=True, defaults=None): """Create a new item for the document and return it. :param number: desired item number :param level: desired item level :param reorder: update levels of document items :return: added :class:`~doorstop.core.item.Item` """ number = max(number or 0, self.next_number) log.debug("next number: {}".format(number)) try: last = self.items[-1] except IndexError: next_level = level else: if level: next_level = level elif last.level.heading: next_level = last.level >> 1 next_level.heading = False else: next_level = last.level + 1 log.debug("next level: {}".format(next_level)) # Load more defaults before the item is created to avoid partially # constructed items in case the loading fails. more_defaults = self._load_with_include(defaults) if defaults else None uid = UID(self.prefix, self.sep, number, self.digits) item = Item.new(self.tree, self, self.path, self.root, uid, level=next_level) if self._attribute_defaults: item.set_attributes(self._attribute_defaults) if more_defaults: item.set_attributes(more_defaults) if level and reorder: self.reorder(keep=item) return item
def test_tree_does_not_find_documents_when_skipall_file_present(self): """Verify items can be found using a convenience function.""" temp = tempfile.mkdtemp() cwd = temp root = temp # Step 1: Create a new tree with one item. tree = build(cwd, root) document = tree.create_document(cwd, 'TST') item = Item.new(tree, document, cwd, cwd, "TST-001") item.save() # Step 2: Put a .doorstop.skip-all to the root of the tree. path = os.path.join(temp, '.doorstop.skip-all') open(path, 'a').close() # Step 3: Find a newly created tree same_tree_again = build(cwd, root) # Verify that the tree does not have a document because it was ignored. document = same_tree_again.document self.assertIsNone(document)
def test_tree_finds_documents(self): """Verify items can be found using a convenience function.""" temp = tempfile.mkdtemp() cwd = temp root = temp # Step 1: Create a new tree with one item. tree = build(cwd, root) document = tree.create_document(cwd, 'TST') item = Item.new(tree, document, cwd, cwd, "TST-001") item.save() # Step 2: Find a newly created tree same_tree_again = build(cwd, root) # Verify that that the tree, document and its item can be found. self.assertEqual(1, len(same_tree_again.documents)) document = same_tree_again.document self.assertIsNotNone(document) self.assertEqual(1, len(document.items)) item = document.items[0] self.assertEqual('TST-001', item.uid)
def add_item(self, number=None, level=None, reorder=True, defaults=None, name=None): """Create a new item for the document and return it. :param number: desired item number :param level: desired item level :param reorder: update levels of document items :return: added :class:`~doorstop.core.item.Item` """ uid = None if name is None: number = max(number or 0, self.next_number) log.debug("next number: {}".format(number)) uid = UID(self.prefix, self.sep, number, self.digits) else: try: uid = UID(self.prefix, self.sep, int(name), self.digits) except ValueError: if not self.sep: msg = "cannot add item with name '{}' to document '{}' without a separator".format( name, self.prefix) raise DoorstopError(msg) if self.sep not in settings.SEP_CHARS: msg = "cannot add item with name '{}' to document '{}' with an invalid separator '{}'".format( name, self.prefix, self.sep) raise DoorstopError(msg) uid = UID(self.prefix, self.sep, name) if uid.prefix != self.prefix or uid.name != name: msg = "invalid item name '{}'".format(name) raise DoorstopError(msg) try: last = self.items[-1] except IndexError: next_level = level else: if level: next_level = level elif last.level.heading: next_level = last.level >> 1 next_level.heading = False else: next_level = last.level + 1 log.debug("next level: {}".format(next_level)) # Load more defaults before the item is created to avoid partially # constructed items in case the loading fails. more_defaults = self._load_with_include(defaults) if defaults else None item = Item.new(self.tree, self, self.path, self.root, uid, level=next_level) if self._attribute_defaults: item.set_attributes(self._attribute_defaults) if more_defaults: item.set_attributes(more_defaults) if level and reorder: self.reorder(keep=item) return item