<commit_before>"""
feature extraction
"""

# from standard library
import sys
import os
import glob

# from dependencies
import numpy as np
from sklearn.externals import joblib

# from hvc
from .parseconfig import parse_config
from . import features
from .utils import timestamp

SELECT_TEMPLATE = """select:
  global:
    num_replicates: None
    num_train_samples:
      start : None
      stop : None
      step : None
    num_test_samples: None

    models:"""

MODELS_TEMPLATE = """
    -
      model: {0}
      feature_list_indices: {1}
      hyperparameters:
        {2}
"""

SVM_HYPERPARAMS = """C : None
        gamma : None
"""

KNN_HYPERPARAMS = """k : None
"""

TODO_TEMPLATE = """  todo_list:
    -
      feature_file : {0}
      output_dir: {1}"""

def write_select_config(summary_ftr_file_dict,
                       summary_filename,
                       output_dir):
    """writes summary output dict from extract to a config file for select
    Only called when feature_group is a list, to save user from figuring
    out manually which features belong to which group.

    Parameters
    ----------
    summary_ftr_file_dict : dictionary
        as defined in featureextract.extract
    summary_filename : string
        name of summary feature file
    output_dir : string
        name of output directory -- assumes it will be the same as it was for extract.yml

    Returns
    -------
    None

    Doesn't return anything, just saves .yml file
    """

    select_config_filename = 'select.config.from_' + summary_filename + '.yml'
    with open(select_config_filename, 'w') as yml_outfile:
        yml_outfile.write(SELECT_TEMPLATE)
        for model_name, model_ID in summary_ftr_file_dict['feature_group_ID_dict'].items():
            inds = np.flatnonzero(summary_ftr_file_dict['feature_list_group_ID']==model_ID).tolist()
            inds = ', '.join(str(ind) for ind in inds)
            if model_name == 'svm':
                hyperparams = SVM_HYPERPARAMS
            elif model_name == 'knn':
                hyperparams = KNN_HYPERPARAMS
            yml_outfile.write(MODELS_TEMPLATE.format(model_name,
                                                     inds,
                                                     hyperparams))
        yml_outfile.write(TODO_TEMPLATE.format(summary_filename,
                                               output_dir))

def extract(config_file):
    """main function that runs feature extraction.
    Does not return anything, just runs through directories specified in config_file
    and extracts features.

    Parameters
    ----------
    config_file : string
        filename of YAML file that configures feature extraction
    """

    extract_config = parse_config(config_file, 'extract')
    print('Parsed extract config.')

    home_dir = os.getcwd()

    todo_list = extract_config['todo_list']
    for ind, todo in enumerate(todo_list):

        print('Completing item {} of {} in to-do list'.format(ind+1, len(todo_list)))
        file_format = todo['file_format']
        if file_format == 'evtaf':
            if 'evfuncs' not in sys.modules:
                from . import evfuncs
        elif file_format == 'koumura':
            if 'koumura' not in sys.modules:
                from . import koumura

        feature_list = todo['feature_list']

        output_dir = 'extract_output_' + timestamp()
        output_dir_with_path = os.path.join(todo['output_dir'] + output_dir)
        if not os.path.isdir(output_dir_with_path):
            os.mkdir(output_dir_with_path)

        data_dirs = todo['data_dirs']
        for data_dir in data_dirs:
            print('Changing to data directory: {}'.format(data_dir))
            os.chdir(home_dir)
            os.chdir(data_dir)

            if 'features_from_all_files' in locals():
                # from last time through loop
                # (need to re-initialize for each directory)
                del features_from_all_files

            if 'neuralnet_inputs_dict' in locals():
                del neuralnet_inputs_dict

            if file_format == 'evtaf':
                songfiles_list = glob.glob('*.cbin')
            elif file_format == 'koumura':
                songfiles_list = glob.glob('*.wav')

            num_songfiles = len(songfiles_list)
            all_labels = []
            song_IDs = []
            song_ID_counter = 0
            for file_num, songfile in enumerate(songfiles_list):
                print('Processing audio file {} of {}.'.format(file_num + 1, num_songfiles))
                # segment_params defined for todo_list item takes precedence over any default
                # defined for `extract` config
                if 'segment_params' in todo:
                    extract_dict = features.extract.from_file(songfile,
                                                              todo['file_format'],
                                                              todo['feature_list'],
                                                              extract_config['spect_params'],
                                                              todo['labelset'],
                                                              todo['segment_params'])
                else:  # if seg params not defined in to-do, revert to default
                    extract_dict = features.extract.from_file(songfile,
                                                              todo['file_format'],
                                                              todo['feature_list'],
                                                              extract_config['spect_params'],
                                                              todo['labelset'],
                                                              extract_config['segment_params'])

                if extract_dict is None:
                    # because no labels from labels_to_use were found in songfile
                    continue

                all_labels.extend(extract_dict['labels'])
                song_IDs.extend([song_ID_counter] * len(extract_dict['labels']))
                song_ID_counter += 1

                if 'features_arr' in extract_dict:
                    if 'features_from_all_files' in locals():
                        features_from_all_files = np.concatenate((features_from_all_files,
                                                                  extract_dict['features_arr']),
                                                                 axis=0)
                    else:
                        features_from_all_files = extract_dict['features_arr']

                if 'neuralnet_inputs_dict' in extract_dict:
                    if 'neuralnet_inputs_all_files' in locals():
                        for key, val in neuralnet_inputs_all_files.items():
                            new_val = np.concatenate((neuralnet_inputs_all_files[key],
                                                     extract_dict['neuralnet_inputs_dict'][key]))
                            neuralnet_inputs_all_files[key] = new_val
                    else:
                        neuralnet_inputs_all_files = extract_dict['neuralnet_inputs_dict']

            # get dir name without the rest of path so it doesn't have separators in the name
            # because those can't be in filename
            just_dir_name = os.getcwd().split(os.path.sep)[-1]
            feature_file = os.path.join(output_dir_with_path,
                                        'features_from_' + just_dir_name + '_created_' + timestamp())
            feature_file_dict = {
                'labels': all_labels,
                'feature_list': todo['feature_list'],
                'spect_params': extract_config['spect_params'],
                'labelset': todo['labelset'],
                'file_format': todo['file_format'],
                'bird_ID': todo['bird_ID'],
                'song_IDs': song_IDs
            }

            if 'features_from_all_files' in locals():
                feature_file_dict['features'] = features_from_all_files
                feature_file_dict['features_arr_column_IDs'] = extract_dict['feature_inds']

                if 'feature_list_group_ID' in todo:
                    feature_file_dict['feature_list_group_ID'] = todo['feature_list_group_ID']
                    feature_file_dict['feature_group_ID_dict'] = todo['feature_group_ID_dict']

            if 'neuralnet_inputs_all_files' in locals():
                feature_file_dict['neuralnet_inputs'] = neuralnet_inputs_all_files

            joblib.dump(feature_file_dict,
                        feature_file,
                        compress=3)

        ##########################################################
        # after looping through all data_dirs for this todo_item #
        ##########################################################
        print('making summary file')
        os.chdir(output_dir_with_path)
        summary_filename = 'summary_feature_file_created_' + timestamp()
        summary_filename_with_path = os.path.join(output_dir_with_path, summary_filename)
        ftr_output_files = glob.glob('*features_from_*')
        if len(ftr_output_files) > 1:
            # make a 'summary' data file
            list_of_output_dicts = []
            summary_ftr_file_dict = {}
            for feature_file in ftr_output_files:
                feature_file_dict = joblib.load(feature_file)

                if 'labels' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['labels'] = feature_file_dict['labels']
                else:
                    summary_ftr_file_dict['labels'] = summary_ftr_file_dict['labels'] + feature_file_dict['labels']

                if 'spect_params' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['spect_params'] = feature_file_dict['spect_params']
                else:

                    if feature_file_dict['spect_params'] != summary_ftr_file_dict['spect_params']:
                        raise ValueError('mismatch between spect_params in {} '
                                         'and other feature files'.format(feature_file))

                if 'labelset' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['labelset'] = feature_file_dict['labelset']
                else:
                    if feature_file_dict['labelset'] != summary_ftr_file_dict['labelset']:
                        raise ValueError('mismatch between labelset in {} '
                                         'and other feature files'.format(feature_file))

                if 'file_format' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['file_format'] = feature_file_dict['file_format']
                else:
                    if feature_file_dict['file_format'] != summary_ftr_file_dict['file_format']:
                        raise ValueError('mismatch between file_format in {} '
                                         'and other feature files'.format(feature_file))

                if 'bird_ID' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['bird_ID'] = feature_file_dict['bird_ID']
                else:
                    if feature_file_dict['bird_ID'] != summary_ftr_file_dict['bird_ID']:
                        raise ValueError('mismatch between bird_ID in {} '
                                         'and other feature files'.format(feature_file))

                if 'song_IDs' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['song_IDs'] = feature_file_dict['song_IDs']
                else:
                    curr_last_ID = summary_ftr_file_dict['song_IDs'][-1]
                    tmp_song_IDs = [el + curr_last_ID + 1 for el in feature_file_dict['song_IDs']]
                    summary_ftr_file_dict['song_IDs'].extend(tmp_song_IDs)

                if 'feature_list' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['feature_list'] = feature_file_dict['feature_list']
                else:
                    if feature_file_dict['feature_list'] != summary_ftr_file_dict['feature_list']:
                        raise ValueError('mismatch between feature_list in {} '
                                         'and other feature files'.format(feature_file))

                # only if not-neuralnet features were used
                if 'features' in feature_file_dict:
                    if 'features' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['features'] = feature_file_dict['features']
                    else:
                        summary_ftr_file_dict['features'] = np.concatenate((summary_ftr_file_dict['features'],
                                                                         feature_file_dict['features']))

                    if 'features_arr_column_IDs' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['features_arr_column_IDs'] = feature_file_dict['features_arr_column_IDs']
                    else:
                        if any(feature_file_dict['features_arr_column_IDs'] !=
                                       summary_ftr_file_dict['features_arr_column_IDs']):
                            raise ValueError('mismatch between features_arr_column_IDs in {} '
                                             'and other feature files'.format(feature_file))

                    if 'feature_list_group_ID' in todo:
                        if 'feature_list_group_ID' not in summary_ftr_file_dict:
                            summary_ftr_file_dict['feature_list_group_ID'] = feature_file_dict['feature_list_group_ID']
                        else:
                            if any(feature_file_dict['feature_list_group_ID'] !=
                                           summary_ftr_file_dict['feature_list_group_ID']):
                                raise ValueError('mismatch between feature_list_group_ID in {} '
                                                 'and other feature files'.format(feature_file))

                        if 'feature_group_ID_dict' not in summary_ftr_file_dict:
                            summary_ftr_file_dict['feature_group_ID_dict'] = \
                                feature_file_dict['feature_group_ID_dict']
                        else:
                            if feature_file_dict['feature_group_ID_dict'] != \
                                    summary_ftr_file_dict['feature_group_ID_dict']:
                                raise ValueError('mismatch between feature_group_ID_dict in {} '
                                                 'and other feature files'.format(feature_file))

                # if extracting inputs for neuralnets
                if 'neuralnet_inputs' in feature_file_dict:
                    if 'neuralnet_inputs' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['neuralnet_inputs'] = \
                        feature_file_dict['neuralnet_inputs']
                    else:
                        for key, val in summary_ftr_file_dict['neuralnet_inputs'].items():
                            newval = np.concatenate((summary_ftr_file_dict['neuralnet_inputs'][key],
                                                     feature_file_dict['neuralnet_inputs'][key]))
                            summary_ftr_file_dict['neuralnet_inputs'][key] = newval

            joblib.dump(summary_ftr_file_dict,
                        summary_filename)

        else:  # if only one feature_file
            os.rename(ftr_output_files[0],
                      summary_filename)
            summary_ftr_file_dict = joblib.load(summary_filename)

        if 'feature_list_group_ID' in summary_ftr_file_dict:
            write_select_config(summary_ftr_file_dict,
                                summary_filename,
                                todo['output_dir'])

        os.chdir(home_dir)<commit_msg>remove `globals` from string for write_select_config in featureextract<commit_after>"""
feature extraction
"""

