コード例 #1
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_same2(s):
     fpat = FileFromPattern('<~filename>')
     pat = Pattern('<~filename>')
     s.assertEquals(fpat.format_list(s.a),
                    {(fpat.format(s.a), fpat.format(s.a))})
     s.assertEquals(pat.format_list(s.a),
                    {(pat.format(s.a), pat.format(s.a))})
コード例 #2
0
ファイル: website_search.py プロジェクト: urielz/quodlibet
 def plugin_songs(self, songs):
     # Check this is a launch, not a configure
     if self.chosen_site:
         url_pat = self.get_url_pattern(self.chosen_site)
         pat = Pattern(url_pat)
         urls = set()
         for song in songs:
             # Generate a sanitised AudioFile; allow through most tags
             subs = AudioFile()
             for k in (USER_TAGS + MACHINE_TAGS):
                 vals = song.comma(k)
                 if vals:
                     try:
                         encoded = unicode(vals).encode('utf-8')
                         subs[k] = (encoded if k == 'website'
                                    else quote_plus(encoded))
                     # Dodgy unicode problems
                     except KeyError:
                         print_d("Problem with %s tag values: %r"
                                 % (k, vals))
             url = str(pat.format(subs))
             if not url:
                 print_w("Couldn't build URL using \"%s\"."
                         "Check your pattern?" % url_pat)
                 return
             # Grr, set.add() should return boolean...
             if url not in urls:
                 urls.add(url)
                 website(url)
コード例 #3
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_sort_combine(s):
     pat = Pattern('<album> <artist>')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u'Album5 Artist1', u'SortAlbum5 SortA1'),
                        (u'Album5 ', u'SortAlbum5 SortA2'),
                        (u'Album5 Artist3', u'SortAlbum5 Artist3')})
     pat = Pattern('x <artist> <album>')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u'x Artist1 Album5', u'x SortA1 SortAlbum5'),
                        (u'x  Album5', u'x SortA2 SortAlbum5'),
                        (u'x Artist3 Album5', u'x Artist3 SortAlbum5')})
     pat = Pattern(' <artist> <album> xx')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u' Artist1 Album5 xx', u' SortA1 SortAlbum5 xx'),
                        (u'  Album5 xx', u' SortA2 SortAlbum5 xx'),
                        (u' Artist3 Album5 xx', u' Artist3 SortAlbum5 xx')})
     pat = Pattern('<album> <tracknumber> <artist>')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u'Album5 7/8 Artist1', u'SortAlbum5 7/8 SortA1'),
                        (u'Album5 7/8 ', u'SortAlbum5 7/8 SortA2'),
                        (u'Album5 7/8 Artist3', u'SortAlbum5 7/8 Artist3')})
     pat = Pattern('<tracknumber> <album> <artist>')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u'7/8 Album5 Artist1', u'7/8 SortAlbum5 SortA1'),
                        (u'7/8 Album5 ', u'7/8 SortAlbum5 SortA2'),
                        (u'7/8 Album5 Artist3', u'7/8 SortAlbum5 Artist3')})
コード例 #4
0
ファイル: mqtt.py プロジェクト: Muges/quodlibet
 def plugin_on_song_started(self, song):
     self.song = song
     pat_str = self.config_get(*Config.PAT_PLAYING)
     pattern = Pattern(pat_str)
     status = (pattern.format(song) if song
               else self.config_get(Config.STATUS_SONGLESS, ""))
     self._set_status(status)
コード例 #5
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_escape_slash(s):
     fpat = s._create('<~filename>')
     pat = Pattern('<~filename>')
     wpat = s._create(r'\\<artist>\\ "<title>')
     s.assertTrue(fpat.format(s.a).startswith("_path_to_a.mp3"))
     s.assertTrue(pat.format(s.a).startswith("/path/to/a"))
     if os.name != "nt":
         s.assertTrue(wpat.format(s.a).startswith("\\Artist\\ \"Title5"))
     else:
         # FIXME..
         pass
