Yields molecules generated from CTAB text

    Args:
        lines (iterable): CTAB text lines
        no_halt (boolean):
            True: shows warning messages for invalid format and go on.
            False: throws an exception for it and stop parsing.
        assign_descriptors (boolean):
            if True, default descriptors are automatically assigned.

def mol_supplier(lines, no_halt, assign_descriptors):
    """Yields molecules generated from CTAB text

    Args:
        lines (iterable): CTAB text lines
        no_halt (boolean):
            True: shows warning messages for invalid format and go on.
            False: throws an exception for it and stop parsing.
        assign_descriptors (boolean):
            if True, default descriptors are automatically assigned.
    """
    def sdf_block(lns):
        mol = []
        opt = []
        is_mol = True
        for line in lns:
            if line.startswith("$$$$"):
                yield mol[:], opt[:]
                is_mol = True
                mol.clear()
                opt.clear()
            elif line.startswith("M  END"):
                is_mol = False
            elif is_mol:
                mol.append(line.rstrip())
            else:
                opt.append(line.rstrip())
        if mol:
            yield mol, opt

    for i, (mol, opt) in enumerate(sdf_block(lines)):
        try:
            c = molecule(mol)
            if assign_descriptors:
                molutil.assign_descriptors(c)
        except ValueError as err:
            if no_halt:
                print("Unsupported symbol: {} (#{} in v2000reader)".format(
                      err, i + 1))
                c = molutil.null_molecule(assign_descriptors)
            else:
                raise ValueError("Unsupported symbol: {}".format(err))
        except RuntimeError as err:
            if no_halt:
                print(
                    "Failed to minimize ring: {} (#{} in v2000reader)".format(
                        err, i + 1)
                )
            else:
                raise RuntimeError("Failed to minimize ring: {}".format(err))
        except:
            if no_halt:
                print("Unexpected error (#{} in v2000reader)".format(i + 1))
                c = molutil.null_molecule(assign_descriptors)
                c.data = optional_data(opt)
                yield c
                continue
            else:
                print(traceback.format_exc())
                raise Exception("Unsupported Error")
        c.data = optional_data(opt)
        yield c