# from standard library
import sys
import os
import glob

# from dependencies
import numpy as np
from sklearn.externals import joblib

# from hvc
from .parseconfig import parse_config
from . import features
from .utils import timestamp

SELECT_TEMPLATE = """select:
  num_replicates: None
  num_train_samples:
    start : None
    stop : None
    step : None
  num_test_samples: None

    models:"""

MODELS_TEMPLATE = """
    -
      model: {0}
      feature_list_indices: {1}
      hyperparameters:
        {2}
"""

SVM_HYPERPARAMS = """C : None
        gamma : None
"""

KNN_HYPERPARAMS = """k : None
"""

TODO_TEMPLATE = """  todo_list:
    -
      feature_file : {0}
      output_dir: {1}"""

def write_select_config(summary_ftr_file_dict,
                       summary_filename,
                       output_dir):
    """writes summary output dict from extract to a config file for select
    Only called when feature_group is a list, to save user from figuring
    out manually which features belong to which group.

    Parameters
    ----------
    summary_ftr_file_dict : dictionary
        as defined in featureextract.extract
    summary_filename : string
        name of summary feature file
    output_dir : string
        name of output directory -- assumes it will be the same as it was for extract.yml

    Returns
    -------
    None

    Doesn't return anything, just saves .yml file
    """

    select_config_filename = 'select.config.from_' + summary_filename + '.yml'
    with open(select_config_filename, 'w') as yml_outfile:
        yml_outfile.write(SELECT_TEMPLATE)
        for model_name, model_ID in summary_ftr_file_dict['feature_group_ID_dict'].items():
            inds = [ftr_list_ind for ftr_list_ind, grp_ID in
                    enumerate(summary_ftr_file_dict['feature_list_group_ID'])
                    if grp_ID == model_ID]
            if model_name == 'svm':
                hyperparams = SVM_HYPERPARAMS
            elif model_name == 'knn':
                hyperparams = KNN_HYPERPARAMS
            yml_outfile.write(MODELS_TEMPLATE.format(model_name,
                                                     inds,
                                                     hyperparams))
        yml_outfile.write(TODO_TEMPLATE.format(summary_filename,
                                               output_dir))