コード例 #6
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_sort_multiply(s):
     pat = Pattern('<artist> <artist>')
     s.failUnlessEqual(pat.format_list(s.h),
                       {(u'Artist1 Artist1', u'SortA1 SortA1'),
                        (u' Artist1', u'SortA2 SortA1'),
                        (u'Artist3 Artist1', u'Artist3 SortA1'),
                        (u'Artist1 ', u'SortA1 SortA2'),
                        (u' ', u'SortA2 SortA2'),
                        (u'Artist3 ', u'Artist3 SortA2'),
                        (u'Artist1 Artist3', u'SortA1 Artist3'),
                        (u' Artist3', u'SortA2 Artist3'),
                        (u'Artist3 Artist3', u'Artist3 Artist3')})
コード例 #7
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_same(s):
     pat = Pattern('<~basename> <title>')
     s.failUnlessEqual(pat.format_list(s.a),
                       {(pat.format(s.a), pat.format(s.a))})
     pat = Pattern('/a<genre|/<genre>>/<title>')
     s.failUnlessEqual(pat.format_list(s.a),
                       {(pat.format(s.a), pat.format(s.a))})
コード例 #8
0
 def __init__(self, name=None, command=None, pattern="<~filename>",
              unique=False, parameter=None, max_args=10000,
              warn_threshold=100):
     JSONObject.__init__(self, name)
     self.command = str(command or "")
     self.pattern = str(pattern)
     self.unique = bool(unique)
     self.max_args = max_args
     self.parameter = str(parameter or "")
     self.__pat = Pattern(self.pattern)
     self.warn_threshold = warn_threshold
コード例 #9
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_sort(s):
     pat = Pattern('<album>')
     s.failUnlessEqual(pat.format_list(s.f),
                       {(u'Best Of', u'Best Of')})
     pat = Pattern('<album>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Album5', u'SortAlbum5')})
     pat = Pattern('<artist>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'),
                                              (u'', u'SortA2'),
                                              (u'Artist3', u'Artist3')})
     pat = Pattern('<artist> x')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1 x', u'SortA1 x'),
                                              (u' x', u'SortA2 x'),
                                              (u'Artist3 x', u'Artist3 x')})
コード例 #10
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_space(self):
     pat = Pattern("a ")
     self.assertEqual(pat.format(self.a), "a ")
     pat = Pattern(" a")
     self.assertEqual(pat.format(self.a), " a")
     pat = Pattern("a\n\n")
     self.assertEqual(pat.format(self.a), "a\n\n")
