This file is indexed.

/usr/share/pyshared/musiclibrarian/musicfile.py is in musiclibrarian 1.6-2.2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# musicfile.py
#  Copyright 2004 Daniel Burrows
#
#  Core classes for storing information about a music file.

import listenable

class MusicFileError(Exception):
    def __init__(self, strerror):
        self.strerror=strerror

    def __str__(self):
        return self.strerror

# The set of known file extensions and associated classes.  It is
# assumed that None is not included in this dictionary.
file_types = { }

def register_file_type(ext, cls):
    """Add a new file type.  'cls' is a class or other callable object
    which takes a single argument (the name of the file to load) and
    returns a file instance."""

    file_types[ext]=cls

class File(listenable.Listenable):
    """This is the most generic abstraction of a file.

    Actual files must implement additional methods like get_tags,
    set_tags, etc."""
    def __init__(self, store):
        listenable.Listenable.__init__(self)

        self.store=store

# A file with a dict interface.  This is an abstract class; subclasses
# need to implement the write_to_file() and get_file() methods and
# initialize "comments" in their constructor.  It is ASSUMED that the
# keys in "comments" are upper-case.
#
# write_to_file() is responsible for actually writing out the current
# data to the file.  get_file() returns a "file-like" object:
# specifically, one with a read() method.  This method will return a
# tuple (data,amt) when called.
class DictFile(File):
    """This class represents a file whose attributes 'look' like a
    dictionary.  Most files will fall into this category.  All keys of
    the dictionary are assumed to be upper-case.

    Subclasses are responsible for implementing write_to_file()."""

    def __init__(self, store, comments):
        """Set this instance up with the given initial store pointer and
        comment dictionary."""
        File.__init__(self, store)
        self.comments=comments
        self.__rationalize_comments()
        self.backup_comments=self.comments.copy()
        self.modified=0

    def __rationalize_comments(self):
        """Purge empty comments from the comments dictionary."""
        for key,val in self.comments.items():
            if val == []:
                del self.comments[key]

    def get_tag(self, key):
        """Returns a list of zero or more strings associated with the
        given case-insensitive key."""
        return self.comments.get(key.upper(), [])

    def set_tags(self, dict):
        """Sets all tags of this object to the values stored in the
        given dictionary."""
        if self.comments <> dict:
            oldcomments=self.comments
            self.comments=dict.copy()
            self.__rationalize_comments()

            self.modified = (self.comments <> self.backup_comments)

            self.store.set_modified(self, self.modified)

            self.call_listeners(self, oldcomments)

    def set_tag(self, key, val):
        """Sets a single tag to the given value."""
        if self.get_tag(key) <> val:
            upkey=key.upper()
            # used to handle updating structures in the GUI:
            oldcomments=self.comments.copy()

            if val==[]:
                del self.comments[upkey]
            else:
                self.comments[upkey]=val

            # careful here. (could just always compare dictionaries,
            # but this is a little more efficient in some common
            # cases)
            if (not self.modified):
                # if it wasn't modified, we can just compare the new value
                # to the old value.
                self.modified=(val <> self.backup_comments.get(upkey, []))
            else:
                # it was modified; if this key is now the same as its
                # original value, compare the whole dictionary. (no
                # way around this right now) Note that if it isn't the
                # same, you might as well just leave it modified.
                if val == self.backup_comments.get(upkey, []):
                    self.modified = (self.comments <> self.backup_comments)

            self.store.set_modified(self, self.modified)

            self.call_listeners(self, oldcomments)

    def get_cache(self):
        """Returns a dictionary whose members are the comments attached to this file."""

        return self.backup_comments.copy()

    def tags(self):
        """Returns a list of the tags of this file."""
        return self.comments.keys()

    def values(self):
        """Returns a list of the values associated with tags of this file."""
        return self.comments.values()

    def items(self):
        """Returns a list of pairs (tag,value) representing the tags of this file."""
        return self.comments.items()

    def set_tag_first(self, key, val):
        """Sets only the first entry of the given tag, leaving the
        rest of the entries (if there are any) unmodified."""
        cur=self.get_tag(key)
        if cur==[]:
            if val <> None:
                self.set_tag(key, [val])
        elif val==None:
            new=list(cur)
            del new[0]
            self.set_tag(key, new)
        elif cur[0] <> val:
            new=list(cur)
            new[0]=val
            self.set_tag(key, new)

    def commit(self):
        """Commit any changes to the backing file."""
        if self.modified:
            self.write_to_file()
            self.modified=0
            self.store.set_modified(self, False)

            self.call_listeners(self, self.comments)
            self.backup_comments=self.comments.copy()

    def revert(self):
        """Revert any modified comments to their original values."""
        if self.modified:
            # no copy, we aren't modifying them.
            oldcomments=self.comments
            self.comments=self.backup_comments.copy()
            self.modified=0
            self.store.set_modified(self, False)

            self.call_listeners(self, oldcomments)