# Path: py_stringsimjoin/utils/generic_helper.py
# def build_dict_from_table(table, key_attr_index, join_attr_index,
#                           remove_null=True):
#     table_dict = {}
#     for row in table.itertuples(index=False):
#         if remove_null and pd.isnull(row[join_attr_index]):
#             continue
#         table_dict[row[key_attr_index]] = tuple(row)
#     return table_dict
# 
# def get_num_processes_to_launch(n_jobs):        
#     # determine number of processes to launch parallely
#     num_procs = n_jobs
#     if n_jobs < 0:
#         num_cpus = multiprocessing.cpu_count()
#         num_procs = num_cpus + 1 + n_jobs
#     return max(num_procs, 1)
# 
# def split_table(table, num_splits):
#     splits = []
#     split_size = 1.0/num_splits*len(table)
#     for i in xrange(num_splits):
#         splits.append(table[int(round(i*split_size)):
#                             int(round((i+1)*split_size))])
#     return splits
# 
# Path: py_stringsimjoin/utils/validation.py
# def validate_attr(attr, table_cols, attr_label, table_label):
#     """Check if the attribute exists in the table."""
#     if attr not in table_cols:
#         raise AssertionError(attr_label + ' \'' + attr + '\' not found in ' + \
#                              table_label) 
#     return True
# 
# def validate_attr_type(attr, attr_type, attr_label, table_label):
#     """Check if the attribute is not of numeric type."""
#     if attr_type != np.object:
#         raise AssertionError(attr_label + ' \'' + attr + '\' in ' + 
#                              table_label + ' is not of string type.')
#     return True
# 
# def validate_key_attr(key_attr, table, table_label):
#     """Check if the attribute is a valid key attribute."""
#     unique_flag = len(table[key_attr].unique()) == len(table)
#     nan_flag = sum(table[key_attr].isnull()) == 0 
#     if not (unique_flag and nan_flag):
#         raise AssertionError('\'' + key_attr + '\' is not a key attribute ' + \
#                              'in ' + table_label)
#     return True
# 
# def validate_input_table(table, table_label):
#     """Check if the input table is a dataframe."""
#     if not isinstance(table, pd.DataFrame):
#         raise TypeError(table_label + ' is not a dataframe')
#     return True


from joblib import delayed, Parallel
from py_stringsimjoin.utils.generic_helper import build_dict_from_table, \
    get_num_processes_to_launch, split_table
from py_stringsimjoin.utils.validation import validate_attr, \
    validate_attr_type, validate_key_attr, validate_input_table
import pandas as pd
import pyprind

            n_jobs (int): number of parallel jobs to use for the computation    
                (defaults to 1). If -1 is given, all CPUs are used. If 1 is     
                given, no parallel computing code is used at all, which is      
                useful for debugging. For n_jobs below -1,                      
                (n_cpus + 1 + n_jobs) are used (where n_cpus is the total       
                number of CPUs in the machine). Thus for n_jobs = -2, all CPUs  
                but one are used. If (n_cpus + 1 + n_jobs) becomes less than 1, 
                then no parallel computing code will be used (i.e., equivalent  
                to the default).
                                                                                
            show_progress (boolean): flag to indicate whether task progress     
                should be displayed to the user (defaults to True). 

        Returns:
            An output table containing tuple pairs from the candidate set that 
            survive the filter (DataFrame).
        """

        # check if the input candset is a dataframe
        validate_input_table(candset, 'candset')

        # check if the candset key attributes exist
        validate_attr(candset_l_key_attr, candset.columns,
                      'left key attribute', 'candset')
        validate_attr(candset_r_key_attr, candset.columns,
                      'right key attribute', 'candset')

        # check if the input tables are dataframes
        validate_input_table(ltable, 'left table')

# Path: py_stringsimjoin/utils/generic_helper.py
# def build_dict_from_table(table, key_attr_index, join_attr_index,
#                           remove_null=True):
#     table_dict = {}
#     for row in table.itertuples(index=False):
#         if remove_null and pd.isnull(row[join_attr_index]):
#             continue
#         table_dict[row[key_attr_index]] = tuple(row)
#     return table_dict
# 
# def get_num_processes_to_launch(n_jobs):        
#     # determine number of processes to launch parallely
#     num_procs = n_jobs
#     if n_jobs < 0:
#         num_cpus = multiprocessing.cpu_count()
#         num_procs = num_cpus + 1 + n_jobs
#     return max(num_procs, 1)
# 
# def split_table(table, num_splits):
#     splits = []
#     split_size = 1.0/num_splits*len(table)
#     for i in xrange(num_splits):
#         splits.append(table[int(round(i*split_size)):
#                             int(round((i+1)*split_size))])
#     return splits
# 
# Path: py_stringsimjoin/utils/validation.py
# def validate_attr(attr, table_cols, attr_label, table_label):
#     """Check if the attribute exists in the table."""
#     if attr not in table_cols:
#         raise AssertionError(attr_label + ' \'' + attr + '\' not found in ' + \
#                              table_label) 
#     return True
# 
# def validate_attr_type(attr, attr_type, attr_label, table_label):
#     """Check if the attribute is not of numeric type."""
#     if attr_type != np.object:
#         raise AssertionError(attr_label + ' \'' + attr + '\' in ' + 
#                              table_label + ' is not of string type.')
#     return True
# 
# def validate_key_attr(key_attr, table, table_label):
#     """Check if the attribute is a valid key attribute."""
#     unique_flag = len(table[key_attr].unique()) == len(table)
#     nan_flag = sum(table[key_attr].isnull()) == 0 
#     if not (unique_flag and nan_flag):
#         raise AssertionError('\'' + key_attr + '\' is not a key attribute ' + \
#                              'in ' + table_label)
#     return True
# 
# def validate_input_table(table, table_label):
#     """Check if the input table is a dataframe."""
#     if not isinstance(table, pd.DataFrame):
#         raise TypeError(table_label + ' is not a dataframe')
#     return True


# Path: py_stringsimjoin/filter/filter.py
from joblib import delayed, Parallel
from py_stringsimjoin.utils.generic_helper import build_dict_from_table, \
    get_num_processes_to_launch, split_table
from py_stringsimjoin.utils.validation import validate_attr, \
    validate_attr_type, validate_key_attr, validate_input_table
import pandas as pd
import pyprind


            n_jobs (int): number of parallel jobs to use for the computation    
                (defaults to 1). If -1 is given, all CPUs are used. If 1 is     
                given, no parallel computing code is used at all, which is      
                useful for debugging. For n_jobs below -1,                      
                (n_cpus + 1 + n_jobs) are used (where n_cpus is the total       
                number of CPUs in the machine). Thus for n_jobs = -2, all CPUs  
                but one are used. If (n_cpus + 1 + n_jobs) becomes less than 1, 
                then no parallel computing code will be used (i.e., equivalent  
                to the default).
                                                                                
            show_progress (boolean): flag to indicate whether task progress     
                should be displayed to the user (defaults to True). 

        Returns:
            An output table containing tuple pairs from the candidate set that 
            survive the filter (DataFrame).
        """

        # check if the input candset is a dataframe
        validate_input_table(candset, 'candset')

        # check if the candset key attributes exist
        validate_attr(candset_l_key_attr, candset.columns,
                      'left key attribute', 'candset')
        validate_attr(candset_r_key_attr, candset.columns,
                      'right key attribute', 'candset')

        # check if the input tables are dataframes
        validate_input_table(ltable, 'left table')

        validate_input_table(rtable, 'right table')