コード例 #11
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_tag_query_escaped_pipe(s):
     pat = Pattern(r'<albumartist=/Lee\|Bob/|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'matched')
     pat = Pattern(r'<albumartist=\||matched|not matched>')
     s.assertEquals(pat.format(s.g), 'not matched')
     pat = Pattern(r'<comment=/Trouble\|Strife/|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'matched')
コード例 #12
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_tag_query_regex(s):
     pat = Pattern("<album=/'only'/|matched|not matched>")
     s.assertEquals(pat.format(s.g), 'matched')
     pat = Pattern("<album=/The .+ way/|matched|not matched>")
     s.assertEquals(pat.format(s.g), 'matched')
     pat = Pattern("</The .+ way/|matched|not matched>")
     s.assertEquals(pat.format(s.g), 'not matched')
コード例 #13
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_tag_internal(self):
     if os.name != "nt":
         pat = Pattern("<~filename='/path/to/a.mp3'|matched|not matched>")
         self.assertEquals(pat.format(self.a), 'matched')
         pat = Pattern(
             "<~filename=/\\/path\\/to\\/a.mp3/|matched|not matched>")
         self.assertEquals(pat.format(self.a), 'matched')
     else:
         pat = Pattern(
             r"<~filename='C:\\\path\\\to\\\a.mp3'|matched|not matched>")
         self.assertEquals(pat.format(self.a), 'matched')
コード例 #14
0
ファイル: website_search.py プロジェクト: LudoBike/quodlibet
def website_for(pat: Pattern, song: AudioFile) -> Optional[str]:
    """Gets a utf-8 encoded string for a website from the given pattern"""

    # Generate a sanitised AudioFile; allow through most tags
    subs = AudioFile()
    # See issue 2762
    for k in (USER_TAGS + MACHINE_TAGS + ['~filename']):
        vals = song.comma(k)
        if vals:
            try:
                # Escaping ~filename stops ~dirname ~basename etc working
                # But not escaping means ? % & will cause problems.
                # Who knows what user wants to do with /, seems better raw.
                subs[k] = (vals if k in ['website', '~filename']
                           else quote_plus(vals))
            except KeyError:
                print_d("Problem with %s tag values: %r" % (k, vals))
    return pat.format(subs) or None
コード例 #15
0
ファイル: test_pattern.py プロジェクト: LudoBike/quodlibet
 def test_sort_tied(s):
     pat = Pattern('<~artist~album>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'),
                                              (u'', u'SortA2'),
                                              (u'Artist3', u'Artist3'),
                                              (u'Album5', u'SortAlbum5')})
     pat = Pattern('<~album~artist>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'),
                                              (u'', u'SortA2'),
                                              (u'Artist3', u'Artist3'),
                                              (u'Album5', u'SortAlbum5')})
     pat = Pattern('<~artist~artist>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'),
                                              (u'', u'SortA2'),
                                              (u'Artist3', u'Artist3')})
コード例 #16
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_unicode_with_int(s):
     song = AudioFile({"tracknumber": "5/6",
         "title": "\xe3\x81\x99\xe3\x81\xbf\xe3\x82\x8c".decode('utf-8')})
     pat = Pattern('<~#track>. <title>')
     s.assertEquals(pat.format(song),
         "5. \xe3\x81\x99\xe3\x81\xbf\xe3\x82\x8c".decode('utf-8'))
コード例 #17
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_number_dot_title_dot(s):
     pat = Pattern('<tracknumber>. <title>.')
     s.assertEquals(pat.format(s.a), '5/6. Title5.')
     s.assertEquals(pat.format(s.b), '6. Title6.')
     s.assertEquals(pat.format(s.c), '. test/subdir.')
コード例 #18
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_query_scope(self):
     pat = Pattern("<foo|<artist=Foo|x|y>|<artist=Foo|z|q>>")
     self.assertEqual(pat.format(self.f), "z")
コード例 #19
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_conditional_notfile(s):
     pat = Pattern('<tracknumber|<tracknumber>|00>')
     s.assertEquals(pat.format(s.a), '5/6')
     s.assertEquals(pat.format(s.b), '6')
     s.assertEquals(pat.format(s.c), '00')
コード例 #20
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_recnumber_dot_title(s):
     pat = Pattern('\<<tracknumber>\>. <title>')
     s.assertEquals(pat.format(s.a), '<5/6>. Title5')
     s.assertEquals(pat.format(s.b), '<6>. Title6')
     s.assertEquals(pat.format(s.c), '<>. test/subdir')
コード例 #21
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_duplicate_query(self):
     pat = Pattern('<u=yes|<u=yes|x|y>|<u=yes|q|z>>')
     self.assertEqual(pat.format(AudioFile({"u": "yes"})), "x")
     self.assertEqual(pat.format(AudioFile({"u": "no"})), "z")
コード例 #22
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_conditional_genre(s):
     pat = Pattern('<genre|<genre>|music>')
     s.assertEquals(pat.format(s.a), 'music')
     s.assertEquals(pat.format(s.b), 'music')
     s.assertEquals(pat.format(s.c), '/, /')
コード例 #23
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_same(s):
     pat = Pattern('<~basename> <title>')
     s.failUnlessEqual(pat.format_list(s.a), set([pat.format(s.a)]))
     pat = Pattern('/a<genre|/<genre>>/<title>')
     s.failUnlessEqual(pat.format_list(s.a), set([pat.format(s.a)]))