def extract(config_file):
    """main function that runs feature extraction.
    Does not return anything, just runs through directories specified in config_file
    and extracts features.

    Parameters
    ----------
    config_file : string
        filename of YAML file that configures feature extraction
    """

    extract_config = parse_config(config_file, 'extract')
    print('Parsed extract config.')

    home_dir = os.getcwd()

    todo_list = extract_config['todo_list']
    for ind, todo in enumerate(todo_list):

        print('Completing item {} of {} in to-do list'.format(ind+1, len(todo_list)))
        file_format = todo['file_format']
        if file_format == 'evtaf':
            if 'evfuncs' not in sys.modules:
                from . import evfuncs
        elif file_format == 'koumura':
            if 'koumura' not in sys.modules:
                from . import koumura

        feature_list = todo['feature_list']

        output_dir = 'extract_output_' + timestamp()
        output_dir_with_path = os.path.join(todo['output_dir'] + output_dir)
        if not os.path.isdir(output_dir_with_path):
            os.mkdir(output_dir_with_path)

        data_dirs = todo['data_dirs']
        for data_dir in data_dirs:
            print('Changing to data directory: {}'.format(data_dir))
            os.chdir(home_dir)
            os.chdir(data_dir)

            if 'features_from_all_files' in locals():
                # from last time through loop
                # (need to re-initialize for each directory)
                del features_from_all_files

            if 'neuralnet_inputs_dict' in locals():
                del neuralnet_inputs_dict

            if file_format == 'evtaf':
                songfiles_list = glob.glob('*.cbin')
            elif file_format == 'koumura':
                songfiles_list = glob.glob('*.wav')

            num_songfiles = len(songfiles_list)
            all_labels = []
            song_IDs = []
            song_ID_counter = 0
            for file_num, songfile in enumerate(songfiles_list):
                print('Processing audio file {} of {}.'.format(file_num + 1, num_songfiles))
                # segment_params defined for todo_list item takes precedence over any default
                # defined for `extract` config
                if 'segment_params' in todo:
                    extract_dict = features.extract.from_file(songfile,
                                                              todo['file_format'],
                                                              todo['feature_list'],
                                                              extract_config['spect_params'],
                                                              todo['labelset'],
                                                              todo['segment_params'])
                else:  # if seg params not defined in to-do, revert to default
                    extract_dict = features.extract.from_file(songfile,
                                                              todo['file_format'],
                                                              todo['feature_list'],
                                                              extract_config['spect_params'],
                                                              todo['labelset'],
                                                              extract_config['segment_params'])

                if extract_dict is None:
                    # because no labels from labels_to_use were found in songfile
                    continue

                all_labels.extend(extract_dict['labels'])
                song_IDs.extend([song_ID_counter] * len(extract_dict['labels']))
                song_ID_counter += 1

                if 'features_arr' in extract_dict:
                    if 'features_from_all_files' in locals():
                        features_from_all_files = np.concatenate((features_from_all_files,
                                                                  extract_dict['features_arr']),
                                                                 axis=0)
                    else:
                        features_from_all_files = extract_dict['features_arr']

                if 'neuralnet_inputs_dict' in extract_dict:
                    if 'neuralnet_inputs_all_files' in locals():
                        for key, val in neuralnet_inputs_all_files.items():
                            new_val = np.concatenate((neuralnet_inputs_all_files[key],
                                                     extract_dict['neuralnet_inputs_dict'][key]))
                            neuralnet_inputs_all_files[key] = new_val
                    else:
                        neuralnet_inputs_all_files = extract_dict['neuralnet_inputs_dict']

            # get dir name without the rest of path so it doesn't have separators in the name
            # because those can't be in filename
            just_dir_name = os.getcwd().split(os.path.sep)[-1]
            feature_file = os.path.join(output_dir_with_path,
                                        'features_from_' + just_dir_name + '_created_' + timestamp())
            feature_file_dict = {
                'labels': all_labels,
                'feature_list': todo['feature_list'],
                'spect_params': extract_config['spect_params'],
                'labelset': todo['labelset'],
                'file_format': todo['file_format'],
                'bird_ID': todo['bird_ID'],
                'song_IDs': song_IDs
            }

            if 'features_from_all_files' in locals():
                feature_file_dict['features'] = features_from_all_files
                feature_file_dict['features_arr_column_IDs'] = extract_dict['feature_inds']

                if 'feature_list_group_ID' in todo:
                    feature_file_dict['feature_list_group_ID'] = todo['feature_list_group_ID']
                    feature_file_dict['feature_group_ID_dict'] = todo['feature_group_ID_dict']

            if 'neuralnet_inputs_all_files' in locals():
                feature_file_dict['neuralnet_inputs'] = neuralnet_inputs_all_files

            joblib.dump(feature_file_dict,
                        feature_file,
                        compress=3)

        ##########################################################
        # after looping through all data_dirs for this todo_item #
        ##########################################################
        print('making summary file')
        os.chdir(output_dir_with_path)
        summary_filename = 'summary_feature_file_created_' + timestamp()
        summary_filename_with_path = os.path.join(output_dir_with_path, summary_filename)
        ftr_output_files = glob.glob('*features_from_*')
        if len(ftr_output_files) > 1:
            # make a 'summary' data file
            list_of_output_dicts = []
            summary_ftr_file_dict = {}
            for feature_file in ftr_output_files:
                feature_file_dict = joblib.load(feature_file)

                if 'labels' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['labels'] = feature_file_dict['labels']
                else:
                    summary_ftr_file_dict['labels'] = summary_ftr_file_dict['labels'] + feature_file_dict['labels']

                if 'spect_params' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['spect_params'] = feature_file_dict['spect_params']
                else:

                    if feature_file_dict['spect_params'] != summary_ftr_file_dict['spect_params']:
                        raise ValueError('mismatch between spect_params in {} '
                                         'and other feature files'.format(feature_file))

                if 'labelset' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['labelset'] = feature_file_dict['labelset']
                else:
                    if feature_file_dict['labelset'] != summary_ftr_file_dict['labelset']:
                        raise ValueError('mismatch between labelset in {} '
                                         'and other feature files'.format(feature_file))

                if 'file_format' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['file_format'] = feature_file_dict['file_format']
                else:
                    if feature_file_dict['file_format'] != summary_ftr_file_dict['file_format']:
                        raise ValueError('mismatch between file_format in {} '
                                         'and other feature files'.format(feature_file))

                if 'bird_ID' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['bird_ID'] = feature_file_dict['bird_ID']
                else:
                    if feature_file_dict['bird_ID'] != summary_ftr_file_dict['bird_ID']:
                        raise ValueError('mismatch between bird_ID in {} '
                                         'and other feature files'.format(feature_file))

                if 'song_IDs' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['song_IDs'] = feature_file_dict['song_IDs']
                else:
                    curr_last_ID = summary_ftr_file_dict['song_IDs'][-1]
                    tmp_song_IDs = [el + curr_last_ID + 1 for el in feature_file_dict['song_IDs']]
                    summary_ftr_file_dict['song_IDs'].extend(tmp_song_IDs)

                if 'feature_list' not in summary_ftr_file_dict:
                    summary_ftr_file_dict['feature_list'] = feature_file_dict['feature_list']
                else:
                    if feature_file_dict['feature_list'] != summary_ftr_file_dict['feature_list']:
                        raise ValueError('mismatch between feature_list in {} '
                                         'and other feature files'.format(feature_file))

                # only if not-neuralnet features were used
                if 'features' in feature_file_dict:
                    if 'features' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['features'] = feature_file_dict['features']
                    else:
                        summary_ftr_file_dict['features'] = np.concatenate((summary_ftr_file_dict['features'],
                                                                         feature_file_dict['features']))

                    if 'features_arr_column_IDs' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['features_arr_column_IDs'] = feature_file_dict['features_arr_column_IDs']
                    else:
                        if any(feature_file_dict['features_arr_column_IDs'] !=
                                       summary_ftr_file_dict['features_arr_column_IDs']):
                            raise ValueError('mismatch between features_arr_column_IDs in {} '
                                             'and other feature files'.format(feature_file))

                    if 'feature_list_group_ID' in todo:
                        if 'feature_list_group_ID' not in summary_ftr_file_dict:
                            summary_ftr_file_dict['feature_list_group_ID'] = feature_file_dict['feature_list_group_ID']
                        else:
                            if feature_file_dict['feature_list_group_ID'] != \
                                           summary_ftr_file_dict['feature_list_group_ID']:
                                raise ValueError('mismatch between feature_list_group_ID in {} '
                                                 'and other feature files'.format(feature_file))

                        if 'feature_group_ID_dict' not in summary_ftr_file_dict:
                            summary_ftr_file_dict['feature_group_ID_dict'] = \
                                feature_file_dict['feature_group_ID_dict']
                        else:
                            if feature_file_dict['feature_group_ID_dict'] != \
                                    summary_ftr_file_dict['feature_group_ID_dict']:
                                raise ValueError('mismatch between feature_group_ID_dict in {} '
                                                 'and other feature files'.format(feature_file))

                # if extracting inputs for neuralnets
                if 'neuralnet_inputs' in feature_file_dict:
                    if 'neuralnet_inputs' not in summary_ftr_file_dict:
                        summary_ftr_file_dict['neuralnet_inputs'] = \
                        feature_file_dict['neuralnet_inputs']
                    else:
                        for key, val in summary_ftr_file_dict['neuralnet_inputs'].items():
                            newval = np.concatenate((summary_ftr_file_dict['neuralnet_inputs'][key],
                                                     feature_file_dict['neuralnet_inputs'][key]))
                            summary_ftr_file_dict['neuralnet_inputs'][key] = newval

            joblib.dump(summary_ftr_file_dict,
                        summary_filename)

        else:  # if only one feature_file
            os.rename(ftr_output_files[0],
                      summary_filename)
            summary_ftr_file_dict = joblib.load(summary_filename)

        if 'feature_list_group_ID' in summary_ftr_file_dict:
            write_select_config(summary_ftr_file_dict,
                                summary_filename,
                                todo['output_dir'])

        os.chdir(home_dir)<|endoftext|>


<commit_before>#!/usr/bin/python
# ---------------------------------
#   Author: Ryan Groten
# ---------------------------------
#   Description:
#           Tool for managing disks for ovirt/RHEV from the command line
#           Provides the ability to create, attach/detach, delete both internal
#           (pool) disks or direct attach (lun) disks to VMs
#           Run without args for usage
#           Requires ovirtFunctions and ovirtsdk
# ---------------------------------

from ovirtsdk.api import API
from ovirtsdk.xml import params
import sys
import getopt
import time
import os
import imp
import ntpath

class UsageException(Exception):
    """UsageException thrown if invalid arguments provided, print usage"""

    def __init__(self, message):
        Exception.__init__(self, message)

        print("Usage: " + os.path.basename(__file__) +
                " : <operation> <arguments>")
        print("   Operations:")
        print("	attachdisk: Attach existing disk to a VM.  Requires -n -d")
        print("	detachdisk: Detach existing disk from a VM. Requires -n -d")
        print("	createdisk: Create a new disk and attach it to a VM. Requires -n -d -s")
        print("	deletedisk: Deletes an existing disk (must be detached). Requires -d")
        print("	createlun: Add a new direct lun disk and attach it to VM. Requires -d -l. Optional -n")
        print("   Arguments:")
        print("	-n: Name of VM Guest")
        print("	-d: Name of disk")
        print("	-s: Size of disk in GB")
        print("	-l: LUN id")
        print("	-w: no-activate/no-detach. When attaching disk, don't activate it. When deactivating, don't detach.")
        print(message)
        sys.exit(2)

def _activate(disk):
    """
    Activate specified disk
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to activate
    """
    try:
        if disk.get_active():
            print("Disk is already active")
        else:
            print("Activating disk: " + disk.alias)
            disk.activate()
    except Exception as e:
        print ("Error while activating disk: " + str(e))
        raise

def _deactivate(disk):
    """
    Deactivate specified disk
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to deactivate
    """
    try:
        if disk.get_active():
            print("Deactivating disk: " + disk.get_alias())
            disk.deactivate()
        else:
            print("Disk is already deactivated")
    except Exception as e:
        print ("Error while deactivating disk: " + str(e))
        raise

def _attach(vm, disk, activate):
    """
    Attach specified disk to VM
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.Disk object to attach
        vm - ovirtsdk.infrastructure.brokers.VM object to attach disk to
    """
    vmDisk = vm.disks.get(id=disk.id)
    # Check if disk is already attached to the VM
    if vmDisk:
        print("Disk " + disk.get_alias() + " is already attached")
        # Disk is already attached so lets activate it
        if activate:
            _activate(vmDisk)
    else:
        print("Attaching " + disk.get_alias() + " to " + vm.get_name())
        vmDisk = vm.disks.add(params.Disk(id = disk.id, active = activate))
    return vmDisk

def _detach(vm, disk):
    """
    Detach specified disk from VM
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to detach
        vm - ovirtsdk.infrastructure.brokers.VM object to detach disk from
    """
    print("Detaching disk " + disk.get_alias() + " from " + vm.get_name())
    disk.delete(action=params.Action(detach=True))

def attachDisk(vm_name, disk_name, activate=True):
    """
    Attach disk_name to vm_name then activate it by default
    Parameters:
      vm_name - string of VM to attach disk to
      disk_name - string of disk to attach to VM
    """
    try:
        vm = api.vms.get(name=vm_name)
        disks = api.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " found")
        for disk in disks.__iter__():
            vmDisk = _attach(vm, disk, activate)
    except Exception as e:
        print ("Error while attaching disk")
        raise

