root / classifier / storage.py

Revision 162:ca1529c62df9, 12.1 kB (checked in by Tarek Ziad?? <tarek@…>, 9 months ago)

fixes

Line 
1# -*- coding: utf-8 -*-
2# Copyright (c) 2006 Nuxeo SAS <http://nuxeo.com>
3# Authors : Tarek Ziadé <tziade@nuxeo.com>
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License version 2 as published
6# by the Free Software Foundation.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
16# 02111-1307, USA.
17#
18# $Id: sql.py 46848 2006-06-29 18:57:28Z ogrisel $
19from sqlalchemy import *
20from settings import SQLURI
21
22_connector = create_engine(SQLURI)
23_metadata = BoundMetaData(_connector)
24
25lang = Table('classifier_lang', _metadata,
26             Column('iso', String(3), primary_key=True),
27             Column('user', String(40), primary_key=True))
28
29word = Table('classifier_word', _metadata,
30            Column('value', String(200), primary_key=True),
31            Column('lang_iso', String(3), ForeignKey('classifier_lang.iso')),
32            Column('count', Integer),
33            Column('user', String(40), primary_key=True)
34            )
35
36category = Table('classifier_category', _metadata,
37                 Column('name', String(50), primary_key=True),
38                 Column('description', String(300)),
39                 Column('user', String(40), primary_key=True))
40
41
42word_category = Table('classifier_word_category', _metadata,
43                 #Column('id', Integer, primary_key=True),
44                 Column('word_value', String(200),
45                        ForeignKey('classifier_word.value'), primary_key=True),
46                 Column('count', Integer),
47                 Column('category_name', String(50),
48                        ForeignKey('classifier_category.name'), primary_key=True),
49                 Column('user', String(40), primary_key=True))
50
51
52tables = (lang, word, category, word_category)
53
54for table in tables:
55    try:
56        table.create()
57    except exceptions.SQLError:
58        pass
59
60class SQLStorage(object):
61
62    def __init__(self, user):
63        self._user = user
64
65    #
66    # categories
67    #
68    def list_categories(self):
69        """ get categories list """
70        # XXX hardcoded here, just two cats
71        return [cat.name for cat in
72                category.select(category.c.user==self._user).execute()]
73
74    def add_category(self, name, description=''):
75        """ give the name of the filter """
76        if name in self.list_categories():
77            return
78        category.insert().execute(name=name, user=self._user,
79                                  description=description)
80
81    def del_category(self, name):
82        """ remove a category """
83        category.delete(and_(category.c.name==name,
84                             category.c.user==self._user)).execute()
85
86    #
87    # langs
88    #
89    def list_languages(self):
90        """ list available languages """
91        return [item.iso for item in
92                lang.select(lang.c.user==self._user).execute()]
93
94    def add_language(self, iso):
95        """ add a language """
96        lang.insert().execute(iso=iso, user=self._user)
97
98    def del_language(self, iso):
99        """ remove a language """
100        lines = lang.delete(and_(lang.c.iso==iso, lang.c.user==self._user))
101        lines.execute()
102
103    #
104    # words
105    #
106    def word_categories(self, the_word, language=None):
107        """list all categories for a given word in a given langugage"""
108        if language is not None:
109            the_word = word.select(and_(word.c.lang_iso==language,
110                                        word.c.value==the_word,
111                                        word.c.user==self._user)).execute()
112        else:
113            the_word = word.select(and_(word.c.user==self._user,
114                                        word.c.value==the_word)).execute()
115
116        the_word = the_word.fetchall()[0].value
117
118        sel = word_category.select(and_(word_category.c.word_value==the_word,
119                                        word.c.user==self._user))
120
121        # XXX see how to distinct
122        cats = []
123        for line in sel.execute():
124            if line.category_name not in cats:
125                cats.append(line.category_name)
126
127        return cats
128
129
130    def list_words(self, language=None, complete=False):
131        """ list all words, filtered by language if given """
132        if language is not None:
133            words = word.select(and_(word.c.lang_iso==language,
134                                     word.c.user==self._user)).execute()
135        else:
136            words = word.select(word.c.user==self._user).execute()
137
138        if not complete:
139            return ((word.value, word.lang_iso) for word in words)
140        else:
141            return ((word.value, self._reprWord(word))
142                    for word in words)
143
144    def add_word(self, the_word, language, categories=()):
145        """ add a word """
146        categories = _tuplify(categories)
147        #language = _tuplify(language)
148
149
150        # getting existing word
151        sel = word.select(and_(word.c.value==the_word,
152                               word.c.user==self._user))
153        selection = sel.execute().fetchone()
154        cat_insert = word_category.insert()
155
156        if selection is None:
157            # new word, let's add it
158            res = word.insert().execute(value=the_word, count=1,
159                                        user=self._user,
160                                        lang_iso=language)
161
162            for category in categories:
163                cat_insert.execute(word_value=the_word,
164                                   category_name=category, count=1,
165                                   user=self._user)
166        else:
167            # existing word, let's increment it
168            res = word.update(and_(word.c.value==the_word,
169                                   word.c.user==self._user))
170            res.execute(count=selection.count+1)
171
172            #sl = and_(word_category.c.word_value==the_word,
173            #         word_category.c.user==self._user)
174            #cat = word_category.select(sl)
175            #cat = cat.execute().fetchall()
176
177            #for old_cat in cat:
178            #    if old_cat.category_name not in categories:
179            #        name = old_cat.category_name
180            #        sl = and_(word_category.c.category_name==name,
181            #                  word_category.c.user==self._user,
182            #                  word_category.c.word_value==the_word)
183
184            #        word_category.delete(sl).execute()
185
186            existing_cats = self.list_categories()
187            for category in categories:
188                # let's check if the category exists in category
189                if category not in existing_cats:
190                    self.add_category(category)
191
192                sl = and_(word_category.c.category_name == category,
193                          word_category.c.user==self._user,
194                          word_category.c.word_value==the_word)
195                cat = word_category.select(sl)
196
197                cat = cat.execute().fetchone()
198                if cat is None:
199                    cat_insert.execute(word_value=the_word,
200                                       category_name=category,
201                                       count=1, user=self._user)
202
203                else:
204                    up = word_category.update(and_(word_category.c.user==cat.user,
205                                   word_category.c.word_value==cat.word_value,
206                                   word_category.c.category_name==cat.category_name))
207                    up.execute(count=cat.count+1)
208
209
210    def _reprWord(self, the_word):
211        # XXX ugly code, will do sql joins here later
212        word_value = the_word.value
213        selection = and_(word_category.c.word_value == word_value,
214                         word_category.c.user==self._user)
215
216        catwords = word_category.select(selection).execute()
217
218        word_sel =  and_(word.c.value == word_value,
219                         word.c.user==self._user)
220
221        langs = [the_word.lang_iso for the_word in
222                 word.select(word_sel).execute()]
223
224        cats = {}
225        for catword in catwords:
226            cats[catword.category_name] = catword.count
227
228        return tuple(langs), cats, int(the_word.count)
229
230    def get_word(self, the_word, language=None):
231        """ get word infos """
232        # TODO: handle language
233        sl = and_(word.c.word_label==the_word,
234                  word.c.user==self._user)
235
236        results = word.select(sl)
237
238        if results.count() == 0:
239            return None
240        return self._reprWord(results[0])
241
242    def del_word(self, the_word, categories=None, language=None):
243        """Remove a word"""
244        sl = and_(word.c.value==the_word, word.c.user==self._user)
245        the_word = word.select(sl).execute().fetchone()
246
247        if the_word is None:
248            return None
249
250        # picking up categorized words to work with
251        if categories is None:
252            sl = word_category.c.word_value == the_word.value
253            catwords = word_category.select(sl).execute(user=self._user)
254        else:
255            categories = _tuplify(categories)
256            sl =  word_category.c.word_value == the_word.value
257            sl2 =  word_category.c.category_name.in_(*categories)
258            sl = and_(sl, sl2)
259            catwords = word_category.select(sl).execute(user=self._user)
260
261        # remove categorized words
262        categories = []
263        for catword in catwords:
264            category_name = catword.category_name
265            if category_name not in categories:
266                categories.append(category_name)
267
268            sl = and_(word_category.c.category_name==category_name,
269                      word_category.c.user==self._user)
270
271            if catword.count == 1:
272                word_category.delete(sl).execute()
273            else:
274                rs = word_category.select(sl).execute().fetchone()
275                rs_count = rs.count
276                rs.close()
277                if rs is not None:
278                    sl2 = word_category.update(sl)
279                    sl2.execute(count=rs_count-1, user=self._user)
280
281        # remove empty categories
282        for category in categories:
283            sl = and_(word_category.c.category_name==category,
284                      word_category.c.user==self._user)
285
286            current_cat = word_category.select(sl).execute().fetchone()
287            if current_cat is not None:
288                if current_cat.count == 0:
289                    current_cat.close()
290                    word_category.delete(sl).execute()
291        #else:
292        #    # remove categories
293        #    sl = and_(word_category.c.word_value==the_word.value,
294        #              word_category.c.user==self._user)
295        #    word_category.delete(sl).execute()
296
297        # removing word if none use it
298        sl = and_(word.c.value==the_word.value, word.c.user==self._user)
299        if word.select(sl).execute().fetchone().count == 0:
300            word.delete(sl).execute()
301
302    def word_count(self, category=None, language=None):
303        if category is None:
304            if language is None:
305                sl = word.c.user == self._user
306                #return len(word.select(sl).execute().fetchall())
307                return word.select(sl).count().execute().fetchone()[0]
308            else:
309                sl = and_(word.c.user == self._user,
310                          word.c.lang_iso == language)
311                return word.select(sl).count().execute().fetchone()[0]
312                #return len(word.select(sl).execute().fetchall())
313        else:
314            categories = _tuplify(category)
315            in_ = word_category.c.category_name.in_(*categories)
316            sl = and_(in_, word_category.c.user == self._user)
317            return word_category.select(sl).count().execute().fetchone()[0]
318            #res = word_category.select(sl).execute()
319            #return len(res.fetchall())
320
321
322def _tuplify(element):
323    if not isinstance(element, tuple):
324        if isinstance(element, list):
325            return tuple(element)
326        else:
327            return (element,)
328    return element
Note: See TracBrowser for help on using the browser.