# Path: crumbs/utils/optional_modules.py
# MSG = 'A python package to run this executable is required,'
# BIO = 'biopython'
# BIO_BGZF = 'biopython with Bgzf support'
#     NCBIXML = create_fake_class(MSG + BIO)
#     NCBIWWW = create_fake_class(MSG + BIO)
# def create_fake_class(msg):
#         def __init__(self, *args, **kwargs):
# def create_fake_funct(msg):
#     def FakeRequiredfunct(*args, **kwargs):
#     class FakePythonRequiredClass(object):
# 
# Path: crumbs/exceptions.py
# class SampleSizeError(Exception):
#     'The asked sample size is bigger than the population'
#     pass


import random
import cPickle as pickle
import sqlite3
from itertools import izip_longest, islice, tee, izip
from tempfile import NamedTemporaryFile
from collections import namedtuple
from crumbs.utils.optional_modules import merge_sorted
from crumbs.exceptions import SampleSizeError


def sample(iterator, sample_size, in_disk=False):
    '''It makes a sample from the given iterator.

    It does not keep the order.
    Since it does not know before hand the size of the iterator it has to
    keep a buffer as large as the sample size in memory (default) or in disk.
    '''
    # This implementation holds the sampled items in memory
    # Example of the algorithm seen in:
    # http://nedbatchelder.com/blog/201208/selecting_randomly_from_an_unknown_
    # sequence.html
    # See also:
    # http://stackoverflow.com/questions/12128948/python-random-lines-from-
    # subfolders/

    if in_disk:
        sample_ = _ListLikeDb()
    else:
        sample_ = []
    too_big_sample = True
    for index, elem in enumerate(iterator):
        if len(sample_) < sample_size:
            sample_.append(elem)
        else:
            too_big_sample = False
            if random.randint(0, index) < sample_size:
                sample_[random.randint(0, sample_size - 1)] = elem
    if too_big_sample:

# Path: crumbs/utils/optional_modules.py
# MSG = 'A python package to run this executable is required,'
# BIO = 'biopython'
# BIO_BGZF = 'biopython with Bgzf support'
#     NCBIXML = create_fake_class(MSG + BIO)
#     NCBIWWW = create_fake_class(MSG + BIO)
# def create_fake_class(msg):
#         def __init__(self, *args, **kwargs):
# def create_fake_funct(msg):
#     def FakeRequiredfunct(*args, **kwargs):
#     class FakePythonRequiredClass(object):
# 
# Path: crumbs/exceptions.py
# class SampleSizeError(Exception):
#     'The asked sample size is bigger than the population'
#     pass


# Path: crumbs/iterutils.py
import random
import cPickle as pickle
import sqlite3
from itertools import izip_longest, islice, tee, izip
from tempfile import NamedTemporaryFile
from collections import namedtuple
from crumbs.utils.optional_modules import merge_sorted
from crumbs.exceptions import SampleSizeError



def sample(iterator, sample_size, in_disk=False):
    '''It makes a sample from the given iterator.

    It does not keep the order.
    Since it does not know before hand the size of the iterator it has to
    keep a buffer as large as the sample size in memory (default) or in disk.
    '''
    # This implementation holds the sampled items in memory
    # Example of the algorithm seen in:
    # http://nedbatchelder.com/blog/201208/selecting_randomly_from_an_unknown_
    # sequence.html
    # See also:
    # http://stackoverflow.com/questions/12128948/python-random-lines-from-
    # subfolders/

    if in_disk:
        sample_ = _ListLikeDb()
    else:
        sample_ = []
    too_big_sample = True
    for index, elem in enumerate(iterator):
        if len(sample_) < sample_size:
            sample_.append(elem)
        else:
            too_big_sample = False
            if random.randint(0, index) < sample_size:
                sample_[random.randint(0, sample_size - 1)] = elem
    if too_big_sample:

        raise SampleSizeError('Sample larger than population')