def detachDisk(vm_name, disk_name, detach=True):
    """
    Deactivate disk_name and by default detach it from vm_name
    """
    try:
        vm = api.vms.get(name=vm_name)
        disks = vm.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " are attached to " + vm_name)
        for disk in disks.__iter__():
            _deactivate(disk)
            if detach:
                _detach(vm, disk)
    except Exception as e:
        print("Exception while detaching disk")
        raise

def createDisk(vm_name, disk_name, sizegb):
    """Create a new disk with specified name and size. Attach to vm_name"""
    return_code = 0
    try:
        vm = api.vms.get(name=vm_name)
        disk = vm.disks.get(name=disk_name)
        size = int(sizegb) * 1024 * 1024 * 1024
        disk_params = params.Disk()
        disk_params.set_wipe_after_delete(True)
        disk_params.set_active(True)
        disk_params.set_alias(disk_name)
        disk_params.set_size(size)
        disk_params.set_interface('virtio')
        disk_params.set_format('cow')
        print("Will create new disk " + disk_name + " with size " + str(size))
        disk = vm.disks.add(disk_params)
        print("Created disk: " + disk.alias + " with size " + str(disk.size))
        # TODO: Dont sleep, use VMDisk.get_creation_status somehow
        #time.sleep(5)
        #activate(disk)
    except Exception as e:
        print("Error while creating new disk: " + str(e))
        return_code = 1

    return return_code

def createLun(vm_name, disk_name, lun_id):
    """
    Create a new direct attach disk from lun_id then attach to vm_name
    WARNING: Due to bug in RHEV3.4.0, direct luns created with this function
    will be missing all meta-information. To be fixed in 3.5.0 release
    """
    return_code = 0
    try:

        lu = params.LogicalUnit()
        lu.set_id(lun_id)

        lus = list()
        lus.append(lu)

        storage_params = params.Storage()
        storage_params.set_id(lun_id)
        storage_params.set_logical_unit(lus)
        storage_params.set_type('fcp')
        disk_params = params.Disk()
        disk_params.set_format('raw')
        disk_params.set_interface('virtio')
        disk_params.set_alias(disk_name)
        disk_params.set_active(True)
        disk_params.set_lun_storage(storage_params)

        if vm_name:
            vm = api.vms.get(name=vm_name)
            disk = vm.disks.add(disk_params)
        else:
            disk = api.disks.add(disk_params)

        #count = 10
        #while(not vm.disks.get(disk_name).get_active()):
            #if (count == 0):
                #print("Out of time, attempting to roll back")
                #detachDisk(vm_name, disk_name)
                #deleteDisk(disk_name)
                #raise Exception("Error adding lun, check lun_id and retry")
            #else:
                #time.sleep(1)
            #print(".")
            #count -= 1

    except Exception as e:
        print("Error while adding new lun: " + str(e))
        return_code = 1

    return return_code

def deleteDisk(disk_name, vm_name=None):
    """
    Permanently delete disk_name from OVIRT. Expects disk to be detached
    already. Unless -y is specified in command line, prompt user to confirm
    before deleting.
    """
    # TODO: If vm_name is populated, detach disk before deleting, instead of raise exception
    return_code = 0
    try:
        disks = api.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " are attached to " + vm_name)
        for disk in disks.__iter__():
            if disk is None:
                raise Exception("No such disk")

            if assumeYes is False:
                print("Will destroy disk " + disk.alias + " with size " + str(disk.size) + ". Are you sure? (Y/[N])")
                input = sys.stdin.readline().rstrip("\r\n")
            else:
                print("Assuming Yes since -y used...")
                input = "y"

            if not input or input not in "yY":
                print("Cancelled by user")
                continue
            disk.delete()
            print("Disk " + disk.alias + " deleted")
    except Exception as e:
        print("Error while deleting disk: " + str(e))
        return_code = 1

    return return_code

def main(argv):
    try:
        if len(argv) == 0:
            raise UsageException("No arguments specified")
        operation = argv.pop(0)
        ret_code = 0

        opts, args = getopt.getopt(argv, "hwyn:d:s:l:")
    except getopt.GetoptError as e:
        raise UsageException(str(e))
    try:
        vm_name = None
        activate = True # Default, activate disk when attaching
        global api
        functionsPath = ntpath.split(os.path.realpath(__file__))[0] + "/ovirtFunctions.py"
        ovirtConnect = imp.load_source('ovirtConnect', functionsPath)
        api = ovirtConnect.ovirtConnect()
        for opt, arg in opts:
            if opt == '-h':
                raise UsageException("blah")
            elif opt in ("-y", "--assume-yes"):
                global assumeYes
                assumeYes = True
            elif opt in ("-w", "--no-activate"):
                activate = False
            elif opt in ("-n", "--vm-name"):
                vm_name = arg
            elif opt in ("-d", "--disk-name"):
                disk_name = arg
            elif opt in ("-s", "--size"):
                size = arg
            elif opt in ("-l", "--lun-id"):
                lun_id = arg
            else:
                raise UsageException("Unknown argument:" + opt)

        if operation == 'attachdisk':
            ret_code = attachDisk(vm_name, disk_name, activate)
        elif operation == 'detachdisk':
            ret_code = detachDisk(vm_name, disk_name, activate)
        elif operation == 'createdisk':
            ret_code = createDisk(vm_name, disk_name, size)
        elif operation == 'deletedisk':
            if vm_name is not None:
                ret_code = deleteDisk(disk_name, vm_name)
            else:
                ret_code = deleteDisk(disk_name)
        elif operation == 'createlun':
            ret_code = createLun(vm_name, disk_name, lun_id)
        else:
            raise UsageException("Unknown operation: " + operation)

    except Exception as e:
        print("Exception: " + str(e))
        ret_code = 1
    finally:
        if api is not None:
            api.disconnect()
    #return_code = diskOperation( vm_name, disk_name, operation )
    sys.exit(ret_code)

api = None
assumeYes = False
if __name__ == "__main__":
    main(sys.argv[1:])
<commit_msg>modified:   rhevManageDisk.py   ; Cleanup some redundant logic and commented codes<commit_after>#!/usr/bin/python
# ---------------------------------
#   Author: Ryan Groten
# ---------------------------------
#   Description:
#           Tool for managing disks for ovirt/RHEV from the command line
#           Provides the ability to create, attach/detach, delete both internal
#           (pool) disks or direct attach (lun) disks to VMs
#           Run without args for usage
#           Requires ovirtFunctions and ovirtsdk
# ---------------------------------

from ovirtsdk.api import API
from ovirtsdk.xml import params
import sys
import getopt
import time
import os
import imp
import ntpath

class UsageException(Exception):
    """UsageException thrown if invalid arguments provided, print usage"""

    def __init__(self, message):
        Exception.__init__(self, message)

        print("Usage: " + os.path.basename(__file__) +
                " : <operation> <arguments>")
        print("   Operations:")
        print("	attachdisk: Attach existing disk to a VM.  Requires -n -d")
        print("	detachdisk: Detach existing disk from a VM. Requires -n -d")
        print("	createdisk: Create a new disk and attach it to a VM. Requires -n -d -s")
        print("	deletedisk: Deletes an existing disk (must be detached). Requires -d")
        print("	createlun: Add a new direct lun disk and attach it to VM. Requires -d -l. Optional -n")
        print("   Arguments:")
        print("	-n: Name of VM Guest")
        print("	-d: Name of disk")
        print("	-s: Size of disk in GB")
        print("	-l: LUN id")
        print("	-w: no-activate/no-detach. When attaching disk, don't activate it. When deactivating, don't detach.")
        print(message)
        sys.exit(2)

def _activate(disk):
    """
    Activate specified disk
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to activate
    """
    try:
        if disk.get_active():
            print("Disk is already active")
        else:
            print("Activating disk: " + disk.alias)
            disk.activate()
    except Exception as e:
        print ("Error while activating disk: " + str(e))
        raise

def _deactivate(disk):
    """
    Deactivate specified disk
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to deactivate
    """
    try:
        if disk.get_active():
            print("Deactivating disk: " + disk.get_alias())
            disk.deactivate()
        else:
            print("Disk is already deactivated")
    except Exception as e:
        print ("Error while deactivating disk: " + str(e))
        raise

def _attach(vm, disk, activate):
    """
    Attach specified disk to VM
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.Disk object to attach
        vm - ovirtsdk.infrastructure.brokers.VM object to attach disk to
    """
    vmDisk = vm.disks.get(id=disk.id)
    # Check if disk is already attached to the VM
    if vmDisk:
        print("Disk " + disk.get_alias() + " is already attached")
        # Disk is already attached so lets activate it
        if activate:
            _activate(vmDisk)
    else:
        print("Attaching " + disk.get_alias() + " to " + vm.get_name())
        vmDisk = vm.disks.add(params.Disk(id = disk.id, active = activate))
    return vmDisk

def _detach(vm, disk):
    """
    Detach specified disk from VM
    Parameters:
        disk - ovirtsdk.infrastructure.brokers.VMDisk object to detach
        vm - ovirtsdk.infrastructure.brokers.VM object to detach disk from
    """
    print("Detaching disk " + disk.get_alias() + " from " + vm.get_name())
    disk.delete(action=params.Action(detach=True))

