def test_intervs_3(self, mock_guc, mock_rfa, mock_rep): """Ensure _intervs() calls everything in the right order, with the right args & settings. This uses the default *except* requires removing rests, so it's more complex.""" test_settings = {'simple or compound': 'compound', 'quality': False} test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)] returns = [ pandas.DataFrame([pandas.Series(['3', 'Rest', '5'])], index=[['interval.IntervalIndexer'], ['0,1']]).T for i in range(len(test_pieces)) ] for piece in test_pieces: piece.get_data.side_effect = lambda *x: returns.pop(0) exp_series_ind = ('interval.IntervalIndexer', '0,1') expected_df = pandas.DataFrame( {exp_series_ind: pandas.Series(['3', '5'], index=[0, 2])}) exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer] test_wc = WorkflowManager(test_pieces) test_wc.settings(None, 'count frequency', False) actual = test_wc._intervs() # pylint: disable=protected-access self.assertEqual(0, mock_guc.call_count) self.assertEqual(len(test_pieces), len(actual)) self.assertEqual(0, mock_rfa.call_count) self.assertEqual(0, mock_rep.call_count) for piece in test_pieces: piece.get_data.assert_called_once_with(exp_analyzers, test_settings) for i in range(len(actual)): self.assertSequenceEqual(list(expected_df.columns), list(actual[i].columns)) self.assertSequenceEqual(list(expected_df[exp_series_ind].index), list(actual[i][exp_series_ind].index)) self.assertSequenceEqual(list(expected_df[exp_series_ind].values), list(actual[i][exp_series_ind].values))
def test_intervs_1(self, mock_guc, mock_rfa, mock_rep): """Ensure _intervs() calls everything in the right order, with the right args & settings. This test uses all the default settings.""" test_settings = {'simple or compound': 'compound', 'quality': False} test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)] returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))] for piece in test_pieces: piece.get_data.side_effect = lambda *x: returns.pop(0) expected = ['get_data() {}'.format(i) for i in range(len(test_pieces))] exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer] test_wc = WorkflowManager(test_pieces) test_wc.settings(None, 'include rests', True) actual = test_wc._intervs() # pylint: disable=protected-access self.assertEqual(0, mock_guc.call_count) self.assertEqual(len(test_pieces), len(expected), len(actual)) self.assertEqual(0, mock_rep.call_count) mock_rfa.assert_called_once_with('interval.IntervalIndexer') for piece in test_pieces: piece.get_data.assert_called_once_with(exp_analyzers, test_settings) for i in range(len(actual)): # NB: in real use, _run_freq_agg() would aggregate a piece's voice pairs and save it in # self._result... but since that method's mocked out, we have to check here the # return of each piece's get_data() call self.assertSequenceEqual(expected[i], actual[i])
def test_intervals_2(self): """test all combinations of bwv77""" test_wm = WorkflowManager( [os.path.join(VIS_PATH, 'tests', 'corpus', 'bwv77.mxl')]) test_wm.load('pieces') test_wm.settings(0, 'voice combinations', 'all pairs') actual = test_wm.run('intervals') self.assertEqual(1, len(actual.columns)) actual = actual['aggregator.ColumnAggregator'] exp_ind = list(IntervalsTests.EXPECTED_2.index) act_ind = list(actual.index) for ind_item in exp_ind: self.assertTrue(ind_item in act_ind) for ind_item in exp_ind: self.assertEqual(IntervalsTests.EXPECTED_2[ind_item], actual[ind_item])
def test_intervals_3(self): """test all combinations of madrigal51 without rests""" test_wm = WorkflowManager( [os.path.join(VIS_PATH, 'tests', 'corpus', 'madrigal51.mxl')]) test_wm.load('pieces') test_wm.settings(0, 'voice combinations', 'all pairs') test_wm.settings(None, 'include rests', False) actual = test_wm.run('intervals') self.assertEqual(1, len(actual.columns)) actual = actual['aggregator.ColumnAggregator'] exp_ind = list(IntervalsTests.EXPECTED_3.index) act_ind = list(actual.index) for ind_item in exp_ind: self.assertTrue(ind_item in act_ind) for ind_item in exp_ind: self.assertEqual(IntervalsTests.EXPECTED_3[ind_item], actual[ind_item])
def test_intervs_4(self): """Ensure _intervs() fails when given an impossible 'voice pair'.""" test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)] returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))] for piece in test_pieces: piece.get_data.side_effect = lambda *x: returns.pop(0) exp_err_msg = WorkflowManager._REQUIRE_PAIRS_ERROR.format(3) # pylint: disable=protected-access test_wc = WorkflowManager(test_pieces) test_wc.settings(None, 'include rests', True) test_wc.settings(None, 'voice combinations', '[[0, 1, 2]]') # that's not a pair! self.assertRaises(RuntimeError, test_wc._intervs) # pylint: disable=protected-access try: test_wc._intervs() # pylint: disable=protected-access except RuntimeError as run_err: self.assertEqual(exp_err_msg, run_err.args[0])
def test_intervs_2(self, mock_guc, mock_rfa, mock_rep): """Ensure _intervs() calls everything in the right order, with the right args & settings. Same as test_intervs_1() but: - calls _remove_extra_pairs(), and - doesn't call _run_freq_agg().""" mock_guc.return_value = [[0, 1]] voice_combos = str(mock_guc.return_value) exp_voice_combos = ['0,1'] test_settings = {'simple or compound': 'compound', 'quality': False} test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)] returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))] for piece in test_pieces: piece.get_data.side_effect = lambda *x: returns.pop(0) exp_into_mock_rep = [ 'get_data() {}'.format(i) for i in range(len(test_pieces)) ] mock_rep_returns = [ 'IndP-{} no pairs'.format(i) for i in range(len(test_pieces)) ] mock_rep.side_effect = lambda *x: mock_rep_returns.pop(0) expected = [ 'IndP-{} no pairs'.format(i) for i in range(len(test_pieces)) ] exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer] exp_mock_guc = [mock.call(i) for i in range(len(test_pieces))] test_wc = WorkflowManager(test_pieces) test_wc.settings(None, 'include rests', True) test_wc.settings(None, 'count frequency', False) test_wc.settings(None, 'voice combinations', voice_combos) actual = test_wc._intervs() # pylint: disable=protected-access self.assertSequenceEqual(exp_mock_guc, mock_guc.call_args_list) self.assertEqual(len(test_pieces), len(expected), len(actual)) self.assertEqual(0, mock_rfa.call_count) self.assertEqual(len(test_pieces), mock_rep.call_count) for i in range(len(test_pieces)): mock_rep.assert_any_call(exp_into_mock_rep[i], exp_voice_combos) for piece in test_pieces: piece.get_data.assert_called_once_with(exp_analyzers, test_settings) for i in range(len(actual)): self.assertSequenceEqual(expected[i], actual[i])
def import_files(request): """ Called with the /api/import URL to load files into the WorkflowManager and return the metadata it discovers. """ filepaths = [ piece.file.path for piece in Piece.objects.filter(user_id=request.session.session_key) ] workm = WorkflowManager(filepaths) workm.load('pieces') request.session['workm'] = workm return [{ "Filename": os.path.basename(workm.metadata(i, 'pathname')), "Title": workm.metadata(i, 'title'), "Part Names": workm.metadata(i, 'parts'), "Offset": None, "Part Combinations": None, "Repeat Identical": False } for i in xrange(len(workm))], 200
def test_intervals_6(self): # TODO: add a frequency-counted test """test Soprano and Alto of bwv77; with quality; not counting frequency""" # NB: the "expected" was hand-counted expected = pandas.read_csv(os.path.join(VIS_PATH, 'tests', 'expecteds', 'bwv77', 'SA_intervals.csv'), comment='#', index_col=0, header=[0, 1], quotechar="'") test_wm = WorkflowManager( [os.path.join(VIS_PATH, 'tests', 'corpus', 'bwv77.mxl')]) test_wm.load('pieces') test_wm.settings(0, 'voice combinations', '[[0, 1]]') test_wm.settings(None, 'count frequency', False) test_wm.settings(None, 'interval quality', True) actual = test_wm.run('intervals') self.assertEqual(1, len(actual)) actual = actual[0].dropna() self.assertDataFramesEqual(expected, actual)
def test_intervals_5(self): """test all combinations of vis_Test_Piece""" test_wm = WorkflowManager( [os.path.join(VIS_PATH, 'tests', 'corpus', 'vis_Test_Piece.xml')]) test_wm.load('pieces') test_wm.settings(0, 'voice combinations', 'all pairs') test_wm.settings(None, 'include rests', True) expected = pandas.read_csv(os.path.join(VIS_PATH, 'tests', 'corpus', 'test_intervals_5.csv'), index_col=0) actual = test_wm.run('intervals') self.assertEqual(1, len(actual.columns)) self.assertSequenceEqual(list(expected.columns), list(actual.columns)) for col_name in expected.columns: self.assertEqual(len(expected[col_name]), len(actual[col_name])) for each_interval in expected[col_name].index: # NOTE: for whatever reason, the "expected" file always imports with an Int64Index, # so .loc() won't find things properly unless we give the int64 index to the # expected and the str index to the actual self.assertEqual(expected[col_name].loc[each_interval], actual[col_name].loc[str(each_interval)])
def setData(self, index, value, role): """ Set the data for the piece and metadatum or setting specified. If the internal :class:`WorkflowManager` has not yet been created and this is the last pathname added, instantiate the :class:`WorkflowManager` and call :meth:`load`. :param index: The row-and-column index you wish to access. Either you can use a :class:`QModelIndex` or a 2-tuple where the first element is an ``int`` representing the index of the piece in the models, and the second element is one of the class properties described above in "Columns in the Data Model." :type index: :class:`QModelIndex` or 2-tuple of ``int`` :param value: The desired value of the setting or metadatum. If you submit a :class:`QVariant`, we will call :meth:`toPyObject` before sending to the :class:`WorkflowManager`. :type value: :class:`QVariant` or any :param role: This should be Qt.EditRole. :type role: :class:`EditRole` :returns: Whether the data was successfully set. :rtype: ``True`` or ``False`` .. note:: If the internal :class:`WorkflowManager` has not been instantiated, you can only set the ``pathname`` field. All other calls to :meth:`setData` will fail. """ if Qt.EditRole != role: return False # Set the row and column row = None column = None if isinstance(index, QModelIndex): # if the QModelIndex is invalid, we won't bother with it if not index.isValid(): return False # otherwise, get the row and column from the QModelIndex row = index.row() column = index.column() else: row = index[0] column = index[1] index = self.createIndex(row, column) # Verify the row and column if row >= self.rowCount() or column >= self._num_cols and \ (column != WorkflowWrapper.quality and column != WorkflowWrapper.simple_ints): return False set_val = value.toPyObject() if isinstance(value, QVariant) else value # ensure we're trying to set a valid thing if self._workm is None: if WorkflowWrapper.filename != column: return False else: self._pathnames[row] = set_val ch_ind_1, ch_ind_2 = None, None if all(self._pathnames): self._workm = WorkflowManager(self._pathnames) self._workm.load(u'pieces') # now that we imported, all the data's changed ch_ind_1 = self.createIndex(0, 0) ch_ind_2 = self.createIndex(len(self), self._num_cols - 1) # let the GUI know self._when_done_import() else: # only one cell has changed ch_ind_1 = ch_ind_2 = self.createIndex(row, column) self.dataChanged.emit(ch_ind_1, ch_ind_2) return True # displayed fields if WorkflowWrapper.filename == column: self._workm.metadata(row, u'pathname', set_val) elif WorkflowWrapper.title == column: self._workm.metadata(row, u'title', set_val) elif WorkflowWrapper.parts_list == column: self._workm.metadata(row, u'parts', set_val) elif WorkflowWrapper.offset_interval == column: self._workm.settings(row, u'offset interval', set_val) elif WorkflowWrapper.parts_combinations == column: self._workm.settings(row, u'voice combinations', set_val) elif WorkflowWrapper.repeat_identical == column: # the wording in the GUI and WorkflowManager has opposite meanings self._workm.settings(row, u'filter repeats', not set_val) # non-displayed fields elif WorkflowWrapper.quality == column: self._workm.settings(None, u'interval quality', set_val) elif WorkflowWrapper.simple_ints == column: self._workm.settings(None, u'simple intervals', set_val) else: return False self._settings_changed = True self.dataChanged.emit(index, index) return True