def _reorder_automatic(items, start=None, keep=None): """Reorder a document's items automatically. :param items: items to reorder :param start: level to start numbering (None = use current start) :param keep: item to keep over duplicates """ nlevel = plevel = None for clevel, item in Document._items_by_level(items, keep=keep): log.debug("current level: {}".format(clevel)) # Determine the next level if not nlevel: # Use the specified or current starting level nlevel = Level(start) if start else clevel nlevel.heading = clevel.heading log.debug("next level (start): {}".format(nlevel)) else: # Adjust the next level to be the same depth if len(clevel) > len(nlevel): nlevel >>= len(clevel) - len(nlevel) log.debug("matched current indent: {}".format(nlevel)) elif len(clevel) < len(nlevel): nlevel <<= len(nlevel) - len(clevel) # nlevel += 1 log.debug("matched current dedent: {}".format(nlevel)) nlevel.heading = clevel.heading # Check for a level jump _size = min(len(clevel.value), len(plevel.value)) for index in range(max(_size - 1, 1)): if clevel.value[index] > plevel.value[index]: nlevel <<= len(nlevel) - 1 - index nlevel += 1 nlevel >>= len(clevel) - len(nlevel) msg = "next level (jump): {}".format(nlevel) log.debug(msg) break # Check for a normal increment else: if len(nlevel) <= len(plevel): nlevel += 1 msg = "next level (increment): {}".format(nlevel) log.debug(msg) else: msg = "next level (indent/dedent): {}".format(nlevel) log.debug(msg) # Apply the next level if clevel == nlevel: log.info("{}: {}".format(item, clevel)) else: log.info("{}: {} to {}".format(item, clevel, nlevel)) item.level = nlevel.copy() # Save the current level as the previous level plevel = clevel.copy()
class TestLevel(unittest.TestCase): """Unit tests for the Level class.""" # pylint: disable=W0212 def setUp(self): self.level_1 = Level('1') self.level_1_2 = Level('1.2') self.level_1_2_heading = Level('1.2.0') self.level_1_2_3 = Level('1.2.3') def test_init(self): """Verify levels can be parsed.""" self.assertEqual((1, 0), Level((1, 0)).value) self.assertEqual((1,), Level((1)).value) self.assertEqual((1,), Level(()).value) self.assertEqual((1, 0), Level(Level('1.0')).value) self.assertEqual((1, 0), Level(1, heading=True).value) self.assertEqual((1,), Level((1, 0), heading=False).value) def test_repr(self): """Verify levels can be represented.""" self.assertEqual("Level('1')", repr(self.level_1)) self.assertEqual("Level('1.2')", repr(self.level_1_2)) self.assertEqual("Level('1.2', heading=True)", repr(self.level_1_2_heading)) self.assertEqual("Level('1.2.3')", repr(self.level_1_2_3)) def test_str(self): """Verify levels can be converted to strings.""" self.assertEqual('1', str(self.level_1)) self.assertEqual('1.2', str(self.level_1_2)) self.assertEqual('1.2.0', str(self.level_1_2_heading)) self.assertEqual('1.2.3', str(self.level_1_2_3)) def test_len(self): """Verify a level length is equal to number of non-heading parts.""" self.assertEqual(1, len(self.level_1)) self.assertEqual(2, len(self.level_1_2)) self.assertEqual(2, len(self.level_1_2_heading)) self.assertEqual(3, len(self.level_1_2_3)) def test_eq(self): """Verify levels can be equated.""" self.assertNotEqual(self.level_1, self.level_1_2) self.assertEqual(self.level_1_2, Level([1, 2])) self.assertEqual(self.level_1_2, (1, 2)) self.assertEqual(self.level_1_2, self.level_1_2_heading) def test_eq_other(self): """Verify levels can be equated with non-levels.""" self.assertNotEqual(self.level_1, None) self.assertEqual((1, 2, 0), self.level_1_2_heading) self.assertEqual((1, 2), self.level_1_2_heading) def test_compare(self): """Verify levels can be compared.""" self.assertLess(self.level_1, self.level_1_2) self.assertLessEqual(self.level_1, self.level_1) self.assertLessEqual(self.level_1, self.level_1_2) self.assertLess(self.level_1_2, [1, 3]) self.assertGreater(self.level_1_2_3, self.level_1_2) self.assertGreaterEqual(self.level_1_2_3, self.level_1_2) self.assertGreaterEqual(self.level_1_2_3, self.level_1_2_3) def test_hash(self): """Verify level's can be hashed.""" levels = {Level('1.2'): 1, Level('1.2.3'): 2} self.assertIn(self.level_1_2, levels) self.assertNotIn(self.level_1_2_heading, levels) def test_add(self): """Verify levels can be incremented.""" level = self.level_1_2 level += 1 self.assertEqual(Level('1.3'), level) self.assertEqual(Level('1.5'), level + 2) def test_add_heading(self): """Verify (heading) levels can be incremented.""" level = self.level_1_2_heading level += 2 self.assertEqual(Level('1.4.0'), level) def test_sub(self): """Verify levels can be decremented.""" level = self.level_1_2_3 level -= 1 self.assertEqual(Level('1.2.2'), level) self.assertEqual(Level('1.2.1'), level - 1) def test_sub_heading(self): """Verify (heading) levels can be decremented.""" level = self.level_1_2_heading level -= 1 self.assertEqual(Level('1.1.0'), level) def test_sub_zero(self): """Verify levels cannot be decremented to zero.""" level = self.level_1_2 level -= 2 self.assertEqual(Level('1.1'), level) def test_rshift(self): """Verify levels can be indented.""" level = self.level_1_2 level >>= 1 self.assertEqual(Level('1.2.1'), level) self.assertEqual(Level('1.2.1.1'), level >> 1) def test_rshift_heading(self): """Verify (heading) levels can be indented.""" level = self.level_1_2_heading level >>= 2 self.assertEqual(Level('1.2.1.1.0'), level) def test_rshift_negative(self): """Verify levels can be indented negatively.""" level = self.level_1_2_3 level >>= -1 self.assertEqual(Level('1.2'), level) self.assertEqual(Level('1'), level >> -1) def test_lshift(self): """Verify levels can be dedented.""" level = self.level_1_2_3 level <<= 1 self.assertEqual(Level('1.2'), level) self.assertEqual(Level('1'), level << 1) def test_lshift_heading(self): """Verify (heading) levels can be dedented.""" level = self.level_1_2_heading level <<= 1 self.assertEqual(Level('1.0'), level) def test_lshift_negative(self): """Verify levels can be dedented negatively.""" level = self.level_1_2_3 level <<= -1 self.assertEqual(Level('1.2.3.1'), level) self.assertEqual(Level('1.2.3.1.1'), level << -1) def test_lshift_empty(self): """Verify levels can be dedented.""" level = self.level_1_2_3 level <<= 4 self.assertEqual(Level('1'), level) def test_lshift_zero(self): """Verify detenting levels by zero has no effect..""" level = self.level_1_2_3 level <<= 0 self.assertEqual(Level('1.2.3'), level) def test_value(self): """Verify levels can be converted to their values.""" self.assertEqual((1,), self.level_1.value) self.assertEqual((1, 2), self.level_1_2.value) self.assertEqual((1, 2, 0), self.level_1_2_heading.value) self.assertEqual((1, 2, 3), self.level_1_2_3.value) def test_yaml(self): """Verify levels can be converted to their YAML representation.""" self.assertEqual(1, self.level_1.yaml) self.assertEqual(1.2, self.level_1_2.yaml) self.assertEqual('1.2.0', self.level_1_2_heading.yaml) self.assertEqual('1.2.3', self.level_1_2_3.yaml) def test_copy(self): """Verify levels can be copied.""" level = self.level_1_2.copy() self.assertEqual(level, self.level_1_2) level += 1 self.assertNotEqual(level, self.level_1_2)
class TestLevel(unittest.TestCase): """Unit tests for the Level class.""" # pylint: disable=W0212 def setUp(self): self.level_1 = Level('1') self.level_1_2 = Level('1.2') self.level_1_2_heading = Level('1.2.0') self.level_1_2_3 = Level('1.2.3') def test_init(self): """Verify levels can be parsed.""" self.assertEqual((1, 0), Level((1, 0)).value) self.assertEqual((1, ), Level((1)).value) self.assertEqual((1, 0), Level(Level('1.0')).value) self.assertEqual((1, 0), Level(1, heading=True).value) self.assertEqual((1, ), Level((1, 0), heading=False).value) self.assertEqual((1, ), Level()) self.assertEqual((1, ), Level(None)) self.assertEqual((1, ), Level(()).value) self.assertEqual((1, ), Level(0).value) self.assertEqual((1, ), Level('').value) self.assertEqual((0, ), Level((0, )).value) self.assertEqual((0, ), Level('0').value) self.assertEqual((0, ), Level('0.0').value) def test_repr(self): """Verify levels can be represented.""" self.assertEqual("Level('1')", repr(self.level_1)) self.assertEqual("Level('1.2')", repr(self.level_1_2)) self.assertEqual("Level('1.2', heading=True)", repr(self.level_1_2_heading)) self.assertEqual("Level('1.2.3')", repr(self.level_1_2_3)) def test_str(self): """Verify levels can be converted to strings.""" self.assertEqual('1', str(self.level_1)) self.assertEqual('1.2', str(self.level_1_2)) self.assertEqual('1.2.0', str(self.level_1_2_heading)) self.assertEqual('1.2.3', str(self.level_1_2_3)) def test_len(self): """Verify a level length is equal to number of non-heading parts.""" self.assertEqual(1, len(self.level_1)) self.assertEqual(2, len(self.level_1_2)) self.assertEqual(2, len(self.level_1_2_heading)) self.assertEqual(3, len(self.level_1_2_3)) def test_eq(self): """Verify levels can be equated.""" self.assertNotEqual(self.level_1, self.level_1_2) self.assertEqual(self.level_1_2, Level([1, 2])) self.assertEqual(self.level_1_2, (1, 2)) self.assertEqual(self.level_1_2, self.level_1_2_heading) def test_eq_other(self): """Verify levels can be equated with non-levels.""" self.assertNotEqual(self.level_1, None) self.assertEqual((1, 2, 0), self.level_1_2_heading) self.assertEqual((1, 2), self.level_1_2_heading) def test_compare(self): """Verify levels can be compared.""" self.assertLess(self.level_1, self.level_1_2) self.assertLessEqual(self.level_1, self.level_1) self.assertLessEqual(self.level_1, self.level_1_2) self.assertLess(self.level_1_2, [1, 3]) self.assertGreater(self.level_1_2_3, self.level_1_2) self.assertGreaterEqual(self.level_1_2_3, self.level_1_2) self.assertGreaterEqual(self.level_1_2_3, self.level_1_2_3) def test_hash(self): """Verify level's can be hashed.""" levels = {Level('1.2'): 1, Level('1.2.3'): 2} self.assertIn(self.level_1_2, levels) self.assertNotIn(self.level_1_2_heading, levels) def test_add(self): """Verify levels can be incremented.""" level = self.level_1_2 level += 1 self.assertEqual(Level('1.3'), level) self.assertEqual(Level('1.5'), level + 2) def test_add_heading(self): """Verify (heading) levels can be incremented.""" level = self.level_1_2_heading level += 2 self.assertEqual(Level('1.4.0'), level) def test_sub(self): """Verify levels can be decremented.""" level = self.level_1_2_3 level -= 1 self.assertEqual(Level('1.2.2'), level) self.assertEqual(Level('1.2.1'), level - 1) def test_sub_heading(self): """Verify (heading) levels can be decremented.""" level = self.level_1_2_heading level -= 1 self.assertEqual(Level('1.1.0'), level) def test_sub_zero(self): """Verify levels cannot be decremented to zero.""" level = self.level_1_2 level -= 2 self.assertEqual(Level('1.1'), level) def test_rshift(self): """Verify levels can be indented.""" level = self.level_1_2 level >>= 1 self.assertEqual(Level('1.2.1'), level) self.assertEqual(Level('1.2.1.1'), level >> 1) def test_rshift_heading(self): """Verify (heading) levels can be indented.""" level = self.level_1_2_heading level >>= 2 self.assertEqual(Level('1.2.1.1.0'), level) def test_rshift_negative(self): """Verify levels can be indented negatively.""" level = self.level_1_2_3 level >>= -1 self.assertEqual(Level('1.2'), level) self.assertEqual(Level('1'), level >> -1) def test_lshift(self): """Verify levels can be dedented.""" level = self.level_1_2_3 level <<= 1 self.assertEqual(Level('1.2'), level) self.assertEqual(Level('1'), level << 1) def test_lshift_heading(self): """Verify (heading) levels can be dedented.""" level = self.level_1_2_heading level <<= 1 self.assertEqual(Level('1.0'), level) def test_lshift_negative(self): """Verify levels can be dedented negatively.""" level = self.level_1_2_3 level <<= -1 self.assertEqual(Level('1.2.3.1'), level) self.assertEqual(Level('1.2.3.1.1'), level << -1) def test_lshift_empty(self): """Verify levels can be dedented.""" level = self.level_1_2_3 level <<= 4 self.assertEqual(Level('1'), level) def test_lshift_zero(self): """Verify detenting levels by zero has no effect..""" level = self.level_1_2_3 level <<= 0 self.assertEqual(Level('1.2.3'), level) def test_value(self): """Verify levels can be converted to their values.""" self.assertEqual((1, ), self.level_1.value) self.assertEqual((1, 2), self.level_1_2.value) self.assertEqual((1, 2, 0), self.level_1_2_heading.value) self.assertEqual((1, 2, 3), self.level_1_2_3.value) def test_yaml(self): """Verify levels can be converted to their YAML representation.""" self.assertEqual(1, self.level_1.yaml) self.assertEqual(1.2, self.level_1_2.yaml) self.assertEqual('1.2.0', self.level_1_2_heading.yaml) self.assertEqual('1.2.3', self.level_1_2_3.yaml) def test_copy(self): """Verify levels can be copied.""" level = self.level_1_2.copy() self.assertEqual(level, self.level_1_2) level += 1 self.assertNotEqual(level, self.level_1_2)