Switch to unified view

a/src/mediaserver/cdplugins/uprcl/uprclfolders.py b/src/mediaserver/cdplugins/uprcl/uprclfolders.py
...
...
46
# configuration. The entries are paths instead of simple names, and
46
# configuration. The entries are paths instead of simple names, and
47
# the docidx is 0. The diridx points to a dirvec entry.
47
# the docidx is 0. The diridx points to a dirvec entry.
48
48
49
import os
49
import os
50
import shlex
50
import shlex
51
import urllib
52
import sys
51
import sys
52
PY3 = sys.version > '3'
53
if PY3:
54
    from urllib.parse import quote as urlquote
55
else:
56
    from urllib import quote as urlquote
57
53
import time
58
import time
54
from timeit import default_timer as timer
59
from timeit import default_timer as timer
55
60
56
from upmplgutils import uplog
61
from upmplgutils import uplog
57
from uprclutils import docarturi, audiomtypes, rcldirentry, \
62
from uprclutils import docarturi, audiomtypes, rcldirentry, \
...
...
105
            self._dirvec[-1][".."] = (0, -1)
110
            self._dirvec[-1][".."] = (0, -1)
106
111
107
        # Walk the doc list and update the directory tree according to the
112
        # Walk the doc list and update the directory tree according to the
108
        # url: create intermediary directories if needed, create leaf
113
        # url: create intermediary directories if needed, create leaf
109
        # entry.
114
        # entry.
115
        #
116
        # Binary path issue: at the moment the python rclconfig can't
117
        # handle binary (the underlying conftree.py can, we'd need a
118
        # binary stringToStrings). So the topdirs entries have to be
119
        # strings, and so we decode the binurl too. This probably
120
        # could be changed we wanted to support binary, (non utf-8)
121
        # paths. For now, for python3 all dir/file names in the tree
122
        # are str
110
        for docidx in range(len(self._rcldocs)):
123
        for docidx in range(len(self._rcldocs)):
111
            doc = self._rcldocs[docidx]
124
            doc = self._rcldocs[docidx]
112
            
125
            
113
            # No need to include non-audio types in the visible tree.
126
            # No need to include non-audio types in the visible tree.
114
            if doc.mtype not in audiomtypes:
127
            if doc.mtype not in audiomtypes:
...
...
119
            if arturi:
132
            if arturi:
120
                # The uri is quoted, so it's ascii and we can just store
133
                # The uri is quoted, so it's ascii and we can just store
121
                # it as a doc attribute
134
                # it as a doc attribute
122
                doc.albumarturi = arturi
135
                doc.albumarturi = arturi
123
136
124
            url = doc.getbinurl()
137
            url = doc.getbinurl().decode('utf-8', errors='replace')
125
            url = url[7:]
138
            url = url[7:]
126
            try:
127
                decoded = url.decode('utf-8')
128
            except:
129
                decoded = urllib.quote(url).decode('utf-8')
130
131
            # Determine the root entry (topdirs element). Special because
139
            # Determine the root entry (topdirs element). Special because
132
            # its path is not a simple name.
140
            # its path is not a simple name.
133
            fathidx = -1
141
            fathidx = -1
134
            for rtpath,idx in self._dirvec[0].iteritems():
142
            for rtpath,idx in self._dirvec[0].items():
143
                #uplog("type(url) %s type(rtpath) %s rtpath %s url %s" %
144
                # (type(url),type(rtpath),rtpath, url))
135
                if url.startswith(rtpath):
145
                if url.startswith(rtpath):
136
                    fathidx = idx[0]
146
                    fathidx = idx[0]
137
                    break
147
                    break
138
            if fathidx == -1:
148
            if fathidx == -1:
139
                uplog("No parent in topdirs: %s" % decoded)
149
                uplog("No parent in topdirs: %s" % url)
140
                continue
150
                continue
141
151
142
            # Compute rest of path
152
            # Compute rest of path
143
            url1 = url[len(rtpath):]