コード例 #24
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
    def test_both(self):
        pat = "<foo|<~bar~fuu> - <fa>|<bar>>"
        self.failUnlessEqual(Pattern(pat).tags, ["bar", "fuu", "fa"])

        pat = "<foo|<~bar~fuu> - <fa>|<quux>>"
        self.failUnlessEqual(Pattern(pat).tags, ["bar", "fuu", "fa", "quux"])
コード例 #25
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_empty(self):
     self.failUnlessEqual(Pattern("").tags, [])
コード例 #26
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_number_dot_genre(s):
     pat = Pattern('<tracknumber>. <genre>')
     s.assertEquals(pat.format(s.a), '5/6. ')
     s.assertEquals(pat.format(s.b), '6. ')
     s.assertEquals(pat.format(s.c), '. /, /')
コード例 #27
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_number_dot_title_dot(s):
     pat = Pattern('<tracknumber>. <title>.')
     s.assertEquals(pat.format(s.a), '5/6. Title5.')
     s.assertEquals(pat.format(s.b), '6. Title6.')
     s.assertEquals(pat.format(s.c), '. test/subdir.')
コード例 #28
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_generated_and_not_generated(s):
     pat = Pattern('<~basename> <title>')
     res = pat.format(s.a)
     s.assertEquals(res,
                    os.path.basename(s.a["~filename"]) + " " + s.a["title"])
コード例 #29
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_generated(s):
     pat = Pattern('<~basename>')
     s.assertEquals(pat.format(s.a), os.path.basename(s.a["~filename"]))
コード例 #30
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_tied(s):
     pat = Pattern('<genre>')
     s.failUnlessEqual(pat.format_list(s.c), {'/', '/'})
     pat = Pattern('<performer>')
     s.failUnlessEqual(pat.format_list(s.d), {'a', 'b'})
     pat = Pattern('<performer><performer>')
     s.failUnlessEqual(set(pat.format_list(s.d)),
                       {'aa', 'ab', 'ba', 'bb'})
     pat = Pattern('<~performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d),
                       {'a - foo', 'b - foo', 'a - bar', 'b - bar'})
     pat = Pattern('<performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d),
                       {'a - foo', 'b - foo', 'a - bar', 'b - bar'})
     pat = Pattern('<artist|<artist>.|<performer>>')
     s.failUnlessEqual(pat.format_list(s.d), {'foo.', 'bar.'})
     pat = Pattern('<artist|<artist|<artist>.|<performer>>>')
     s.failUnlessEqual(pat.format_list(s.d), {'foo.', 'bar.'})
コード例 #31
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_query_like_tag(self):
     pat = Pattern("<t=v>")
     self.assertEqual(pat.format(AudioFile({"t=v": "foo"})), "foo")
コード例 #32
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_same2(s):
     fpat = FileFromPattern('<~filename>')
     pat = Pattern('<~filename>')
     s.assertEquals(fpat.format_list(s.a), set([fpat.format(s.a)]))
     s.assertEquals(pat.format_list(s.a), set([pat.format(s.a)]))
コード例 #33
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_conditional_equals(s):
     pat = Pattern('<artist=Artist|matched|not matched>')
     s.assertEquals(pat.format(s.a), 'matched')
     pat = Pattern('<artist=Artistic|matched|not matched>')
     s.assertEquals(pat.format(s.a), 'not matched')