def attachDisk(vm_name, disk_name, activate=True):
    """
    Attach disk_name to vm_name then activate it by default
    Parameters:
      vm_name - string of VM to attach disk to
      disk_name - string of disk to attach to VM
    """
    try:
        vm = api.vms.get(name=vm_name)
        disks = api.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " found")
        for disk in disks.__iter__():
            vmDisk = _attach(vm, disk, activate)
    except Exception as e:
        print ("Error while attaching disk")
        raise

def detachDisk(vm_name, disk_name, detach=True):
    """
    Deactivate disk_name and by default detach it from vm_name
    """
    try:
        vm = api.vms.get(name=vm_name)
        disks = vm.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " are attached to " + vm_name)
        for disk in disks.__iter__():
            _deactivate(disk)
            if detach:
                _detach(vm, disk)
    except Exception as e:
        print("Exception while detaching disk")
        raise

def createDisk(vm_name, disk_name, sizegb):
    """Create a new disk with specified name and size. Attach to vm_name"""
    return_code = 0
    try:
        vm = api.vms.get(name=vm_name)
        disk = vm.disks.get(name=disk_name)
        size = int(sizegb) * 1024 * 1024 * 1024
        disk_params = params.Disk()
        disk_params.set_wipe_after_delete(True)
        disk_params.set_active(True)
        disk_params.set_alias(disk_name)
        disk_params.set_size(size)
        disk_params.set_interface('virtio')
        disk_params.set_format('cow')
        print("Will create new disk " + disk_name + " with size " + str(size))
        disk = vm.disks.add(disk_params)
        print("Created disk: " + disk.alias + " with size " + str(disk.size))
        # TODO: Dont sleep, use VMDisk.get_creation_status somehow
        #time.sleep(5)
        #activate(disk)
    except Exception as e:
        print("Error while creating new disk: " + str(e))
        return_code = 1

    return return_code

def createLun(vm_name, disk_name, lun_id):
    """
    Create a new direct attach disk from lun_id then attach to vm_name
    WARNING: Due to bug in RHEV3.4.0, direct luns created with this function
    will be missing all meta-information. To be fixed in 3.5.0 release
    """
    return_code = 0
    try:

        lu = params.LogicalUnit()
        lu.set_id(lun_id)

        lus = list()
        lus.append(lu)

        storage_params = params.Storage()
        storage_params.set_id(lun_id)
        storage_params.set_logical_unit(lus)
        storage_params.set_type('fcp')
        disk_params = params.Disk()
        disk_params.set_format('raw')
        disk_params.set_interface('virtio')
        disk_params.set_alias(disk_name)
        disk_params.set_active(True)
        disk_params.set_lun_storage(storage_params)

        if vm_name:
            vm = api.vms.get(name=vm_name)
            disk = vm.disks.add(disk_params)
        else:
            disk = api.disks.add(disk_params)

    except Exception as e:
        print("Error while adding new lun: " + str(e))
        return_code = 1

    return return_code

def deleteDisk(disk_name, vm_name=None):
    """
    Permanently delete disk_name from OVIRT. Expects disk to be detached
    already. Unless -y is specified in command line, prompt user to confirm
    before deleting.
    """
    # TODO: If vm_name is populated, detach disk before deleting, instead of raise exception
    return_code = 0
    try:
        disks = api.disks.list(alias=disk_name)
        if not disks:
            raise Exception("No disks with name " + disk_name + " are attached to " + vm_name)
        for disk in disks.__iter__():
            if disk is None:
                raise Exception("No such disk")

            if assumeYes is False:
                print("Will destroy disk " + disk.alias + " with size " + str(disk.size) + ". Are you sure? (Y/[N])")
                input = sys.stdin.readline().rstrip("\r\n")
            else:
                print("Assuming Yes since -y used...")
                input = "y"

            if not input or input not in "yY":
                print("Cancelled by user")
                continue
            disk.delete()
            print("Disk " + disk.alias + " deleted")
    except Exception as e:
        print("Error while deleting disk: " + str(e))
        return_code = 1

    return return_code

def main(argv):
    try:
        if len(argv) == 0:
            raise UsageException("No arguments specified")
        operation = argv.pop(0)
        ret_code = 0

        opts, args = getopt.getopt(argv, "hwyn:d:s:l:")
    except getopt.GetoptError as e:
        raise UsageException(str(e))
    try:
        vm_name = None
        activate = True # Default, activate disk when attaching
        global api
        functionsPath = ntpath.split(os.path.realpath(__file__))[0] + "/ovirtFunctions.py"
        ovirtConnect = imp.load_source('ovirtConnect', functionsPath)
        api = ovirtConnect.ovirtConnect()
        for opt, arg in opts:
            if opt == '-h':
                raise UsageException("Print usage")
            elif opt in ("-y", "--assume-yes"):
                global assumeYes
                assumeYes = True
            elif opt in ("-w", "--no-activate"):
                activate = False
            elif opt in ("-n", "--vm-name"):
                vm_name = arg
            elif opt in ("-d", "--disk-name"):
                disk_name = arg
            elif opt in ("-s", "--size"):
                size = arg
            elif opt in ("-l", "--lun-id"):
                lun_id = arg
            else:
                raise UsageException("Unknown argument:" + opt)

        if operation == 'attachdisk':
            ret_code = attachDisk(vm_name, disk_name, activate)
        elif operation == 'detachdisk':
            ret_code = detachDisk(vm_name, disk_name, activate)
        elif operation == 'createdisk':
            ret_code = createDisk(vm_name, disk_name, size)
        elif operation == 'deletedisk':
            if vm_name:
                ret_code = deleteDisk(disk_name, vm_name)
            else:
                ret_code = deleteDisk(disk_name)
        elif operation == 'createlun':
            ret_code = createLun(vm_name, disk_name, lun_id)
        else:
            raise UsageException("Unknown operation: " + operation)

    except Exception as e:
        print("Exception: " + str(e))
        ret_code = 1
    finally:
        if api is not None:
            api.disconnect()
    #return_code = diskOperation( vm_name, disk_name, operation )
    sys.exit(ret_code)

api = None
assumeYes = False
if __name__ == "__main__":
    main(sys.argv[1:])
<|endoftext|>


<commit_before>#!/usr/bin/python

#----------------------------------------------------------------------
# Copyright (c) 2011 Raytheon BBN Technologies
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#----------------------------------------------------------------------
""" Acceptance tests for AM API v1."""

import datetime
from geni.util import rspec_util
import unittest
import omni_unittest as ut
from omni_unittest import NotDictAssertionError, NotNoneAssertionError
from omni_unittest import NotXMLAssertionError, NoResourcesAssertionError
from omnilib.util import OmniError, NoSliceCredError
import omni
import os
import pprint
import re
import sys
import time
import tempfile

import am_api_accept as accept

# Works at PLC
PGV2_RSPEC_NAME = "ProtoGENI"
PGV2_RSPEC_NUM = 2
RSPEC_NAME = "GENI"
RSPEC_NUM = 3

TMP_DIR="."
REQ_RSPEC_FILE="request.xml"
BAD_RSPEC_FILE="bad.xml"
SLEEP_TIME=3
################################################################################
#
# Test AM API v1 calls for accurate and complete functionality.
#
# This script relies on the unittest module.
#
# To run test:
# ./am_api_accept.py -a <AM to test>
#
# To add a new test:
# Create a new method with a name starting with 'test_".  It will
# automatically be run when am_api_accept.py is called.
#
################################################################################

# This is the acceptance test for AM API version 1
API_VERSION = 2

#NUM_SLEEP = 15*60 # 15 minutes
NUM_SLEEP = 15
#MAX_TIME_TO_CREATESLIVER = 15*60 # 15 minutes
MAX_TIME_TO_CREATESLIVER = 15

