code: def bst(height=3, is_perfect=False):
      
      _validate_tree_height(height)
      if is_perfect:
          return _generate_perfect_bst(height)
  
      values = _generate_random_node_values(height)
      leaf_count = _generate_random_leaf_count(height)
  
      root = Node(values.pop(0))
      leaves = set()
  
      for value in values:
          node = root
          depth = 0
          inserted = False
  
          while depth < height and not inserted:
              attr = 'left' if node.value > value else 'right'
              if getattr(node, attr) is None:
                  setattr(node, attr, Node(value))
                  inserted = True
              node = getattr(node, attr)
              depth += 1
  
          if inserted and depth == height:
              leaves.add(node)
          if len(leaves) == leaf_count:
              break
  
      return root
docs: Generate a random BST (binary search tree) and return its root node.
  
      :param height: Height of the BST (default: 3, range: 0 - 9 inclusive).
      :type height: int
      :param is_perfect: If set to True (default: False), a perfect BST with all
          levels filled is returned. If set to False, a perfect BST may still be
          generated by chance.
      :type is_perfect: bool
      :return: Root node of the BST.
      :rtype: binarytree.Node
      :raise binarytree.exceptions.TreeHeightError: If height is invalid.
  
      **Example**:
  
      .. doctest::
  
          >>> from binarytree import bst
          >>>
          >>> root = bst()
          >>>
          >>> root.height
          3
          >>> root.is_bst
          True
  
      .. doctest::
  
          >>> from binarytree import bst
          >>>
          >>> root = bst(10)  # doctest: +IGNORE_EXCEPTION_DETAIL
          Traceback (most recent call last):
           ...
          TreeHeightError: height must be an int between 0 - 9