コード例 #34
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_tied(s):
     pat = Pattern('<genre>')
     s.failUnlessEqual(pat.format_list(s.c), set(['/', '/']))
     pat = Pattern('<performer>')
     s.failUnlessEqual(pat.format_list(s.d), set(['a', 'b']))
     pat = Pattern('<performer><performer>')
     s.failUnlessEqual(set(pat.format_list(s.d)),
                       set(['aa', 'ab', 'ba', 'bb']))
     pat = Pattern('<~performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d),
                       set(['a - foo', 'b - foo', 'a - bar', 'b - bar']))
     pat = Pattern('<performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d),
                       set(['a - foo', 'b - foo', 'a - bar', 'b - bar']))
     pat = Pattern('<artist|<artist>.|<performer>>')
     s.failUnlessEqual(pat.format_list(s.d), set(['foo.', 'bar.']))
     pat = Pattern('<artist|<artist|<artist>.|<performer>>>')
     s.failUnlessEqual(pat.format_list(s.d), set(['foo.', 'bar.']))
コード例 #35
0
class Command(JSONObject):
    """
    Wraps an arbitrary shell command and its argument pattern.
    Serialises as JSON for some editability
    """

    NAME = _("Command")

    FIELDS = {
        "name": Field(_("name"), _("The name of this command")),

        "command": Field(_("command"), _("The shell command syntax to run")),

        "parameter": Field(_("parameter"),
                           _("If specified, a parameter whose occurrences in "
                             "the command will be substituted with a "
                             "user-supplied value, e.g. by using 'PARAM' "
                             "all instances of '{PARAM}' in your command will "
                             "have the value prompted for when run")),

        "pattern": Field(_("pattern"),
                         _("The QL pattern, e.g. <~filename>, to use to "
                           "compute a value for the command")),

        "unique": Field(_("unique"),
                        _("If set, this will remove duplicate computed values "
                          "of the pattern")),

        "max_args": Field(_("max args"),
                          _("The maximum number of argument to pass to the "
                            "command at one time (like xargs)")),
    }

    def __init__(self, name=None, command=None, pattern="<~filename>",
                 unique=False, parameter=None, max_args=10000,
                 warn_threshold=100):
        JSONObject.__init__(self, name)
        self.command = str(command or "")
        self.pattern = str(pattern)
        self.unique = bool(unique)
        self.max_args = max_args
        self.parameter = str(parameter or "")
        self.__pat = Pattern(self.pattern)
        self.warn_threshold = warn_threshold

    def run(self, songs):
        """
        Runs this command on `songs`,
        splitting into multiple calls if necessary
        """
        args = []
        if self.parameter:
            value = GetStringDialog(None, _("Input value"),
                                    _("Value for %s?") % self.parameter).run()
            self.command = self.command.format(**{self.parameter: value})
            print_d("Actual command=%s" % self.command)
        for song in songs:
            arg = str(self.__pat.format(song))
            if not arg:
                print_w("Couldn't build shell command using \"%s\"."
                        "Check your pattern?" % self.pattern)
                break
            if not self.unique:
                args.append(arg)
            elif arg not in args:
                args.append(arg)
        max = int((self.max_args or 10000))
        com_words = self.command.split(" ")
        while args:
            print_d("Running %s with %d substituted arg(s) (of %d%s total)..."
                    % (self.command, min(max, len(args)), len(args),
                       " unique" if self.unique else ""))
            util.spawn(com_words + args[:max])
            args = args[max:]

    def __str__(self):
        return "Command= {command} {pattern}".format(**dict(self.data))
コード例 #36
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
    def test_missing_value(self):
        pat = Pattern('<genre> - <artist>')
        self.assertEqual(pat.format_list(self.a), set([" - Artist"]))

        pat = Pattern('')
        self.assertEqual(pat.format_list(self.a), set([""]))
コード例 #37
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_empty(self):
     pat = Pattern("<nopenope>")
     self.assertEqual(pat.format_list(self.a), {("", "")})
コード例 #38
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_conditional_other_number_dot_title(s):
     pat = Pattern('<tracknumber|<tracknumber>|00>. <title>')
     s.assertEquals(pat.format(s.a), '5/6. Title5')
     s.assertEquals(pat.format(s.b), '6. Title6')
     s.assertEquals(pat.format(s.c), '00. test/subdir')
