5 from sqlobject.sqlbuilder import CONCAT
7 from m_lib.defenc import default_encoding
8 from m_librarian.db import Author, Book, Extension, Language, open_db
9 from m_librarian.search import mk_search_conditions, \
10 search_authors, search_books, \
11 search_extensions, search_genres, search_languages
13 from m_librarian.translations import translations
14 _ = translations.ugettext
17 def _guess_case_sensitivity(values):
18 for value in values.values():
19 if not value.islower():
24 def _search_authors(case_sensitive, search_type, args):
25 if (args.surname or args.name or args.misc_name) and args.fullname:
27 "Cannot search by names and full name at the same time\n")
28 main_parser.print_help()
32 for column in 'surname', 'name', 'misc_name':
33 value = getattr(args, column)
35 values[column] = unicode(value, default_encoding)
40 CONCAT(Author.q.surname, ' ', Author.q.name, ' ',
42 unicode(value, default_encoding)
44 if case_sensitive is None:
45 case_sensitive = _guess_case_sensitivity(values)
46 for author in search_authors(search_type, case_sensitive, values,
48 orderBy=('surname', 'name', 'misc_name')):
49 names = filter(None, (author.surname, author.name, author.misc_name))
50 fullname = u' '.join(names)
51 print fullname.encode(default_encoding), \
52 (u"(%s: %d)" % (_('books'), author.count)).encode(default_encoding)
55 def _search_books(case_sensitive, search_type, args):
58 for column in 'title', 'series', 'archive', 'file':
59 value = getattr(args, column)
61 values[column] = unicode(value, default_encoding)
62 if case_sensitive is None:
63 test_values = values.copy()
64 for column in 'ext', 'lang':
65 value = getattr(args, column)
67 test_values[column] = unicode(value, default_encoding)
68 case_sensitive = _guess_case_sensitivity(test_values)
70 join_expressions.append(Book.j.extension)
71 conditions = mk_search_conditions(
72 Extension, search_type, case_sensitive,
74 join_expressions.extend(conditions)
76 join_expressions.append(Book.j.language)
77 conditions = mk_search_conditions(
78 Language, search_type, case_sensitive,
80 join_expressions.extend(conditions)
81 for book in search_books(search_type, case_sensitive, values,
83 orderBy=('series', 'ser_no', 'title')):
84 print book.title.encode(default_encoding)
86 print " ", _("Author(s)"), ":",
87 for author in book.authors:
89 (author.surname, author.name, author.misc_name))
90 fullname = u' '.join(names)
91 print fullname.encode(default_encoding),
93 print " ", _("Genre(s)"), ":",
94 for genre in book.genres:
95 print (genre.title or genre.name).encode(default_encoding),
98 print " ", _("Series"), ":",
99 print book.series.encode(default_encoding), \
102 if args.details >= 2:
103 print " ", _("Date"), ":", book.date
104 print " ", _("Language"), ":", book.language.name
106 if args.details >= 3:
107 print " ", _("Archive"), ":", book.archive
108 print " ", _("File"), ":", book.file
109 print " ", _("Extension"), ":", book.extension.name
110 print " ", _("Size"), ":", book.size, _("bytes")
111 print " ", _("Deleted"), ":", _(str(book.deleted))
114 def _search_extensions(case_sensitive, search_type, args):
116 values = {'name': args.name}
117 if case_sensitive is None:
118 case_sensitive = _guess_case_sensitivity(values)
121 for ext in search_extensions(search_type, case_sensitive, values,
123 print ext.name.encode(default_encoding), \
124 (u"(%s: %d)" % (_('books'), ext.count)).encode(default_encoding)
127 def _search_genres(case_sensitive, search_type, args):
129 for column in 'name', 'title':
130 value = getattr(args, column)
132 values[column] = unicode(value, default_encoding)
133 if case_sensitive is None:
134 case_sensitive = _guess_case_sensitivity(values)
135 for genre in search_genres(search_type, case_sensitive, values,
137 names = filter(None, (genre.name, genre.title))
138 fullname = u' '.join(names)
139 print fullname.encode(default_encoding), \
140 (u"(%s: %d)" % (_('books'), genre.count)).encode(default_encoding)
143 def _search_languages(case_sensitive, search_type, args):
145 values = {'name': args.name}
146 if case_sensitive is None:
147 case_sensitive = _guess_case_sensitivity(values)
150 for lang in search_languages(search_type, case_sensitive, values,
152 print lang.name.encode(default_encoding), \
153 (u"(%s: %d)" % (_('books'), lang.count)).encode(default_encoding)
156 if __name__ == '__main__':
157 main_parser = argparse.ArgumentParser(description='Search')
158 main_parser.add_argument('-i', '--ignore-case', action='store_true',
160 '(default is to guess)')
161 main_parser.add_argument('-I', '--case-sensitive', action='store_true',
162 help='don\'t ignore case')
163 main_parser.add_argument('-t', '--start', action='store_true',
164 help='search substring at the start '
165 '(this is the default)')
166 main_parser.add_argument('-s', '--substring', action='store_true',
167 help='search substring anywhere')
168 main_parser.add_argument('-f', '--full', action='store_true',
169 help='match the entire string')
170 subparsers = main_parser.add_subparsers(help='Commands')
172 parser = subparsers.add_parser('authors', help='Search authors')
173 parser.add_argument('-s', '--surname', help='search by surname')
174 parser.add_argument('-n', '--name', help='search by name')
175 parser.add_argument('-m', '--misc-name', help='search by misc. name')
176 parser.add_argument('fullname', nargs='?', help='search by full name')
177 parser.set_defaults(func=_search_authors)
179 parser = subparsers.add_parser('books', help='Search books')
180 parser.add_argument('-t', '--title', help='search by title')
181 parser.add_argument('-s', '--series', help='search by series')
182 parser.add_argument('-a', '--archive', help='search by archive (zip file)')
183 parser.add_argument('-f', '--file', help='search by file name')
184 parser.add_argument('-d', '--details', action='count',
185 help='output more details about books; '
186 'repeat for even more details')
187 parser.add_argument('-e', '--ext', help='search by file extension')
188 parser.add_argument('-l', '--lang', help='search by language')
189 parser.set_defaults(func=_search_books)
191 parser = subparsers.add_parser('ext', help='Search extensions')
192 parser.add_argument('name', nargs='?', help='search by name')
193 parser.set_defaults(func=_search_extensions)
195 parser = subparsers.add_parser('genres', help='Search genres')
196 parser.add_argument('-n', '--name', help='search by name')
197 parser.add_argument('-t', '--title', help='search by title')
198 parser.set_defaults(func=_search_genres)
200 parser = subparsers.add_parser('lang', help='Search languages')
201 parser.add_argument('name', nargs='?', help='search by name')
202 parser.set_defaults(func=_search_languages)
204 args = main_parser.parse_args()
206 if args.case_sensitive:
209 "Cannot search case sensitive and case insensitive "
210 "at the same time\n")
211 main_parser.print_help()
214 case_sensitive = True
215 elif args.ignore_case:
216 case_sensitive = False
218 case_sensitive = None # guess case sensitivity
220 if int(args.start) + int(args.substring) + int(args.full) > 1:
222 "Cannot search case sensitive and case insensitive "
223 "at the same time\n")
224 main_parser.print_help()
227 search_type = 'start'
229 search_type = 'substring'
233 search_type = 'start'
236 args.func(case_sensitive, search_type, args)