class NagiosTest(accept.Test):
    """Test to be used by nagios."""

    def setUp( self ):
        accept.Test.setUp( self )
        self.slicename = self.create_slice_name( prefix="nag-" )

    def test_CreateSliver_nagios(self):
        """test_CreateSliver: Passes if the sliver creation workflow succeeds.
        Use --rspec-file to replace the default request RSpec."""
        self.logger.info("\n=== Test.test_CreateSliver_nagios ===")

        self.subtest_CreateSliver_nagios( self.slicename )
        self.success = True

    def subtest_CreateSliver_nagios(self, slicename=None, doProvision=True, doPOA=True):
        # Check to see if 'rspeclint' can be found before doing the hard (and
        # slow) work of calling ListResources at the aggregate
        if self.options_copy.rspeclint:
            rspec_util.rspeclint_exists()
            rspec_namespace = self.manifest_namespace
            rspec_schema = self.manifest_schema
        else:
            rspec_namespace = None
            rspec_schema = None

        if slicename==None:
            slicename = self.create_slice_name()

        # if reusing a slice name, don't create (or delete) the slice
        if not self.options_copy.reuse_slice_name:
            self.subtest_createslice( slicename )
            time.sleep(self.options_copy.sleep_time)

        # cleanup up any previous failed runs
        try:
            self.subtest_generic_Delete( slicename )
            time.sleep(self.options_copy.sleep_time)
        except:
            pass

        numslivers, manifest, slivers = self.subtest_generic_CreateSliver( slicename, doProvision, doPOA )
        with open(self.options_copy.rspec_file) as f:
            req = f.readlines()
            request = "".join(req)

        try:
            self.assertRspec( "CreateSliver", manifest,
                              rspec_namespace, rspec_schema,
                              self.options_copy.rspeclint )
            self.assertRspecType( request, 'request')
            self.assertRspecType( manifest, 'manifest')
            # Make sure the Manifest returned the nodes identified in
            # the Request
            self.assertManifestMatchesRequest( request, manifest,
                                               self.RSpecVersion(),
                                               self.options_copy.bound,
                                               "Created sliver")
        except:
            raise
        finally:
            time.sleep(self.options_copy.sleep_time)

    def test_SliverStatus_nagios(self):
        self.logger.info("\n=== Test.test_SliverStatus_nagios ===")
        self.assertTrue( hasattr(self.options_copy, 'reuse_slice_name'),
                         "No slice name passed in via (--reuse-slice) to use on this test.")
        self.subtest_SliverStatus_nagios(self.slicename)
        self.success = True

    def subtest_SliverStatus_nagios(self, slicename):
        have_slept = 0
        status_ready = False
        long_sleep = NUM_SLEEP * self.options_copy.sleep_time
        if slicename==None:
            slicename = self.create_slice_name()
        while have_slept <= MAX_TIME_TO_CREATESLIVER:
            try:
                self.subtest_generic_SliverStatus( slicename )
                status_ready=True
                break
            except:
                self.logger.info("===> Starting to sleep")
                self.logger.info("=== long_sleep ==="+str(long_sleep))
                time.sleep( long_sleep )

                have_slept += long_sleep
        self.assertTrue( status_ready )

    @classmethod
    def nagios_parser( cls, parser=omni.getParser(), usage=None):
        parser.add_option( "--max-createsliver-time",
                           action="store", type='int', dest='MAX_TIME_TO_CREATESLIVER',
                           help="Max time will attempt to check status of a sliver before failing")

if __name__ == '__main__':
    usage = "\n      %s -a am-undertest" \
            "\n      Also try --vv" % sys.argv[0]
    NagiosTest.accept_parser(usage=usage)

    suite = unittest.TestLoader().loadTestsFromNames(["am_api_accept_nagios.NagiosTest.test_CreateSliver_nagios", "am_api_accept_nagios.NagiosTest.test_SliverStatus_nagios"])

    unittest.TextTestRunner().run(suite)

<commit_msg>Loop for repeated checking of SliverStatus test.<commit_after>#!/usr/bin/python

#----------------------------------------------------------------------
# Copyright (c) 2011 Raytheon BBN Technologies
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and/or hardware specification (the "Work") to
# deal in the Work without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Work, and to permit persons to whom the Work
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Work.
#
# THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS
# IN THE WORK.
#----------------------------------------------------------------------
""" Acceptance tests for AM API v1."""

import datetime
from geni.util import rspec_util
import unittest
import omni_unittest as ut
from omni_unittest import NotDictAssertionError, NotNoneAssertionError
from omni_unittest import NotXMLAssertionError, NoResourcesAssertionError
from omnilib.util import OmniError, NoSliceCredError, RefusedError, AMAPIError
import omni
import os
import pprint
import re
import sys
import time
import tempfile

import am_api_accept as accept

# Works at PLC
PGV2_RSPEC_NAME = "ProtoGENI"
PGV2_RSPEC_NUM = 2
RSPEC_NAME = "GENI"
RSPEC_NUM = 3

TMP_DIR="."
REQ_RSPEC_FILE="request.xml"
BAD_RSPEC_FILE="bad.xml"
SLEEP_TIME=3
################################################################################
#
# Test AM API v1 calls for accurate and complete functionality.
#
# This script relies on the unittest module.
#
# To run test:
# ./am_api_accept.py -a <AM to test>
#
# To add a new test:
# Create a new method with a name starting with 'test_".  It will
# automatically be run when am_api_accept.py is called.
#
################################################################################

# This is the acceptance test for AM API version 1
API_VERSION = 2

#NUM_SLEEP = 15*60 # 15 minutes
NUM_SLEEP = 15
#MAX_TIME_TO_CREATESLIVER = 15*60 # 15 minutes
MAX_TIME_TO_CREATESLIVER = 15

class NagiosTest(accept.Test):
    """Test to be used by nagios."""

    def setUp( self ):
        accept.Test.setUp( self )
        self.slicename = self.create_slice_name( prefix="nag-" )

    def test_CreateSliver_nagios(self):
        """test_CreateSliver: Passes if the sliver creation workflow succeeds.
        Use --rspec-file to replace the default request RSpec."""
        self.logger.info("\n=== Test.test_CreateSliver_nagios ===")

        self.subtest_CreateSliver_nagios( self.slicename )
        self.success = True

    def subtest_CreateSliver_nagios(self, slicename=None, doProvision=True, doPOA=True):
        # Check to see if 'rspeclint' can be found before doing the hard (and
        # slow) work of calling ListResources at the aggregate
        if self.options_copy.rspeclint:
            rspec_util.rspeclint_exists()
            rspec_namespace = self.manifest_namespace
            rspec_schema = self.manifest_schema
        else:
            rspec_namespace = None
            rspec_schema = None

        if slicename==None:
            slicename = self.create_slice_name()

        # if reusing a slice name, don't create (or delete) the slice
        if not self.options_copy.reuse_slice_name:
            self.subtest_createslice( slicename )
            time.sleep(self.options_copy.sleep_time)

        # cleanup up any previous failed runs
        try:
            self.subtest_generic_Delete( slicename )
            time.sleep(self.options_copy.sleep_time)
        except:
            pass

        numslivers, manifest, slivers = self.subtest_generic_CreateSliver( slicename, doProvision, doPOA )
        with open(self.options_copy.rspec_file) as f:
            req = f.readlines()
            request = "".join(req)

        try:
            self.assertRspec( "CreateSliver", manifest,
                              rspec_namespace, rspec_schema,
                              self.options_copy.rspeclint )
            self.assertRspecType( request, 'request')
            self.assertRspecType( manifest, 'manifest')
            # Make sure the Manifest returned the nodes identified in
            # the Request
            self.assertManifestMatchesRequest( request, manifest,
                                               self.RSpecVersion(),
                                               self.options_copy.bound,
                                               "Created sliver")
        except:
            raise
        finally:
            time.sleep(self.options_copy.sleep_time)

    def test_SliverStatus_nagios(self):
        self.logger.info("\n=== Test.test_SliverStatus_nagios ===")
        self.assertTrue( hasattr(self.options_copy, 'reuse_slice_name'),
                         "No slice name passed in via (--reuse-slice) to use on this test.")
        self.subtest_SliverStatus_nagios(self.slicename)
        self.success = True

    def subtest_SliverStatus_nagios(self, slicename):
        have_slept = 0
        status_ready = False
        long_sleep = NUM_SLEEP * self.options_copy.sleep_time
        if slicename==None:
            slicename = self.create_slice_name()
        while have_slept <= MAX_TIME_TO_CREATESLIVER:
            try:
# check for ready
                self.subtest_generic_SliverStatus( slicename )
                status_ready=True
                break
            except Exception, e:
                self.logger.info("===> Starting to sleep")
                self.logger.info("=== long_sleep ==="+str(long_sleep))
                time.sleep( long_sleep )
                have_slept += long_sleep
        self.assertTrue( status_ready,
                         "SliverStatus on slice '%s' expected to be ready but was not" % slicename)

    @classmethod
    def nagios_parser( cls, parser=omni.getParser(), usage=None):
        parser.add_option( "--max-createsliver-time",
                           action="store", type='int', dest='MAX_TIME_TO_CREATESLIVER',
                           help="Max time will attempt to check status of a sliver before failing")

if __name__ == '__main__':
    usage = "\n      %s -a am-undertest" \
            "\n      Also try --vv" % sys.argv[0]
    NagiosTest.accept_parser(usage=usage)

    suite = unittest.TestLoader().loadTestsFromNames(["am_api_accept_nagios.NagiosTest.test_CreateSliver_nagios", "am_api_accept_nagios.NagiosTest.test_SliverStatus_nagios"])

    unittest.TextTestRunner().run(suite)

<|endoftext|>


<commit_before># Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tests.common import Form

_logger = logging.getLogger(__name__)

# List of move's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE = {"journal_id", "date"}
# List of move line's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE_LINE = {
    "credit",
    "debit",
    "account_id",
    "journal_id",
    "date",
    "asset_profile_id",
    "asset_id",
}

