ExportXMLWordPrintable

    • Type: Bug
    • Resolution: Fixed
    • Priority: Normal
    • 3.0.0rc1
    • Affects Version/s: None
    • Component/s: File Formats
    • None

      When an ASF/WMA/WMV file has a rating of 0, Picard writes it to the file correctly but drops it when reading the file back. Saving a 0 rating and reloading returns no rating at all. Every other supported format (ID3, Vorbis, MP4, APEv2) preserves a rating of 0, so ASF is inconsistent.

      Steps to reproduce

      1. Load a WMA/WMV/ASF file in Picard.
      2. Set its rating to 0 (no stars).
      3. Save the file.
      4. Remove the file and load it again (or inspect the loaded metadata).

      Expected result

      The rating loads back as 0, matching what was saved and matching the behavior of all other formats.

      Actual result

      The rating is missing after reload. The ~rating tag is absent from the loaded metadata even though WM/SharedUserRating was written to the file correctly (verified as ASFDWordAttribute(0)).

      Root cause

      In ASFFile._load() (picard/formats/asf.py), the WM/SharedUserRating value is normalized from the 0-99 WMA scale to Picard's 0-5 scale and left as an int:

      values[0] = int(round(int(str(values[0])) / 99.0 * (config.setting['rating_steps'] - 1)))
      

      A few lines later, all tag values pass through a truthiness filter:

      values = [str(value) for value in values if value]
      

      The rating is still an int at this point, so a value of 0 is falsy and is silently dropped. Empty strings must still be filtered out, so the filter itself is correct; the problem is that the rating is tested for truthiness as an int before being converted to a string.

      Suggested fix

      Convert the normalized rating to str immediately, so 0 becomes '0' and survives the truthiness filter:

      values[0] = str(int(round(int(str(values[0])) / 99.0 * (config.setting['rating_steps'] - 1))))
      

      This makes ASF consistent with ID3, Vorbis, MP4, and APEv2, all of which already preserve a rating of 0. Empty strings continue to be filtered as before.

      History

      • Latent since commit 31af96b5d1 ("Support ratings in WMA files", Philipp Wolfer, 2009-02-20), which introduced the int-normalization plus truthiness-filter pattern. Under Python 2 the code was filter(bool, map(unicode, values)), which stringified before filtering, so 0 (-> u'0', truthy) survived.
      • Became a live bug at commit 8834ec3384 ("Fix filter,map and reduce behaviour for py3", Sambhav Kothari, 2017-03-31), which rewrote the line as [str(value) for value in values if value]. This tests the still-int rating 0 for truthiness before converting it, so 0 is now dropped. Shipped from Picard 2.0 onward.
      • Commit 683b9346858 ("Drop use of string_(), deprecated", 2018-09-06) only renamed string_() -> str() and did not change the behaviour.

            Assignee:
            Zas
            Reporter:
            Zas
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:

                Version Package
                3.0.0rc1