コード例 #39
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_query_numeric(self):
     pat = Pattern("<#(foo=42)|42|other>")
     self.assertEqual(pat.format(AudioFile()), "other")
     self.assertEqual(pat.format(AudioFile({"foo": "42"})), "42")
コード例 #40
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_conditional_other_other(s):
     # FIXME: was <tracknumber|a|b|c>.. but we can't put <>| in the format
     # string since it would break the XML pattern formater.
     s.assertEqual(Pattern('<tracknumber|a|b|c>').format(s.a), "")
コード例 #41
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_tag_query_disallowed_free_text(s):
     pat = Pattern("<The only way|matched|not matched>")
     s.assertEquals(pat.format(s.g), 'not matched')
コード例 #42
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_conditional_genre(s):
     pat = Pattern('<genre|<genre>|music>')
     s.assertEquals(pat.format(s.a), 'music')
     s.assertEquals(pat.format(s.b), 'music')
     s.assertEquals(pat.format(s.c), '/, /')
コード例 #43
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_number_dot_genre(s):
     pat = Pattern('<tracknumber>. <genre>')
     s.assertEquals(pat.format(s.a), '5/6. ')
     s.assertEquals(pat.format(s.b), '6. ')
     s.assertEquals(pat.format(s.c), '. /, /')
コード例 #44
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_numeric(self):
     pat = Pattern("<~#rating>")
     self.assertEqual(pat.format(self.a), "0.50")