class AccountMove(models.Model):
    _inherit = "account.move"

    asset_count = fields.Integer(compute="_compute_asset_count")

    def _compute_asset_count(self):
        for rec in self:
            assets = (
                self.env["account.asset.line"]
                .search([("move_id", "=", rec.id)])
                .mapped("asset_id")
            )
            rec.asset_count = len(assets)

    def unlink(self):
        # for move in self:
        deprs = self.env["account.asset.line"].search(
            [("move_id", "in", self.ids), ("type", "in", ["depreciate", "remove"])]
        )
        if deprs and not self.env.context.get("unlink_from_asset"):
            raise UserError(
                _(
                    "You are not allowed to remove an accounting entry "
                    "linked to an asset."
                    "\nYou should remove such entries from the asset."
                )
            )
        # trigger store function
        deprs.write({"move_id": False})
        return super().unlink()

    def write(self, vals):
        if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE):
            deprs = self.env["account.asset.line"].search(
                [("move_id", "in", self.ids), ("type", "=", "depreciate")]
            )
            if deprs:
                raise UserError(
                    _(
                        "You cannot change an accounting entry "
                        "linked to an asset depreciation line."
                    )
                )
        return super().write(vals)

    def post(self):
        super().post()
        for move in self:
            for aml in move.line_ids.filtered("asset_profile_id"):
                depreciation_base = aml.debit or -aml.credit
                if not aml.name:
                    raise UserError(
                        _("Asset name must be set in the label of the line.")
                    )
                vals = {
                    "name": aml.name,
                    "code": move.name,
                    "profile_id": aml.asset_profile_id,
                    "purchase_value": depreciation_base,
                    "partner_id": aml.partner_id,
                    "date_start": move.date,
                    "account_analytic_id": aml.analytic_account_id,
                }
                if self.env.context.get("company_id"):
                    vals["company_id"] = self.env["res.company"].browse(
                        self.env.context["company_id"]
                    )
                asset_form = Form(
                    self.env["account.asset"].with_context(
                        create_asset_from_move_line=True, move_id=move.id
                    )
                )
                for key, val in vals.items():
                    setattr(asset_form, key, val)
                asset = asset_form.save()
                asset.analytic_tag_ids = aml.analytic_tag_ids
                aml.with_context(allow_asset=True).asset_id = asset.id
            refs = [
                "%s"
                % tuple(name_get)
                for name_get in move.line_ids.filtered(
                    "asset_profile_id"
                ).asset_id.name_get()
            ]
            if refs:
                message = _("This invoice created the asset(s): %s") % ", ".join(refs)
                move.message_post(body=message)

    def button_draft(self):
        invoices = self.filtered(lambda r: r.is_purchase_document())
        if invoices:
            invoices.line_ids.asset_id.unlink()
        super().button_draft()

    def _reverse_move_vals(self, default_values, cancel=True):
        move_vals = super()._reverse_move_vals(default_values, cancel)
        if move_vals["type"] not in ("out_invoice", "out_refund"):
            for line_command in move_vals.get("line_ids", []):
                line_vals = line_command[2]  # (0, 0, {...})
                asset = self.env["account.asset"].browse(line_vals["asset_id"])
                # We remove the asset if we recognize that we are reversing
                # the asset creation
                if asset:
                    asset_line = self.env["account.asset.line"].search(
                        [("asset_id", "=", asset.id), ("type", "=", "create")], limit=1
                    )
                    if asset_line and asset_line.move_id == self:
                        asset.unlink()
                        line_vals.update(asset_profile_id=False, asset_id=False)
        return move_vals

    def action_view_assets(self):
        assets = (
            self.env["account.asset.line"]
            .search([("move_id", "=", self.id)])
            .mapped("asset_id")
        )
        action = self.env.ref("account_asset_management.account_asset_action")
        action_dict = action.read()[0]
        if len(assets) == 1:
            res = self.env.ref(
                "account_asset_management.account_asset_view_form", False
            )
            action_dict["views"] = [(res and res.id or False, "form")]
            action_dict["res_id"] = assets.id
        elif assets:
            action_dict["domain"] = [("id", "in", assets.ids)]
        else:
            action_dict = {"type": "ir.actions.act_window_close"}
        return action_dict

class AccountMoveLine(models.Model):
    _inherit = "account.move.line"

    asset_profile_id = fields.Many2one(
        comodel_name="account.asset.profile", string="Asset Profile",
    )
    asset_id = fields.Many2one(
        comodel_name="account.asset", string="Asset", ondelete="restrict",
    )

    @api.onchange("account_id")
    def _onchange_account_id(self):
        if self.account_id.asset_profile_id:
            self.asset_profile_id = self.account_id.asset_profile_id
        super()._onchange_account_id()

    @api.onchange("asset_profile_id")
    def _onchange_asset_profile_id(self):
        if self.asset_profile_id.account_asset_id:
            self.account_id = self.asset_profile_id.account_asset_id

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            move = self.env["account.move"].browse(vals.get("move_id"))
            if not move.is_sale_document():
                if vals.get("asset_id") and not self.env.context.get("allow_asset"):
                    raise UserError(
                        _(
                            "You are not allowed to link "
                            "an accounting entry to an asset."
                            "\nYou should generate such entries from the asset."
                        )
                    )
        records = super().create(vals_list)
        for record in records:
            record._expand_asset_line()
        return records

    def write(self, vals):
        if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE_LINE) and not (
            self.env.context.get("allow_asset_removal")
            and list(vals.keys()) == ["asset_id"]
        ):
            # Check if at least one asset is linked to a move
            linked_asset = False
            for move_line in self.filtered(lambda r: not r.move_id.is_sale_document()):
                linked_asset = move_line.asset_id
                if linked_asset:
                    raise UserError(
                        _(
                            "You cannot change an accounting item "
                            "linked to an asset depreciation line."
                        )
                    )

        if (
            self.filtered(lambda r: not r.move_id.is_sale_document())
            and vals.get("asset_id")
            and not self.env.context.get("allow_asset")
        ):
            raise UserError(
                _(
                    "You are not allowed to link "
                    "an accounting entry to an asset."
                    "\nYou should generate such entries from the asset."
                )
            )
        super().write(vals)
        if "quantity" in vals or "asset_profile_id" in vals:
            for record in self:
                record._expand_asset_line()
        return True

    def _expand_asset_line(self):
        self.ensure_one()
        if self.asset_profile_id and self.quantity > 1.0:
            profile = self.asset_profile_id
            if profile.asset_product_item:
                aml = self.with_context(check_move_validity=False)
                qty = self.quantity
                name = self.name
                aml.write({"quantity": 1, "name": "{} {}".format(name, 1)})
                aml._onchange_price_subtotal()
                for i in range(1, int(qty)):
                    aml.copy({"name": "{} {}".format(name, i + 1)})
                aml.move_id._onchange_invoice_line_ids()
<commit_msg>[FIX] account_asset_management: make asset company match move's<commit_after># Copyright 2009-2018 Noviat
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

from odoo import _, api, fields, models
from odoo.exceptions import UserError
from odoo.tests.common import Form

_logger = logging.getLogger(__name__)

# List of move's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE = {"journal_id", "date"}
# List of move line's fields that can't be modified if move is linked
# with a depreciation line
FIELDS_AFFECTS_ASSET_MOVE_LINE = {
    "credit",
    "debit",
    "account_id",
    "journal_id",
    "date",
    "asset_profile_id",
    "asset_id",
}

class AccountMove(models.Model):
    _inherit = "account.move"

    asset_count = fields.Integer(compute="_compute_asset_count")

    def _compute_asset_count(self):
        for rec in self:
            assets = (
                self.env["account.asset.line"]
                .search([("move_id", "=", rec.id)])
                .mapped("asset_id")
            )
            rec.asset_count = len(assets)

    def unlink(self):
        # for move in self:
        deprs = self.env["account.asset.line"].search(
            [("move_id", "in", self.ids), ("type", "in", ["depreciate", "remove"])]
        )
        if deprs and not self.env.context.get("unlink_from_asset"):
            raise UserError(
                _(
                    "You are not allowed to remove an accounting entry "
                    "linked to an asset."
                    "\nYou should remove such entries from the asset."
                )
            )
        # trigger store function
        deprs.write({"move_id": False})
        return super().unlink()

    def write(self, vals):
        if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE):
            deprs = self.env["account.asset.line"].search(
                [("move_id", "in", self.ids), ("type", "=", "depreciate")]
            )
            if deprs:
                raise UserError(
                    _(
                        "You cannot change an accounting entry "
                        "linked to an asset depreciation line."
                    )
                )
        return super().write(vals)

    def post(self):
        super().post()
        for move in self:
            for aml in move.line_ids.filtered("asset_profile_id"):
                depreciation_base = aml.debit or -aml.credit
                if not aml.name:
                    raise UserError(
                        _("Asset name must be set in the label of the line.")
                    )
                vals = {
                    "name": aml.name,
                    "code": move.name,
                    "profile_id": aml.asset_profile_id,
                    "purchase_value": depreciation_base,
                    "partner_id": aml.partner_id,
                    "date_start": move.date,
                    "account_analytic_id": aml.analytic_account_id,
                }
                asset_form = Form(
                    self.env["account.asset"].with_context(
                        create_asset_from_move_line=True,
                        force_company=move.company_id.id,
                        move_id=move.id,
                    )
                )
                for key, val in vals.items():
                    setattr(asset_form, key, val)
                asset = asset_form.save()
                asset.analytic_tag_ids = aml.analytic_tag_ids
                aml.with_context(allow_asset=True).asset_id = asset.id
            refs = [
                "%s"
                % tuple(name_get)
                for name_get in move.line_ids.filtered(
                    "asset_profile_id"
                ).asset_id.name_get()
            ]
            if refs:
                message = _("This invoice created the asset(s): %s") % ", ".join(refs)
                move.message_post(body=message)

    def button_draft(self):
        invoices = self.filtered(lambda r: r.is_purchase_document())
        if invoices:
            invoices.line_ids.asset_id.unlink()
        super().button_draft()

    def _reverse_move_vals(self, default_values, cancel=True):
        move_vals = super()._reverse_move_vals(default_values, cancel)
        if move_vals["type"] not in ("out_invoice", "out_refund"):
            for line_command in move_vals.get("line_ids", []):
                line_vals = line_command[2]  # (0, 0, {...})
                asset = self.env["account.asset"].browse(line_vals["asset_id"])
                # We remove the asset if we recognize that we are reversing
                # the asset creation
                if asset:
                    asset_line = self.env["account.asset.line"].search(
                        [("asset_id", "=", asset.id), ("type", "=", "create")], limit=1
                    )
                    if asset_line and asset_line.move_id == self:
                        asset.unlink()
                        line_vals.update(asset_profile_id=False, asset_id=False)
        return move_vals

    def action_view_assets(self):
        assets = (
            self.env["account.asset.line"]
            .search([("move_id", "=", self.id)])
            .mapped("asset_id")
        )
        action = self.env.ref("account_asset_management.account_asset_action")
        action_dict = action.read()[0]
        if len(assets) == 1:
            res = self.env.ref(
                "account_asset_management.account_asset_view_form", False
            )
            action_dict["views"] = [(res and res.id or False, "form")]
            action_dict["res_id"] = assets.id
        elif assets:
            action_dict["domain"] = [("id", "in", assets.ids)]
        else:
            action_dict = {"type": "ir.actions.act_window_close"}
        return action_dict

