home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_1345 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  21.8 KB  |  801 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
  7. __docformat__ = 'restructuredtext en'
  8. import re
  9. import itertools
  10. import functools
  11. from itertools import repeat
  12. from datetime import timedelta
  13. from threading import Thread, RLock
  14. from Queue import Queue, Empty
  15. from PyQt4.Qt import QImage, Qt
  16. from calibre.utils.config import tweaks
  17. from calibre.utils.date import parse_date, now, UNDEFINED_DATE
  18. from calibre.utils.search_query_parser import SearchQueryParser
  19. from calibre.utils.pyparsing import ParseException
  20. from calibre.ebooks.metadata import title_sort
  21. from calibre import fit_image
  22.  
  23. class CoverCache(Thread):
  24.     
  25.     def __init__(self, db):
  26.         Thread.__init__(self)
  27.         self.daemon = True
  28.         self.db = db
  29.         self.load_queue = Queue()
  30.         self.keep_running = True
  31.         self.cache = { }
  32.         self.lock = RLock()
  33.         self.null_image = QImage()
  34.  
  35.     
  36.     def stop(self):
  37.         self.keep_running = False
  38.  
  39.     
  40.     def _image_for_id(self, id_):
  41.         img = self.db.cover(id_, index_is_id = True, as_image = True)
  42.         if img is None:
  43.             img = QImage()
  44.         
  45.         if not img.isNull():
  46.             (scaled, nwidth, nheight) = fit_image(img.width(), img.height(), 600, 800)
  47.             if scaled:
  48.                 img = img.scaled(nwidth, nheight, Qt.KeepAspectRatio, Qt.SmoothTransformation)
  49.             
  50.         
  51.         return img
  52.  
  53.     
  54.     def run(self):
  55.         while self.keep_running:
  56.             
  57.             try:
  58.                 id_ = self.load_queue.get(True, 1)
  59.             except Empty:
  60.                 continue
  61.  
  62.             
  63.             try:
  64.                 img = self._image_for_id(id_)
  65.             except:
  66.                 import traceback
  67.                 traceback.print_exc()
  68.                 continue
  69.  
  70.             self.lock.__enter__()
  71.             
  72.             try:
  73.                 self.cache[id_] = img
  74.             finally:
  75.                 pass
  76.  
  77.             continue
  78.             self.lock.__exit__
  79.  
  80.     
  81.     def set_cache(self, ids):
  82.         self.lock.__enter__()
  83.         
  84.         try:
  85.             already_loaded = set([])
  86.             for id in self.cache.keys():
  87.                 if id in ids:
  88.                     already_loaded.add(id)
  89.                     continue
  90.                 self.lock.__exit__
  91.                 self.cache.pop(id)
  92.         finally:
  93.             pass
  94.  
  95.         for id_ in set(ids) - already_loaded:
  96.             self.load_queue.put(id_)
  97.         
  98.  
  99.     
  100.     def cover(self, id_):
  101.         self.lock.__enter__()
  102.         
  103.         try:
  104.             return self.cache.get(id_, self.null_image)
  105.         finally:
  106.             pass
  107.  
  108.  
  109.     
  110.     def clear_cache(self):
  111.         self.lock.__enter__()
  112.         
  113.         try:
  114.             self.cache = { }
  115.         finally:
  116.             pass
  117.  
  118.  
  119.     
  120.     def refresh(self, ids):
  121.         self.lock.__enter__()
  122.         
  123.         try:
  124.             for id_ in ids:
  125.                 self.cache.pop(id_, None)
  126.                 self.load_queue.put(id_)
  127.         finally:
  128.             pass
  129.  
  130.  
  131.  
  132. CONTAINS_MATCH = 0
  133. EQUALS_MATCH = 1
  134. REGEXP_MATCH = 2
  135.  
  136. def _match(query, value, matchkind):
  137.     for t in value:
  138.         t = t.lower()
  139.         
  140.         try:
  141.             if not matchkind == EQUALS_MATCH or query == t:
  142.                 if (matchkind == REGEXP_MATCH or re.search(query, t, re.I) or matchkind == CONTAINS_MATCH) and query in t:
  143.                     return True
  144.         continue
  145.         except re.error:
  146.             continue
  147.         
  148.  
  149.     
  150.     return False
  151.  
  152.  
  153. class ResultCache(SearchQueryParser):
  154.     
  155.     def __init__(self, FIELD_MAP, field_metadata):
  156.         self.FIELD_MAP = FIELD_MAP
  157.         self._map = self._map_filtered = self._data = []
  158.         self.first_sort = True
  159.         self.search_restriction = ''
  160.         self.field_metadata = field_metadata
  161.         self.all_search_locations = field_metadata.get_search_terms()
  162.         SearchQueryParser.__init__(self, self.all_search_locations)
  163.         self.build_date_relop_dict()
  164.         self.build_numeric_relop_dict()
  165.  
  166.     
  167.     def __getitem__(self, row):
  168.         return self._data[self._map_filtered[row]]
  169.  
  170.     
  171.     def __len__(self):
  172.         return len(self._map_filtered)
  173.  
  174.     
  175.     def __iter__(self):
  176.         for id in self._map_filtered:
  177.             yield self._data[id]
  178.         
  179.  
  180.     
  181.     def iterall(self):
  182.         for x in self._data:
  183.             if x is not None:
  184.                 yield x
  185.                 continue
  186.         
  187.  
  188.     
  189.     def iterallids(self):
  190.         idx = self.FIELD_MAP['id']
  191.         for x in self.iterall():
  192.             yield x[idx]
  193.         
  194.  
  195.     
  196.     def universal_set(self):
  197.         return [](_[1])
  198.  
  199.     
  200.     def build_date_relop_dict(self):
  201.         
  202.         def relop_eq(db, query, field_count):
  203.             return False
  204.  
  205.         
  206.         def relop_gt(db, query, field_count):
  207.             if db.year > query.year:
  208.                 return True
  209.             if field_count > 1 and db.year == query.year:
  210.                 if db.month > query.month:
  211.                     return True
  212.                 if field_count == 3 and db.month == query.month:
  213.                     pass
  214.                 return db.day > query.day
  215.             return False
  216.  
  217.         
  218.         def relop_lt(db, query, field_count):
  219.             if db.year < query.year:
  220.                 return True
  221.             if field_count > 1 and db.year == query.year:
  222.                 if db.month < query.month:
  223.                     return True
  224.                 if field_count == 3 and db.month == query.month:
  225.                     pass
  226.                 return db.day < query.day
  227.             return False
  228.  
  229.         
  230.         def relop_ne(db, query, field_count):
  231.             return not relop_eq(db, query, field_count)
  232.  
  233.         
  234.         def relop_ge(db, query, field_count):
  235.             return not relop_lt(db, query, field_count)
  236.  
  237.         
  238.         def relop_le(db, query, field_count):
  239.             return not relop_gt(db, query, field_count)
  240.  
  241.         self.date_search_relops = {
  242.             '=': [
  243.                 1,
  244.                 relop_eq],
  245.             '>': [
  246.                 1,
  247.                 relop_gt],
  248.             '<': [
  249.                 1,
  250.                 relop_lt],
  251.             '!=': [
  252.                 2,
  253.                 relop_ne],
  254.             '>=': [
  255.                 2,
  256.                 relop_ge],
  257.             '<=': [
  258.                 2,
  259.                 relop_le] }
  260.  
  261.     
  262.     def get_dates_matches(self, location, query):
  263.         matches = set([])
  264.         if len(query) < 2:
  265.             return matches
  266.         if location == 'date':
  267.             location = 'timestamp'
  268.         
  269.         loc = self.field_metadata[location]['rec_index']
  270.         if query == 'false':
  271.             for item in self._data:
  272.                 if item is None:
  273.                     continue
  274.                 
  275.                 if item[loc] is None or item[loc] <= UNDEFINED_DATE:
  276.                     matches.add(item[0])
  277.                     continue
  278.             
  279.             return matches
  280.         if query == 'true':
  281.             for item in self._data:
  282.                 if item is None:
  283.                     continue
  284.                 
  285.                 if item[loc] is not None and item[loc] > UNDEFINED_DATE:
  286.                     matches.add(item[0])
  287.                     continue
  288.             
  289.             return matches
  290.         relop = None
  291.         for k in self.date_search_relops.keys():
  292.             if query.startswith(k):
  293.                 (p, relop) = self.date_search_relops[k]
  294.                 query = query[p:]
  295.                 continue
  296.             query == 'true'
  297.         
  298.         if relop is None:
  299.             (p, relop) = self.date_search_relops['=']
  300.         
  301.         if query == _('today'):
  302.             qd = now()
  303.             field_count = 3
  304.         elif query == _('yesterday'):
  305.             qd = now() - timedelta(1)
  306.             field_count = 3
  307.         elif query == _('thismonth'):
  308.             qd = now()
  309.             field_count = 2
  310.         elif query.endswith(_('daysago')):
  311.             num = query[0:-len(_('daysago'))]
  312.             
  313.             try:
  314.                 qd = now() - timedelta(int(num))
  315.             except:
  316.                 raise ParseException(query, len(query), 'Number conversion error', self)
  317.  
  318.             field_count = 3
  319.         else:
  320.             
  321.             try:
  322.                 qd = parse_date(query)
  323.             except:
  324.                 raise ParseException(query, len(query), 'Date conversion error', self)
  325.  
  326.             if '-' in query:
  327.                 field_count = query.count('-') + 1
  328.             else:
  329.                 field_count = query.count('/') + 1
  330.         for item in self._data:
  331.             if item is None or item[loc] is None:
  332.                 continue
  333.             
  334.             if relop(item[loc], qd, field_count):
  335.                 matches.add(item[0])
  336.                 continue
  337.         
  338.         return matches
  339.  
  340.     
  341.     def build_numeric_relop_dict(self):
  342.         self.numeric_search_relops = {
  343.             '=': [
  344.                 1,
  345.                 (lambda r, q: r == q)],
  346.             '>': [
  347.                 1,
  348.                 (lambda r, q: r > q)],
  349.             '<': [
  350.                 1,
  351.                 (lambda r, q: r < q)],
  352.             '!=': [
  353.                 2,
  354.                 (lambda r, q: r != q)],
  355.             '>=': [
  356.                 2,
  357.                 (lambda r, q: r >= q)],
  358.             '<=': [
  359.                 2,
  360.                 (lambda r, q: r <= q)] }
  361.  
  362.     
  363.     def get_numeric_matches(self, location, query):
  364.         matches = set([])
  365.         if len(query) == 0:
  366.             return matches
  367.         if query == 'false':
  368.             query = '0'
  369.         elif query == 'true':
  370.             query = '!=0'
  371.         
  372.         relop = None
  373.         for k in self.numeric_search_relops.keys():
  374.             if query.startswith(k):
  375.                 (p, relop) = self.numeric_search_relops[k]
  376.                 query = query[p:]
  377.                 continue
  378.         
  379.         if relop is None:
  380.             (p, relop) = self.numeric_search_relops['=']
  381.         
  382.         loc = self.field_metadata[location]['rec_index']
  383.         dt = self.field_metadata[location]['datatype']
  384.         if dt == 'int':
  385.             
  386.             cast = lambda x: int(x)
  387.             
  388.             adjust = lambda x: x
  389.         elif dt == 'rating':
  390.             
  391.             cast = lambda x: int(x)
  392.             
  393.             adjust = lambda x: x / 2
  394.         elif dt == 'float':
  395.             
  396.             cast = lambda x: float(x)
  397.             
  398.             adjust = lambda x: x
  399.         
  400.         if len(query) > 1:
  401.             mult = query[-1:].lower()
  402.             mult = {
  403.                 'k': 1024,
  404.                 'm': 1.04858e+06,
  405.                 'g': 1.07374e+09 }.get(mult, 1)
  406.             if mult != 1:
  407.                 query = query[:-1]
  408.             
  409.         else:
  410.             mult = 1
  411.         
  412.         try:
  413.             q = cast(query) * mult
  414.         except:
  415.             return matches
  416.  
  417.         for item in self._data:
  418.             if item is None:
  419.                 continue
  420.             
  421.             if not item[loc]:
  422.                 i = 0
  423.             else:
  424.                 i = adjust(item[loc])
  425.             if relop(i, q):
  426.                 matches.add(item[0])
  427.                 continue
  428.         
  429.         return matches
  430.  
  431.     
  432.     def get_matches(self, location, query):
  433.         matches = set([])
  434.         if query and query.strip():
  435.             location = self.field_metadata.search_term_to_key(location.lower().strip())
  436.             if location in self.field_metadata and self.field_metadata[location]['datatype'] == 'datetime':
  437.                 return self.get_dates_matches(location, query.lower())
  438.             if location in self.field_metadata and self.field_metadata[location]['datatype'] in ('rating', 'int', 'float'):
  439.                 return self.get_numeric_matches(location, query.lower())
  440.             matchkind = CONTAINS_MATCH
  441.             if matchkind != REGEXP_MATCH:
  442.                 query = query.lower()
  443.             
  444.             if not isinstance(query, unicode):
  445.                 query = query.decode('utf-8')
  446.             
  447.             db_col = { }
  448.             exclude_fields = []
  449.             col_datatype = []
  450.             is_multiple_cols = { }
  451.             for x in range(len(self.FIELD_MAP)):
  452.                 col_datatype.append('')
  453.             
  454.             for x in self.field_metadata:
  455.                 if len(self.field_metadata[x]['search_terms']):
  456.                     db_col[x] = self.field_metadata[x]['rec_index']
  457.                     if self.field_metadata[x]['datatype'] not in ('text', 'comments', 'series'):
  458.                         exclude_fields.append(db_col[x])
  459.                     
  460.                     col_datatype[db_col[x]] = self.field_metadata[x]['datatype']
  461.                     is_multiple_cols[db_col[x]] = self.field_metadata[x]['is_multiple']
  462.                     continue
  463.             
  464.             
  465.             try:
  466.                 rating_query = int(query) * 2
  467.             except:
  468.                 rating_query = None
  469.  
  470.             location = None if location != 'all' else list(db_col.keys())
  471.             for i, loc in enumerate(location):
  472.                 location[i] = db_col[loc]
  473.             
  474.             bools_are_tristate = tweaks['bool_custom_columns_are_tristate'] == 'yes'
  475.             for loc in location:
  476.                 if loc == db_col['authors']:
  477.                     q = query.replace(',', '|')
  478.                 else:
  479.                     q = query
  480.                 for item in self._data:
  481.                     if item is None:
  482.                         continue
  483.                     
  484.                     if col_datatype[loc] == 'bool':
  485.                         v = item[loc]
  486.                         if not bools_are_tristate:
  487.                             if v is None or not v:
  488.                                 if q in [
  489.                                     _('no'),
  490.                                     _('unchecked'),
  491.                                     'false']:
  492.                                     matches.add(item[0])
  493.                                 
  494.                             elif q in [
  495.                                 _('yes'),
  496.                                 _('checked'),
  497.                                 'true']:
  498.                                 matches.add(item[0])
  499.                             
  500.                         not v
  501.                         if v is None:
  502.                             if q in [
  503.                                 _('empty'),
  504.                                 _('blank'),
  505.                                 'false']:
  506.                                 matches.add(item[0])
  507.                             
  508.                         q in [
  509.                             _('empty'),
  510.                             _('blank'),
  511.                             'false']
  512.                         if not v:
  513.                             if q in [
  514.                                 _('no'),
  515.                                 _('unchecked'),
  516.                                 'true']:
  517.                                 matches.add(item[0])
  518.                             
  519.                         q in [
  520.                             _('no'),
  521.                             _('unchecked'),
  522.                             'true']
  523.                         if q in [
  524.                             _('yes'),
  525.                             _('checked'),
  526.                             'true']:
  527.                             matches.add(item[0])
  528.                             continue
  529.                         continue
  530.                     
  531.                     if not item[loc]:
  532.                         if q == 'false':
  533.                             matches.add(item[0])
  534.                             continue
  535.                         continue
  536.                     
  537.                     if q == 'false':
  538.                         continue
  539.                     
  540.                     if q == 'true':
  541.                         if isinstance(item[loc], basestring):
  542.                             if item[loc].strip() == '':
  543.                                 continue
  544.                             
  545.                         
  546.                         matches.add(item[0])
  547.                         continue
  548.                     
  549.                     if col_datatype[loc] == 'rating':
  550.                         if rating_query and rating_query == int(item[loc]):
  551.                             matches.add(item[0])
  552.                             continue
  553.                         continue
  554.                     
  555.                     
  556.                     try:
  557.                         if col_datatype[loc] == 'float':
  558.                             if float(query) == item[loc]:
  559.                                 matches.add(item[0])
  560.                             
  561.                             continue
  562.                         
  563.                         if col_datatype[loc] == 'int':
  564.                             if int(query) == item[loc]:
  565.                                 matches.add(item[0])
  566.                             
  567.                             continue
  568.                     except:
  569.                         continue
  570.  
  571.                     if loc not in exclude_fields:
  572.                         if is_multiple_cols[loc] is not None:
  573.                             vals = item[loc].split(is_multiple_cols[loc])
  574.                         else:
  575.                             vals = [
  576.                                 item[loc]]
  577.                         if _match(q, vals, matchkind):
  578.                             matches.add(item[0])
  579.                             continue
  580.                         
  581.                     _match(q, vals, matchkind)
  582.                 
  583.             
  584.         
  585.         return matches
  586.  
  587.     
  588.     def remove(self, id):
  589.         self._data[id] = None
  590.         if id in self._map:
  591.             self._map.remove(id)
  592.         
  593.         if id in self._map_filtered:
  594.             self._map_filtered.remove(id)
  595.         
  596.  
  597.     
  598.     def set(self, row, col, val, row_is_id = False):
  599.         id = None if row_is_id else self._map_filtered[row]
  600.         self._data[id][col] = val
  601.  
  602.     
  603.     def get(self, row, col, row_is_id = False):
  604.         id = None if row_is_id else self._map_filtered[row]
  605.         return self._data[id][col]
  606.  
  607.     
  608.     def index(self, id, cache = False):
  609.         x = None if cache else self._map_filtered
  610.         return x.index(id)
  611.  
  612.     
  613.     def row(self, id):
  614.         return self.index(id)
  615.  
  616.     
  617.     def has_id(self, id):
  618.         
  619.         try:
  620.             return self._data[id] is not None
  621.         except IndexError:
  622.             pass
  623.  
  624.         return False
  625.  
  626.     
  627.     def refresh_ids(self, db, ids):
  628.         for id in ids:
  629.             
  630.             try:
  631.                 self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
  632.                 self._data[id].append(db.has_cover(id, index_is_id = True))
  633.                 self._data[id].append(db.book_on_device_string(id))
  634.             continue
  635.             except IndexError:
  636.                 return None
  637.             
  638.  
  639.         
  640.         
  641.         try:
  642.             return map(self.row, ids)
  643.         except ValueError:
  644.             None<EXCEPTION MATCH>IndexError
  645.             None<EXCEPTION MATCH>IndexError
  646.         except:
  647.             None<EXCEPTION MATCH>IndexError
  648.  
  649.  
  650.     
  651.     def books_added(self, ids, db):
  652.         if not ids:
  653.             return None
  654.         self._data.extend(repeat(None, (max(ids) - len(self._data)) + 2))
  655.         for id in ids:
  656.             self._data[id] = db.conn.get('SELECT * from meta2 WHERE id=?', (id,))[0]
  657.             self._data[id].append(db.has_cover(id, index_is_id = True))
  658.             self._data[id].append(db.book_on_device_string(id))
  659.         
  660.         self._map[0:0] = ids
  661.         self._map_filtered[0:0] = ids
  662.  
  663.     
  664.     def books_deleted(self, ids):
  665.         for id in ids:
  666.             self._data[id] = None
  667.             if id in self._map:
  668.                 self._map.remove(id)
  669.             
  670.             if id in self._map_filtered:
  671.                 self._map_filtered.remove(id)
  672.                 continue
  673.         
  674.  
  675.     
  676.     def count(self):
  677.         return len(self._map)
  678.  
  679.     
  680.     def refresh_ondevice(self, db):
  681.         ondevice_col = self.FIELD_MAP['ondevice']
  682.         for item in self._data:
  683.             if item is not None:
  684.                 item[ondevice_col] = db.book_on_device_string(item[0])
  685.                 continue
  686.         
  687.  
  688.     
  689.     def refresh(self, db, field = None, ascending = True):
  690.         temp = db.conn.get('SELECT * FROM meta2')
  691.         self._data = None if temp else []
  692.         for r in temp:
  693.             self._data[r[0]] = r
  694.         
  695.         for item in self._data:
  696.             if item is not None:
  697.                 item.append(db.has_cover(item[0], index_is_id = True))
  698.                 item.append(db.book_on_device_string(item[0]))
  699.                 continue
  700.         
  701.         self._map = _[1]
  702.         self._map_filtered = list(self._map)
  703.  
  704.     
  705.     def seriescmp(self, sidx, siidx, x, y, library_order = None):
  706.         
  707.         try:
  708.             if library_order:
  709.                 ans = cmp(title_sort(self._data[x][sidx].lower()), title_sort(self._data[y][sidx].lower()))
  710.             else:
  711.                 ans = cmp(self._data[x][sidx].lower(), self._data[y][sidx].lower())
  712.         except AttributeError:
  713.             ans = cmp(self._data[x][sidx], self._data[y][sidx])
  714.  
  715.         if ans != 0:
  716.             return ans
  717.         return cmp(self._data[x][siidx], self._data[y][siidx])
  718.  
  719.     
  720.     def cmp(self, loc, x, y, asstr = True, subsort = False):
  721.         
  722.         try:
  723.             ans = None if asstr else cmp(self._data[x][loc], self._data[y][loc])
  724.         except AttributeError:
  725.             ans = cmp(self._data[x][loc], self._data[y][loc])
  726.         except TypeError:
  727.             x = self._data[x][loc]
  728.             if x is None:
  729.                 x = UNDEFINED_DATE
  730.             
  731.             y = self._data[y][loc]
  732.             if y is None:
  733.                 y = UNDEFINED_DATE
  734.             
  735.             return cmp(x, y)
  736.  
  737.         if subsort and ans == 0:
  738.             return cmp(self._data[x][11].lower(), self._data[y][11].lower())
  739.         return ans
  740.  
  741.     
  742.     def sort(self, field, ascending, subsort = False):
  743.         field = field.lower().strip()
  744.         if field in ('author', 'tag', 'comment'):
  745.             field += 's'
  746.         
  747.         if field == 'date':
  748.             field = 'timestamp'
  749.         elif field == 'title':
  750.             field = 'sort'
  751.         elif field == 'authors':
  752.             field = 'author_sort'
  753.         
  754.         as_string = field not in ('size', 'rating', 'timestamp')
  755.         if self.first_sort:
  756.             subsort = True
  757.             self.first_sort = False
  758.         
  759.         if self.field_metadata[field]['is_custom']:
  760.             if self.field_metadata[field]['datatype'] == 'series':
  761.                 fcmp = functools.partial(self.seriescmp, self.field_metadata[field]['rec_index'], self.field_metadata.cc_series_index_column_for(field), library_order = tweaks['title_series_sorting'] == 'library_order')
  762.             else:
  763.                 as_string = self.field_metadata[field]['datatype'] in ('comments', 'text')
  764.                 field = self.field_metadata[field]['colnum']
  765.                 fcmp = functools.partial(self.cmp, self.FIELD_MAP[field], subsort = subsort, asstr = as_string)
  766.         elif field == 'series':
  767.             fcmp = functools.partial(self.seriescmp, self.FIELD_MAP['series'], self.FIELD_MAP['series_index'], library_order = tweaks['title_series_sorting'] == 'library_order')
  768.         else:
  769.             fcmp = functools.partial(self.cmp, self.FIELD_MAP[field], subsort = subsort, asstr = as_string)
  770.         self._map.sort(cmp = fcmp, reverse = not ascending)
  771.         self._map_filtered = _[1]
  772.  
  773.     
  774.     def search(self, query, return_matches = False, ignore_search_restriction = False):
  775.         q = ''
  776.         if not query or not query.strip():
  777.             if not ignore_search_restriction:
  778.                 q = self.search_restriction
  779.             
  780.         else:
  781.             q = query
  782.             if not ignore_search_restriction and self.search_restriction:
  783.                 q = u'%s (%s)' % (self.search_restriction, query)
  784.             
  785.         if not q:
  786.             if return_matches:
  787.                 return list(self._map)
  788.             self._map_filtered = list(self._map)
  789.             return None
  790.         matches = sorted(self.parse(q))
  791.         ans = _[1]
  792.         if return_matches:
  793.             return ans
  794.         self._map_filtered = ans
  795.  
  796.     
  797.     def set_search_restriction(self, s):
  798.         self.search_restriction = s
  799.  
  800.  
  801.