コード例 #45
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_tag_query_quoting(s):
     pat = Pattern('<album=The only way|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'not matched')
     pat = Pattern("<album=\"The 'only' way!\"|matched|not matched>")
     s.assertEquals(pat.format(s.g), 'matched')
コード例 #46
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_tag_query_escaping(s):
     pat = Pattern('<albumartist=Lee "Scratch" Perry|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'matched')
コード例 #47
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
    def test_missing_value(self):
        pat = Pattern('<genre> - <artist>')
        self.assertEqual(pat.format_list(self.a), {" - Artist"})

        pat = Pattern('')
        self.assertEqual(pat.format_list(self.a), {""})
コード例 #48
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_string(s):
     pat = Pattern('display')
     s.assertEqual(pat.format_list(s.a), {("display", "display")})
コード例 #49
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_conditional_other_number_dot_title(s):
     pat = Pattern('<tracknumber|<tracknumber>|00>. <title>')
     s.assertEquals(pat.format(s.a), '5/6. Title5')
     s.assertEquals(pat.format(s.b), '6. Title6')
     s.assertEquals(pat.format(s.c), '00. test/subdir')
コード例 #50
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_missing_value(self):
     pat = Pattern('<genre> - <artist>')
     self.assertEqual(pat.format_list(self.a), {(" - Artist", " - Artist")})
     pat = Pattern('')
     self.assertEqual(pat.format_list(self.a), {("", "")})
コード例 #51
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_conditional_unknown(s):
     pat = Pattern('<album|foo|bar>')
     s.assertEquals(pat.format(s.a), 'bar')
コード例 #52
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_sort_combine(s):
     pat = Pattern('<album> <artist>')
     s.failUnlessEqual(
         pat.format_list(s.h), {(u'Album5 Artist1', u'SortAlbum5 SortA1'),
                                (u'Album5 ', u'SortAlbum5 SortA2'),
                                (u'Album5 Artist3', u'SortAlbum5 Artist3')})
     pat = Pattern('x <artist> <album>')
     s.failUnlessEqual(
         pat.format_list(s.h),
         {(u'x Artist1 Album5', u'x SortA1 SortAlbum5'),
          (u'x  Album5', u'x SortA2 SortAlbum5'),
          (u'x Artist3 Album5', u'x Artist3 SortAlbum5')})
     pat = Pattern(' <artist> <album> xx')
     s.failUnlessEqual(
         pat.format_list(s.h),
         {(u' Artist1 Album5 xx', u' SortA1 SortAlbum5 xx'),
          (u'  Album5 xx', u' SortA2 SortAlbum5 xx'),
          (u' Artist3 Album5 xx', u' Artist3 SortAlbum5 xx')})
     pat = Pattern('<album> <tracknumber> <artist>')
     s.failUnlessEqual(
         pat.format_list(s.h),
         {(u'Album5 7/8 Artist1', u'SortAlbum5 7/8 SortA1'),
          (u'Album5 7/8 ', u'SortAlbum5 7/8 SortA2'),
          (u'Album5 7/8 Artist3', u'SortAlbum5 7/8 Artist3')})
     pat = Pattern('<tracknumber> <album> <artist>')
     s.failUnlessEqual(
         pat.format_list(s.h),
         {(u'7/8 Album5 Artist1', u'7/8 SortAlbum5 SortA1'),
          (u'7/8 Album5 ', u'7/8 SortAlbum5 SortA2'),
          (u'7/8 Album5 Artist3', u'7/8 SortAlbum5 Artist3')})
コード例 #53
0
ファイル: test_pattern.py プロジェクト: SimonLarsen/quodlibet
 def test_conditional_equals_unicode(s):
     pat = Pattern(u'<artist=Artist|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'not matched')
     pat = Pattern(u'<artist=un élève français|matched|not matched>')
     s.assertEquals(pat.format(s.g), 'matched')
コード例 #54
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_sort(s):
     pat = Pattern('<album>')
     s.failUnlessEqual(pat.format_list(s.f), {(u'Best Of', u'Best Of')})
     pat = Pattern('<album>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Album5', u'SortAlbum5')})
     pat = Pattern('<artist>')
     s.failUnlessEqual(pat.format_list(s.h), {(u'Artist1', u'SortA1'),
                                              (u'', u'SortA2'),
                                              (u'Artist3', u'Artist3')})
     pat = Pattern('<artist> x')
     s.failUnlessEqual(
         pat.format_list(s.h), {(u'Artist1 x', u'SortA1 x'),
                                (u' x', u'SortA2 x'),
                                (u'Artist3 x', u'Artist3 x')})
コード例 #55
0
ファイル: custom_commands.py プロジェクト: LudoBike/quodlibet
class Command(JSONObject):
    """
    Wraps an arbitrary shell command and its argument pattern.
    Serialises as JSON for some editability
    """

    NAME = _("Command")

    FIELDS = {
        "name": Field(_("name"), _("The name of this command")),

        "command": Field(_("command"), _("The shell command syntax to run")),

        "parameter": Field(_("parameter"),
                           _("If specified, a parameter whose occurrences in "
                             "the command will be substituted with a "
                             "user-supplied value, e.g. by using 'PARAM' "
                             "all instances of '{PARAM}' in your command will "
                             "have the value prompted for when run")),

        "pattern": Field(_("pattern"),
                         _("The QL pattern, e.g. <~filename>, to use to "
                           "compute a value for the command. For playlists, "
                           "this also supports virtual tags <~playlistname> "
                           "and <~#playlistindex>.")),

        "unique": Field(_("unique"),
                        _("If set, this will remove duplicate computed values "
                          "of the pattern")),

        "max_args": Field(_("max args"),
                          _("The maximum number of argument to pass to the "
                            "command at one time (like xargs)")),
    }

    def __init__(self, name=None, command=None, pattern="<~filename>",
                 unique=False, parameter=None, max_args=10000,
                 warn_threshold=50):
        JSONObject.__init__(self, name)
        self.command = str(command or "")
        self.pattern = str(pattern)
        self.unique = bool(unique)
        self.max_args = max_args
        self.parameter = str(parameter or "")
        self.__pat = Pattern(self.pattern)
        self.warn_threshold = warn_threshold

    def run(self, songs, playlist_name=None):
        """
        Runs this command on `songs`,
        splitting into multiple calls if necessary.
        `playlist_name` if populated contains the Playlist's name.
        """
        args = []
        template_vars = {}
        if self.parameter:
            value = GetStringDialog(None, _("Input value"),
                                    _("Value for %s?") % self.parameter).run()
            template_vars[self.parameter] = value
        if playlist_name:
            print_d("Playlist command for %s" % playlist_name)
            template_vars["PLAYLIST"] = playlist_name
        self.command = self.command.format(**template_vars)
        print_d("Actual command=%s" % self.command)
        for i, song in enumerate(songs):
            wrapped = SongWrapper(song)
            if playlist_name:
                wrapped["~playlistname"] = playlist_name
                wrapped["~playlistindex"] = str(i + 1)
                wrapped["~#playlistindex"] = i + 1
            arg = str(self.__pat.format(wrapped))
            if not arg:
                print_w("Couldn't build shell command using \"%s\"."
                        "Check your pattern?" % self.pattern)
                break
            if not self.unique:
                args.append(arg)
            elif arg not in args:
                args.append(arg)
        max = int((self.max_args or 10000))
        com_words = self.command.split(" ")
        while args:
            print_d("Running %s with %d substituted arg(s) (of %d%s total)..."
                    % (self.command, min(max, len(args)), len(args),
                       " unique" if self.unique else ""))
            util.spawn(com_words + args[:max])
            args = args[max:]

    @property
    def playlists_only(self):
        return ("~playlistname" in self.pattern
                or "playlistindex" in self.pattern)

    def __str__(self):
        return 'Command: "{command} {pattern}"'.format(**dict(self.data))
コード例 #56
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_tied(s):
     pat = Pattern('<genre>')
     s.failUnlessEqual(pat.format_list(s.c), {('/', '/')})
     pat = Pattern('<performer>')
     s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b')})
     pat = Pattern('<performer><performer>')
     s.failUnlessEqual(set(pat.format_list(s.d)),
                       {('aa', 'aa'), ('ab', 'ab'), ('ba', 'ba'),
                        ('bb', 'bb')})
     pat = Pattern('<~performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b'),
                                              ('bar', 'bar'),
                                              ('foo', 'foo')})
     pat = Pattern('<performer~artist>')
     s.failUnlessEqual(pat.format_list(s.d), {('a', 'a'), ('b', 'b'),
                                              ('bar', 'bar'),
                                              ('foo', 'foo')})
     pat = Pattern('<artist|<artist>.|<performer>>')
     s.failUnlessEqual(pat.format_list(s.d), {('foo.', 'foo.'),
                                              ('bar.', 'bar.')})
     pat = Pattern('<artist|<artist|<artist>.|<performer>>>')
     s.failUnlessEqual(pat.format_list(s.d), {('foo.', 'foo.'),
                                              ('bar.', 'bar.')})