153
            url1 = url[len(rtpath):]
144
            if len(url1) == 0:
154
            if len(url1) == 0:
...
...
146
156
147
            # If there is a contentgroup field, just add it as a virtual
157
            # If there is a contentgroup field, just add it as a virtual
148
            # directory in the path. This only affects the visible tree,
158
            # directory in the path. This only affects the visible tree,
149
            # not the 'real' URLs of course.
159
            # not the 'real' URLs of course.
150
            if doc.contentgroup:
160
            if doc.contentgroup:
151
                a = os.path.dirname(url1).decode('utf-8', errors='replace')
161
                a = os.path.dirname(url1)
152
                b = os.path.basename(url1).decode('utf-8', errors='replace')
162
                b = os.path.basename(url1)
153
                url1 = os.path.join(a, doc.contentgroup, b)
163
                url1 = os.path.join(a, doc.contentgroup, b)
154
            
164
            
155
            # Split path, then walk the vector, possibly creating
165
            # Split path, then walk the vector, possibly creating
156
            # directory entries as needed
166
            # directory entries as needed
157
            path = url1.split('/')[1:]
167
            path = url1.split('/')[1:]
...
...
162
                    # This path element was already seen
172
                    # This path element was already seen
163
                    # If this is the last entry in the path, maybe update
173
                    # If this is the last entry in the path, maybe update
164
                    # the doc idx (previous entries were created for
174
                    # the doc idx (previous entries were created for
165
                    # intermediate elements without a Doc).
175
                    # intermediate elements without a Doc).
166
                    if idx == len(path) -1:
176
                    if idx == len(path) -1:
177
                        self._dirvec[fathidx][elt] = \
167
                        self._dirvec[fathidx][elt] = (self._dirvec[fathidx][elt][0], docidx)
178
                                   (self._dirvec[fathidx][elt][0], docidx)
168
                        #uplog("updating docidx for %s" % decoded)
169
                    # Update fathidx for next iteration
179
                    # Update fathidx for next iteration
170
                    fathidx = self._dirvec[fathidx][elt][0]
180
                    fathidx = self._dirvec[fathidx][elt][0]
171
                else:
181
                else:
172
                    # Element has no entry in father directory (hence no
182
                    # Element has no entry in father directory (hence no
173
                    # self._dirvec entry either).
183
                    # self._dirvec entry either).
...
...
177
                        fathidx = self._createdir(fathidx, -1, elt)
187
                        fathidx = self._createdir(fathidx, -1, elt)
178
                    else:
188
                    else:
179
                        # Last element. If directory, needs a self._dirvec entry
189
                        # Last element. If directory, needs a self._dirvec entry
180
                        if doc.mtype == 'inode/directory':
190
                        if doc.mtype == 'inode/directory':
181
                            fathidx = self._createdir(fathidx, docidx, elt)
191
                            fathidx = self._createdir(fathidx, docidx, elt)
182
                            #uplog("Setting docidx for %s" % decoded)
183
                        else:
192
                        else:
184
                            self._dirvec[fathidx][elt] = (-1, docidx)
193
                            self._dirvec[fathidx][elt] = (-1, docidx)
185
194
186
        if False:
195
        if False:
187
            for ent in self._dirvec:
196
            for ent in self._dirvec:
...
...
204
        uplog("Estimated alldocs query results: %d" % (rclq.rowcount))
213
        uplog("Estimated alldocs query results: %d" % (rclq.rowcount))
205
214
206
        totcnt = 0
215
        totcnt = 0
207
        self._rcldocs = []
216
        self._rcldocs = []
208
        while True:
217
        while True:
218
            # There are issues at the end of list with fetchmany (sets
219
            # an exception). Works in python2 for some reason, but
220
            # breaks p3. Until recoll is fixed, catch exception
221
            # here. Also does not work if we try to fetch by bigger
222
            # slices (we get an exception and a truncated list)
223
            try:
209
            docs = rclq.fetchmany()
224
                docs = rclq.fetchmany()