class AccountMoveLine(models.Model):
    _inherit = "account.move.line"

    asset_profile_id = fields.Many2one(
        comodel_name="account.asset.profile", string="Asset Profile",
    )
    asset_id = fields.Many2one(
        comodel_name="account.asset", string="Asset", ondelete="restrict",
    )

    @api.onchange("account_id")
    def _onchange_account_id(self):
        if self.account_id.asset_profile_id:
            self.asset_profile_id = self.account_id.asset_profile_id
        super()._onchange_account_id()

    @api.onchange("asset_profile_id")
    def _onchange_asset_profile_id(self):
        if self.asset_profile_id.account_asset_id:
            self.account_id = self.asset_profile_id.account_asset_id

    @api.model_create_multi
    def create(self, vals_list):
        for vals in vals_list:
            move = self.env["account.move"].browse(vals.get("move_id"))
            if not move.is_sale_document():
                if vals.get("asset_id") and not self.env.context.get("allow_asset"):
                    raise UserError(
                        _(
                            "You are not allowed to link "
                            "an accounting entry to an asset."
                            "\nYou should generate such entries from the asset."
                        )
                    )
        records = super().create(vals_list)
        for record in records:
            record._expand_asset_line()
        return records

    def write(self, vals):
        if set(vals).intersection(FIELDS_AFFECTS_ASSET_MOVE_LINE) and not (
            self.env.context.get("allow_asset_removal")
            and list(vals.keys()) == ["asset_id"]
        ):
            # Check if at least one asset is linked to a move
            linked_asset = False
            for move_line in self.filtered(lambda r: not r.move_id.is_sale_document()):
                linked_asset = move_line.asset_id
                if linked_asset:
                    raise UserError(
                        _(
                            "You cannot change an accounting item "
                            "linked to an asset depreciation line."
                        )
                    )

        if (
            self.filtered(lambda r: not r.move_id.is_sale_document())
            and vals.get("asset_id")
            and not self.env.context.get("allow_asset")
        ):
            raise UserError(
                _(
                    "You are not allowed to link "
                    "an accounting entry to an asset."
                    "\nYou should generate such entries from the asset."
                )
            )
        super().write(vals)
        if "quantity" in vals or "asset_profile_id" in vals:
            for record in self:
                record._expand_asset_line()
        return True

    def _expand_asset_line(self):
        self.ensure_one()
        if self.asset_profile_id and self.quantity > 1.0:
            profile = self.asset_profile_id
            if profile.asset_product_item:
                aml = self.with_context(check_move_validity=False)
                qty = self.quantity
                name = self.name
                aml.write({"quantity": 1, "name": "{} {}".format(name, 1)})
                aml._onchange_price_subtotal()
                for i in range(1, int(qty)):
                    aml.copy({"name": "{} {}".format(name, i + 1)})
                aml.move_id._onchange_invoice_line_ids()
<|endoftext|>


<commit_before>from django.core.urlresolvers import reverse_lazy
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden

from entries.models import Entry

class LoginRequiredMixin(object):
    @classmethod
    def as_view(cls, **initkwargs):
        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
        return login_required(view)

class EntryList(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user)

class EntryListByYear(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'])

class EntryListByMonth(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'], created_at__month=self.kwargs['month'])

class EntryListByDay(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'], created_at__month=self.kwargs['month'], created_at__day=self.kwargs['day'])

class EntryCreate(LoginRequiredMixin, CreateView):
    model = Entry
    fields = ['text', 'tags']
    template_name_suffix = '_form'

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(EntryCreate, self).form_valid(form)

from django.views.generic.detail import SingleObjectMixin
from django.shortcuts import redirect
from taggit.managers import TaggableManager

class EntryClone(LoginRequiredMixin, UpdateView):
    model = Entry
    template_name_suffix = '_update_form'
    fields = ['text', 'tags']

    def get_object(self, queryset=None):
        #clone = super(SingleObjectMixin, self).get_object(queryset)
        clone = super(EntryClone, self).get_object(queryset)

        tags = clone.tags.names()

        # Clone the object specified by the URL slug
        clone.pk = None
        clone.slug = None
        clone.save()

        for tag in tags:
            clone.tags.add(tag)

        return clone

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            #return super(EntryClone, self).get(request, *args, **kwargs)
            return redirect('/entries/update/' + self.object.slug)
        else:
            return HttpResponseForbidden()

class EntryRead(LoginRequiredMixin, DetailView):
    model = Entry
    template_name_suffix = '_detail'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)
        else:
            return HttpResponseForbidden()

class EntryUpdate(LoginRequiredMixin, UpdateView):
    model = Entry
    template_name_suffix = '_update_form'
    fields = ['text', 'tags']

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return super(EntryUpdate, self).get(request, *args, **kwargs)
        else:
            return HttpResponseForbidden()

class EntryDelete(LoginRequiredMixin, DeleteView):
    model = Entry
    success_url = reverse_lazy('entries:index')

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)
        else:
            return HttpResponseForbidden()
<commit_msg>Added EntryFavorite view which toggles a favorite entry in the Favorite table<commit_after>from django.core.urlresolvers import reverse_lazy
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.contrib.auth.decorators import login_required
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.shortcuts import get_object_or_404

from favorites.models import Favorite

from entries.models import Entry

class LoginRequiredMixin(object):
    @classmethod
    def as_view(cls, **initkwargs):
        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
        return login_required(view)

class EntryList(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user)

class EntryListByYear(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'])

class EntryListByMonth(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'], created_at__month=self.kwargs['month'])

class EntryListByDay(LoginRequiredMixin, ListView):
    model = Entry

    def get_queryset(self):
        return Entry.objects.filter(user=self.request.user, created_at__year=self.kwargs['year'], created_at__month=self.kwargs['month'], created_at__day=self.kwargs['day'])

class EntryCreate(LoginRequiredMixin, CreateView):
    model = Entry
    fields = ['text', 'tags']
    template_name_suffix = '_form'

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(EntryCreate, self).form_valid(form)

from django.views.generic.detail import SingleObjectMixin
from django.shortcuts import redirect
from taggit.managers import TaggableManager

class EntryClone(LoginRequiredMixin, UpdateView):
    model = Entry
    template_name_suffix = '_update_form'
    fields = ['text', 'tags']

    def get_object(self, queryset=None):
        #clone = super(SingleObjectMixin, self).get_object(queryset)
        clone = super(EntryClone, self).get_object(queryset)

        tags = clone.tags.names()

        # Clone the object specified by the URL slug
        clone.pk = None
        clone.slug = None
        clone.save()

        for tag in tags:
            clone.tags.add(tag)

        return clone

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            #return super(EntryClone, self).get(request, *args, **kwargs)
            return redirect('/entries/update/' + self.object.slug)
        else:
            return HttpResponseForbidden()

class EntryFavorite(LoginRequiredMixin, DetailView):
    model = Entry

    def get(self, request, *args, **kwargs):
        self.object = get_object_or_404(Entry, slug=kwargs['slug'])

        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            fav = Favorite.objects.favorites_for_obj(self.object)
            # Toggle the favorite by creating or deleting the table entry
            if not fav:
                Favorite.objects.create_favorite(self.object.user, self.object)
            else:
                fav.delete()
            context = self.get_context_data(object=self.object)
            return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
        else:
            return HttpResponseForbidden()

class EntryRead(LoginRequiredMixin, DetailView):
    model = Entry
    template_name_suffix = '_detail'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)
        else:
            return HttpResponseForbidden()

class EntryUpdate(LoginRequiredMixin, UpdateView):
    model = Entry
    template_name_suffix = '_update_form'
    fields = ['text', 'tags']

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return super(EntryUpdate, self).get(request, *args, **kwargs)
        else:
            return HttpResponseForbidden()

class EntryDelete(LoginRequiredMixin, DeleteView):
    model = Entry
    success_url = reverse_lazy('entries:index')

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        # Users should only be allowed to see their own entries
        if self.object.user == self.request.user:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)
        else:
            return HttpResponseForbidden()
<|endoftext|>