def song_excluded(self, song): if self.exclude and Query(self.exclude).search(song): print_d("%s is excluded by %s" % (song("~artist~title"), self.exclude)) return True return False
def test_synth_search(self): self.failUnless(Query("~dirname=/dir1/").search(self.s1)) self.failUnless(Query("~dirname=/dir2/").search(self.s2)) self.failIf(Query("~dirname=/dirty/").search(self.s1)) self.failIf(Query("~dirname=/dirty/").search(self.s2))
def test_empty(self): self.failUnless(Query.is_valid('')) self.failUnless(Query.is_parsable('')) self.failUnless(Query(''))
def test_dumb_search(self): self.failUnless(Query("ate man").search(self.s1)) self.failUnless(Query("Ate man").search(self.s1)) self.failIf(Query("woo man").search(self.s1)) self.failIf(Query("not crazy").search(self.s1))
def test_dumb_search_regexp(self): self.failUnless(Query("/(x|H)ate/").search(self.s1)) self.failUnless(Query("'PiMan'").search(self.s1)) self.failIf(Query("'PiMan'c").search(self.s1)) self.failUnless(Query("!'PiMan'c").search(self.s1)) self.failIf(Query("!/(x|H)ate/").search(self.s1))
def test_not_2(self): for s in ["album = !/i hate/", "artist = !/pi*/", "title = !/x.y/"]: self.failUnless(Query(s).search(self.s2)) self.failIf(Query(s).search(self.s1))
def test_newlines(self): self.failUnless(Query("a = /\n/").search(self.s3)) self.failUnless(Query("a = /\\n/").search(self.s3)) self.failIf(Query("a = /\n/").search(self.s2)) self.failIf(Query("a = /\\n/").search(self.s2))
def filter_text(self, text): self.__searchbar.set_text(text) if Query(text).is_parsable: self.__filter_changed(self.__searchbar, text) self.activate()
def _update_query_from(self, text): # TODO: remove tight coupling to Query self._query = Query(text, star=self._star)
def test_match_diacriticals_invalid_or_unsupported(self): # these fall back to test dumb searches: # invalid regex Query(u'/Sigur [r-zos/d') # group refs unsupported for diacritic matching Query(u'/(<)?(\w+@\w+(?:\.\w+)+)(?(1)>)/d')
def __filter_changed(self, bar, text, restore=False): self.__filter = Query(text, self.STAR) if not restore: self.activate()
def test_match_diacriticals_dumb(self): self.assertTrue(Query(u'Angstrom').search(self.s4)) self.assertTrue(Query(u'Ångström').search(self.s4)) self.assertTrue(Query(u'Ångstrom').search(self.s4)) self.assertFalse(Query(u'Ängström').search(self.s4))
def test_filename_utf8_fallback(self): self.failUnless(Query(u"filename=foü.ogg").search(self.s3)) self.failUnless(Query(u"filename=öä").search(self.s3))
def test_utf8(self): # also handle undecoded values self.assertTrue(Query(u"utf8=Ångström").search(self.s4))
def test_str(self): for k in self.s2.keys(): v = self.s2[k] self.failUnless(Query('%s = "%s"' % (k, v)).search(self.s2)) self.failIf(Query('%s = !"%s"' % (k, v)).search(self.s2))
def PluginPreferences(self, parent): vbox = Gtk.VBox(spacing=6) queries = {} query_path = os.path.join(get_user_dir(), 'lists', 'queries.saved') with open(query_path, 'rU', encoding='utf-8') as query_file: for query_string in query_file: name = next(query_file).strip() queries[name] = Query(query_string.strip()) for query_name, query in queries.items(): check_button = ConfigCheckButton((query_name), "plugins", self._config_key(query_name)) check_button.set_active(self.config_get_bool(query_name)) vbox.pack_start(check_button, False, True, 0) chooserButton = Gtk.FileChooserButton(_('Select destination folder')) chooserButton.set_current_folder(self.lastfolder) chooserButton.set_action(Gtk.FileChooserAction.SELECT_FOLDER) # https://stackoverflow.com/a/14742779/109813 def get_actual_filename(name): # Do nothing except on Windows if os.name != 'nt': return name dirs = name.split('\\') # disk letter test_name = [dirs[0].upper()] for d in dirs[1:]: test_name += ["%s[%s]" % (d[:-1], d[-1])] res = glob.glob('\\'.join(test_name)) if not res: # File not found, return the input return name return res[0] def __file_error(file_path): qltk.ErrorMessage( None, _("Unable to export playlist"), _("Writing to <b>%s</b> failed.") % util.escape(file_path)).run() def __m3u_export(dir_path, query_name, songs): file_path = os.path.join(dir_path, query_name + '.m3u') try: fhandler = open(file_path, "wb") except IOError: __file_error(file_path) else: text = "#EXTM3U\n" for song in songs: title = "%s - %s" % (song('~people').replace( "\n", ", "), song('~title~version')) path = song('~filename') path = get_actual_filename(path) try: path = relpath(path, dir_path) except ValueError: # Keep absolute path pass text += "#EXTINF:%d,%s\n" % (song('~#length'), title) text += path + "\n" fhandler.write(text.encode("utf-8")) fhandler.close() def __start(button): target_folder = chooserButton.get_filename() songs = app.library.get_content() for query_name, query in queries.items(): if self.config_get_bool(query_name): # Query is enabled songs_for_query = query.filter(songs) __m3u_export(target_folder, query_name, songs_for_query) message = qltk.Message(Gtk.MessageType.INFO, app.window, _("Done"), _("Export finished.")) message.run() start_button = Gtk.Button(label=("Export")) start_button.connect('clicked', __start) vbox.pack_start(chooserButton, True, True, 0) vbox.pack_start(start_button, True, True, 0) label = Gtk.Label( label= "Quod Libet may become unresponsive. You will get a message when finished." ) vbox.pack_start(label, True, True, 0) return qltk.Frame(("Select the saved searches to copy:"), child=vbox)
def test_numcmp(self): self.failIf(Query("#(track = 0)").search(self.s1)) self.failIf(Query("#(notatag = 0)").search(self.s1)) self.failUnless(Query("#(track = 12)").search(self.s2))
def filter_text(self, text): self.__search.set_text(text) if Query(text).is_parsable: self.__update_filter(self.__search, text) self.activate()
def test_re_or(self): self.failUnless(Query("album = |(/ate/,/est/)").search(self.s1)) self.failUnless(Query("album = |(/ate/,/ets/)").search(self.s1)) self.failIf(Query("album = |(/tate/, /ets/)").search(self.s1))
def test_2007_07_27_synth_search(self): song = self.AF({"~filename": "foo/64K/bar.ogg"}) query = Query("~dirname = !64K") self.failIf(query.search(song), "%r, %r" % (query, song))
def test_exp_or(self): self.failUnless(Query("|(album = ate, artist = man)").search(self.s1)) self.failUnless(Query("|(album = ate, artist = nam)").search(self.s1)) self.failIf(Query("&(album = tea, artist = nam)").search(self.s1))
def test_empty(self): self.failIf(Query("foobar = /./").search(self.s1))
def test_dumb_search_value(self): self.failUnless(Query("|(ate, foobar)").search(self.s1)) self.failUnless(Query("!!|(ate, foobar)").search(self.s1)) self.failUnless(Query("&(ate, te)").search(self.s1)) self.failIf(Query("|(foo, bar)").search(self.s1)) self.failIf(Query("&(ate, foobar)").search(self.s1)) self.failIf(Query("! !&(ate, foobar)").search(self.s1)) self.failIf(Query("&blah").search(self.s1)) self.failUnless(Query("&blah oh").search(self.s5)) self.failUnless(Query("!oh no").search(self.s5)) self.failIf(Query("|blah").search(self.s1)) # https://github.com/quodlibet/quodlibet/issues/1056 self.failUnless(Query("&(ate, piman)").search(self.s1))
def test_gte(self): self.failUnless(Query("#(track >= 11)").search(self.s2))
def test_unslashed_search(self): self.failUnless(Query("artist=piman").search(self.s1)) self.failUnless(Query(u"title=ång").search(self.s4)) self.failIf(Query("artist=mu").search(self.s1)) self.failIf(Query(u"title=äng").search(self.s4))
def test_not(self): for s in ["album = !hate", "artist = !pi"]: self.failIf(Query(s).search(self.s1)) self.failUnless(Query(s).search(self.s2))
def test_search_almostequal(self): a, b = self.AF({"~#rating": 0.771}), self.AF({"~#rating": 0.769}) self.failUnless(Query("#(rating = 0.77)").search(a)) self.failUnless(Query("#(rating = 0.77)").search(b))
def test_abbrs(self): for s in ["b = /i hate/", "a = /pi*/", "t = /x.y/"]: self.failUnless(Query(s).search(self.s1)) self.failIf(Query(s).search(self.s2))
def test_fs_utf8(self): self.failUnless(Query(u"~filename=foü.ogg").search(self.s3)) self.failUnless(Query(u"~filename=öä").search(self.s3)) self.failUnless(Query(u"~dirname=öäü").search(self.s3)) self.failUnless(Query(u"~basename=ü.ogg").search(self.s3))
def test_numcmp_func(self): self.assertTrue(Query("#(t:min < 3)").valid) self.assertTrue( Query("&(#(playcount:min = 0), #(added < 1 month ago))").valid)