コード例 #57
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_conditional_unknown(s):
     pat = Pattern('<album|foo|bar>')
     s.assertEquals(pat.format(s.a), 'bar')
コード例 #58
0
ファイル: test_pattern.py プロジェクト: thisfred/quodlibet
 def test_conditional_subdir(s):
     pat = Pattern('/a<genre|/<genre>>/<title>')
     s.assertEquals(pat.format(s.a), '/a/Title5')
     s.assertEquals(pat.format(s.b), '/a/Title6')
     s.assertEquals(pat.format(s.c), '/a//, //test/subdir')
コード例 #59
0
ファイル: mqtt.py プロジェクト: Muges/quodlibet
 def plugin_on_paused(self):
     pat_str = self.config_get(*Config.PAT_PAUSED)
     pattern = Pattern(pat_str)
     self.status = pattern.format(self.song) if self.song else ""
     self._set_status(self.status)
コード例 #60
0
ファイル: test_pattern.py プロジェクト: tomscytale/quodlibet
 def test_duplicate_query(self):
     pat = Pattern('<u=yes|<u=yes|x|y>|<u=yes|q|z>>')
     self.assertEqual(pat.format(AudioFile({"u": u"yes"})), "x")
     self.assertEqual(pat.format(AudioFile({"u": u"no"})), "z")