~ubuntu-branches/debian/sid/dmedia/sid

« back to all changes in this revision

Viewing changes to .pc/02_fix_couchdb_deprecated_function.patch/dmedia/metastore.py

  • Committer: Bazaar Package Importer
  • Author(s): Bilal Akhtar
  • Date: 2011-01-04 16:03:29 UTC
  • Revision ID: james.westby@ubuntu.com-20110104160329-4e5vhosser50n4v7
Tags: 0.3.0~repack-1
Initial release (Closes: #608364)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Authors:
 
2
#   Jason Gerard DeRose <jderose@novacut.com>
 
3
#
 
4
# dmedia: distributed media library
 
5
# Copyright (C) 2010 Jason Gerard DeRose <jderose@novacut.com>
 
6
#
 
7
# This file is part of `dmedia`.
 
8
#
 
9
# `dmedia` is free software: you can redistribute it and/or modify it under the
 
10
# terms of the GNU Affero General Public License as published by the Free
 
11
# Software Foundation, either version 3 of the License, or (at your option) any
 
12
# later version.
 
13
#
 
14
# `dmedia` is distributed in the hope that it will be useful, but WITHOUT ANY
 
15
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 
16
# A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
 
17
# details.
 
18
#
 
19
# You should have received a copy of the GNU Affero General Public License along
 
20
# with `dmedia`.  If not, see <http://www.gnu.org/licenses/>.
 
21
 
 
22
"""
 
23
Store meta-data in desktop-couch.
 
24
"""
 
25
 
 
26
from os import path
 
27
import time
 
28
import socket
 
29
import platform
 
30
import gnomekeyring
 
31
from couchdb import ResourceNotFound, ResourceConflict
 
32
import desktopcouch
 
33
from desktopcouch.records.server import  CouchDatabase
 
34
from desktopcouch.records.record import  Record
 
35
from desktopcouch.local_files import DEFAULT_CONTEXT, Context
 
36
from .util import random_id
 
37
 
 
38
 
 
39
_sum = '_sum'
 
40
_count = '_count'
 
41
 
 
42
type_type = """
 
43
function(doc) {
 
44
    if (doc.type) {
 
45
        emit(doc.type, null);
 
46
    }
 
47
}
 
48
"""
 
49
 
 
50
batch_time = """
 
51
function(doc) {
 
52
    if (doc.type == 'dmedia/batch') {
 
53
        emit(doc.time, null);
 
54
    }
 
55
}
 
56
"""
 
57
 
 
58
import_time = """
 
59
function(doc) {
 
60
    if (doc.type == 'dmedia/import') {
 
61
        emit(doc.time, null);
 
62
    }
 
63
}
 
64
"""
 
65
 
 
66
file_bytes = """
 
67
function(doc) {
 
68
    if (doc.type == 'dmedia/file' && typeof(doc.bytes) == 'number') {
 
69
        emit(doc.bytes, doc.bytes);
 
70
    }
 
71
}
 
72
"""
 
73
 
 
74
file_ext = """
 
75
function(doc) {
 
76
    if (doc.type == 'dmedia/file') {
 
77
        emit(doc.ext, null);
 
78
    }
 
79
}
 
80
"""
 
81
 
 
82
file_content_type = """
 
83
function(doc) {
 
84
    if (doc.type == 'dmedia/file') {
 
85
        emit(doc.content_type, null);
 
86
    }
 
87
}
 
88
"""
 
89
 
 
90
file_mtime = """
 
91
function(doc) {
 
92
    if (doc.type == 'dmedia/file') {
 
93
        emit(doc.mtime, null);
 
94
    }
 
95
}
 
96
"""
 
97
 
 
98
file_tags = """
 
99
function(doc) {
 
100
    if (doc.type == 'dmedia/file' && doc.tags) {
 
101
        doc.tags.forEach(function(tag) {
 
102
            emit(tag, null);
 
103
        });
 
104
    }
 
105
}
 
106
"""
 
107
 
 
108
file_qid = """
 
109
function(doc) {
 
110
    if (doc.type == 'dmedia/file' && doc.qid) {
 
111
        emit(doc.qid, null);
 
112
    }
 
113
}
 
114
"""
 
115
 
 
116
file_import_id = """
 
117
function(doc) {
 
118
    if (doc.type == 'dmedia/file' && doc.import_id) {
 
119
        emit(doc.import_id, null);
 
120
    }
 
121
}
 
122
"""
 
123
 
 
124
 
 
125
def dc_context(couchdir):
 
126
    """
 
127
    Create a desktopcouch Context for testing purposes.
 
128
    """
 
129
    assert path.isdir(couchdir)
 
130
    return Context(
 
131
        path.join(couchdir, 'cache'),
 
132
        path.join(couchdir, 'data'),
 
133
        path.join(couchdir, 'config'),
 
134
    )
 
135
 
 
136
 
 
137
def build_design_doc(design, views):
 
138
    _id = '_design/' + design
 
139
    d = {}
 
140
    for (view, map_, reduce_) in views:
 
141
        d[view] = {'map': map_}
 
142
        if reduce_ is not None:
 
143
            d[view]['reduce'] = reduce_
 
144
    doc = {
 
145
        '_id': _id,
 
146
        'language': 'javascript',
 
147
        'views': d,
 
148
    }
 
149
    return (_id, doc)
 
150
 
 
151
 
 
152
def create_machine():
 
153
    return {
 
154
        '_id': '_local/machine',
 
155
        'machine_id': random_id(),
 
156
        'type': 'dmedia/machine',
 
157
        'time': time.time(),
 
158
        'hostname': socket.gethostname(),
 
159
        'distribution': platform.linux_distribution(),
 
160
    }
 
161
 
 
162
 
 
163
class MetaStore(object):
 
164
    designs = (
 
165
        ('type', (
 
166
            ('type', type_type, _count),
 
167
        )),
 
168
 
 
169
        ('batch', (
 
170
            ('time', batch_time, None),
 
171
        )),
 
172
 
 
173
        ('import', (
 
174
            ('time', import_time, None),
 
175
        )),
 
176
 
 
177
        ('file', (
 
178
            ('qid', file_qid, None),
 
179
            ('import_id', file_import_id, None),
 
180
            ('bytes', file_bytes, _sum),
 
181
            ('ext', file_ext, _count),
 
182
            ('content_type', file_content_type, _count),
 
183
            ('mtime', file_mtime, None),
 
184
            ('tags', file_tags, _count),
 
185
        )),
 
186
    )
 
187
 
 
188
    def __init__(self, dbname='dmedia', couchdir=None):
 
189
        self.dbname = dbname
 
190
        # FIXME: once lp:672481 is fixed, this wont be needed.  See:
 
191
        # https://bugs.launchpad.net/desktopcouch/+bug/672481
 
192
        self.ctx = (DEFAULT_CONTEXT if couchdir is None else dc_context(couchdir))
 
193
        # /FIXME
 
194
        self.desktop = CouchDatabase(self.dbname, create=True, ctx=self.ctx)
 
195
        self.server = self.desktop._server
 
196
        self.db = self.server[self.dbname]
 
197
        self.create_views()
 
198
        self._machine_id = None
 
199
 
 
200
    def get_basic_auth(self):
 
201
        data = gnomekeyring.find_items_sync(
 
202
            gnomekeyring.ITEM_GENERIC_SECRET,
 
203
            {'desktopcouch': 'basic'}
 
204
        )
 
205
        (user, password) = data[0].secret.split(':')
 
206
        return (user, password)
 
207
 
 
208
    def get_port(self):
 
209
        return desktopcouch.find_port()
 
210
 
 
211
    def get_uri(self):
 
212
        return 'http://localhost:%s' % self.get_port()
 
213
 
 
214
    def get_auth_uri(self):
 
215
        (user, password) = self.get_basic_auth()
 
216
        return 'http://%s:%s@localhost:%s' % (
 
217
            user, password, self.get_port()
 
218
        )
 
219
 
 
220
    def create_machine(self):
 
221
        try:
 
222
            loc = self.db['_local/machine']
 
223
        except ResourceNotFound:
 
224
            loc = self.sync(create_machine())
 
225
        doc = dict(loc)
 
226
        doc['_id'] = doc['machine_id']
 
227
        try:
 
228
            self.db[doc['_id']] = doc
 
229
        except ResourceConflict:
 
230
            pass
 
231
        return loc['machine_id']
 
232
 
 
233
    @property
 
234
    def machine_id(self):
 
235
        if self._machine_id is None:
 
236
            self._machine_id = self.create_machine()
 
237
        return self._machine_id
 
238
 
 
239
    def update(self, doc):
 
240
        """
 
241
        Create *doc* if it doesn't exists, update doc only if different.
 
242
        """
 
243
        _id = doc['_id']
 
244
        try:
 
245
            old = self.db[_id]
 
246
            doc['_rev'] = old['_rev']
 
247
            if old != doc:
 
248
                self.db[_id] = doc
 
249
        except ResourceNotFound:
 
250
            self.db[_id] = doc
 
251
 
 
252
    def sync(self, doc):
 
253
        _id = doc['_id']
 
254
        self.db[_id] = doc
 
255
        return self.db[_id]
 
256
 
 
257
    def create_views(self):
 
258
        for (name, views) in self.designs:
 
259
            (_id, doc) = build_design_doc(name, views)
 
260
            self.update(doc)
 
261
 
 
262
    def by_quickid(self, qid):
 
263
        for row in self.db.view('_design/file/_view/qid', key=qid):
 
264
            yield row.id
 
265
 
 
266
    def total_bytes(self):
 
267
        for row in self.db.view('_design/file/_view/bytes'):
 
268
            return row.value
 
269
        return 0
 
270
 
 
271
    def extensions(self):
 
272
        for row in self.db.view('_design/file/_view/ext', group=True):
 
273
            yield (row.key, row.value)