210
            for doc in docs:
225
                for doc in docs:
211
                self._rcldocs.append(doc)
226
                    self._rcldocs.append(doc)
212
                totcnt += 1
227
                    totcnt += 1
228
            except:
229
                docs = []
213
            if (self._maxrclcnt > 0 and totcnt >= self._maxrclcnt) or \
230
            if (self._maxrclcnt > 0 and totcnt >= self._maxrclcnt) or \
214
                   len(docs) != rclq.arraysize:
231
                   len(docs) != rclq.arraysize:
215
                break
232
                break
216
            time.sleep(0)
233
            time.sleep(0)
217
        end = timer()
234
        end = timer()
...
...
250
267
251
268
252
    # Look all non-directory docs inside directory, and return the cover
269
    # Look all non-directory docs inside directory, and return the cover
253
    # art we find.
270
    # art we find.
254
    def _arturifordir(self, diridx):
271
    def _arturifordir(self, diridx):
255
        for nm,ids in self._dirvec[diridx].iteritems():
272
        for nm,ids in self._dirvec[diridx].items():
256
            if ids[1] >= 0:
273
            if ids[1] >= 0:
257
                doc = self._rcldocs[ids[1]]
274
                doc = self._rcldocs[ids[1]]
258
                if doc.mtype != 'inode/directory' and doc.albumarturi:
275
                if doc.mtype != 'inode/directory' and doc.albumarturi:
259
                    return doc.albumarturi
276
                    return doc.albumarturi
260
              
277
              
...
...
274
        
291
        
275
        entries = []
292
        entries = []
276
293
277
        # The basename call is just for diridx==0 (topdirs). Remove it if
294
        # The basename call is just for diridx==0 (topdirs). Remove it if
278
        # this proves a performance issue
295
        # this proves a performance issue
279
        for nm,ids in self._dirvec[diridx].iteritems():
296
        for nm,ids in self._dirvec[diridx].items():
280
            if nm == "..":
297
            if nm == "..":
281
                continue
298
                continue
282
            thisdiridx = ids[0]
299
            thisdiridx = ids[0]
283
            thisdocidx = ids[1]
300
            thisdocidx = ids[1]
284
            if thisdocidx >= 0:
301
            if thisdocidx >= 0:
...
...
307
                id = self._idprefix + '$i' + str(thisdocidx)
324
                id = self._idprefix + '$i' + str(thisdocidx)
308
                e = rcldoctoentry(id, pid, self._httphp, self._pprefix, doc)
325
                e = rcldoctoentry(id, pid, self._httphp, self._pprefix, doc)
309
                if e:
326
                if e:
310
                    entries.append(e)
327
                    entries.append(e)
311
328
329
        if PY3:
330
            return sorted(entries, key=cmpentries)
331
        else:
312
        return sorted(entries, cmp=cmpentries)
332
            return sorted(entries, cmp=cmpentries)
313
333
314
    # Return path for objid, which has to be a container.This is good old
334
    # Return path for objid, which has to be a container.This is good old
315
    # pwd... It is called from the search module for generating a 'dir:'
335
    # pwd... It is called from the search module for generating a 'dir:'
316
    # recoll filtering directive.
336
    # recoll filtering directive.
317
    def dirpath(self, objid):
337
    def dirpath(self, objid):
...
...
326
            return "/"
346
            return "/"
327
    
347
    
328
        lpath = []
348
        lpath = []
329
        while True:
349
        while True:
330
            fathidx = self._dirvec[diridx][".."][0]
350
            fathidx = self._dirvec[diridx][".."][0]
331
            for nm, ids in self._dirvec[fathidx].iteritems():
351
            for nm, ids in self._dirvec[fathidx].items():
332
                if ids[0] == diridx:
352
                if ids[0] == diridx:
333
                    lpath.append(nm)
353
                    lpath.append(nm)
334
                    break
354
                    break
335
                diridx = fathidx
355
                diridx = fathidx
336
                if diridx == 0:
356
                if diridx == 0: