From 9686bc5fd9b73a6f43a7753afd172a5fe5b9501a Mon Sep 17 00:00:00 2001 From: Oleg Broytman Date: Thu, 19 May 2016 20:29:41 +0300 Subject: [PATCH] Split --search-type into separate -t/-s/-f options --- docs-ru/command_line.rst | 25 +++++++++-------- docs/command_line.rst | 26 +++++++++-------- m_librarian/search.py | 10 +++---- scripts/ml-search.py | 60 +++++++++++++++++++++++++--------------- 4 files changed, 70 insertions(+), 51 deletions(-) diff --git a/docs-ru/command_line.rst b/docs-ru/command_line.rst index 3d87fd9..90990cf 100644 --- a/docs-ru/command_line.rst +++ b/docs-ru/command_line.rst @@ -32,7 +32,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t {exact,start,substring}] ... + ml-search.py [-i] [-I] [-t] [-s] [-f] ... Программа выполняет поиск по базе данных и показывает список результатов. В настоящее время может искать только в списке авторов. @@ -41,9 +41,10 @@ ml-search.py -i, --ignore-case независимо от регистра (по умолчанию: угадать) -I, --case-sensitive с учётом регистра - -t, --search-type {exact,start,substring} - тип поиска: точный, подстрока в начале (это тип по умолчанию), - подстрока в любом месте. + -t, --start тип поиска: подстрока в начале строки + (это тип поиска по умолчанию) + -s, --substring тип поиска: подстрока в любом месте + -f, --full тип поиска: полное совпадение всей строки Опции ``-i/-I`` не могут использованы одновременно, поскольку означают противоположные команды. В случае, если ни одна из них не использована, @@ -52,14 +53,14 @@ ml-search.py параметров есть параметры в ВЕРХНЕМ или Смешанном регистре - поиск будет с учётом регистра. -Опция ``-t/--search-type`` определяет тип поиска. Возможные значения: +Опции ``-t/-s/-f`` определяют тип поиска. Возможные значения: -* exact - поиск на точное совпадение; поиск "друг" найдёт только "друг", - но не "другой"; * start - поиск подстроки в начале поля; поиск "друг" найдёт "друг" и "другой", но не "подруга"; это тип по умолчанию; * substring - поиск подстроки в любом месте; поиск "друг" найдёт "друг", "другой" и "подруга". +* full - поиск на точное совпадение всей строки; поиск "друг" найдёт + только "друг", но не "другой"; Поиск авторов @@ -67,7 +68,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t ...] author [-s surname] [-n name] [-m misc-name] [fullname] + ml-search.py [-i/-I] [-t/-s/-f] author [-s surname] [-n name] [-m misc-name] [fullname] Искать и печатать список авторов по фамилии, имени, доп. имени (обычно отчеству) или полному имени. @@ -98,7 +99,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t ...] books [-t title] [-s series] [-a archive] [-f file] [-d] + ml-search.py [-i/-I] [-t/-s/-f] books [-t title] [-s series] [-a archive] [-f file] [-d] Искать и печатать список книг по заголовку, серии, архиву, имени файла. @@ -120,7 +121,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t ...] ext [name] + ml-search.py [-i/-I] [-t/-s/-f] ext [name] Искать и печатать список расширений имён файлов по имени. @@ -129,7 +130,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t ...] genres [-n name] [-t title] + ml-search.py [-i/-I] [-t/-s/-f] genres [-n name] [-t title] Искать и печатать список жанров по имени и заголовку. @@ -143,7 +144,7 @@ ml-search.py Использование:: - ml-search.py [-i] [-I] [-t ...] lang [name] + ml-search.py [-i/-I] [-t/-s/-f] lang [name] Искать и печатать список языков по имени. diff --git a/docs/command_line.rst b/docs/command_line.rst index 0e63d97..42bae7e 100644 --- a/docs/command_line.rst +++ b/docs/command_line.rst @@ -31,7 +31,7 @@ ml-search.py Usage:: - ml-search.py [-i] [-I] [-t {exact,start,substring}] ... + ml-search.py [-i] [-I] [-t] [-s] [-f] ... Search through the database and display results. Currently can only search authors by name. @@ -40,9 +40,10 @@ Global options:: -i, --ignore-case ignore case (default is to guess) -I, --case-sensitive don't ignore case - -t, --search-type {exact,start,substring} - search type: exact match, substring at the start (this is the default), - substring anywhere. + -t, --start search type: substring at the start + (this is the default) + -s, --substring search type: substring anywhere + -f, --full search type: match the full string Options ``-i/-I`` cannot be used together as they are the opposite. In case none of them are used the program guesses case-sensitivity by @@ -50,15 +51,16 @@ looking at the arguments. If all arguments are lowercase the program performs case-insensitive search. If there are UPPERCASE or MixedCase arguments the program performs case-sensitive search. -Option ``-t/--search-type`` defines the search type. Search types are: +Options ``-t/-s/-f`` define the search type. Search types are: -* exact - search for exact match; i.e. searching for "duck" returns - results for "duck" but not for "duckling"; * start - search for substring at the start of the search field; for example searching for "duck" returns results for "duck" and "duckling" but not for "McDuck"; this is the default search type. * substring - search for any substring; "duck" => "duck", "duckling", "McDuck" (except for case-sensitive search, of course). +* full - search for exact match, compare the entire strings; + i.e. searching for "duck" returns results for "duck" but not for + "duckling"; Author search @@ -66,7 +68,7 @@ Author search Usage:: - ml-search.py [-i] [-I] [-t ...] author [-s surname] [-n name] [-m misc-name] [fullname] + ml-search.py [-i/-I] [-t/-s/-f] author [-s surname] [-n name] [-m misc-name] [fullname] Search and print a list of authors by surname/name/misc name/full name. @@ -96,7 +98,7 @@ Book search Usage:: - ml-search.py [-i] [-I] [-t ...] books [-t title] [-s series] [-a archive] [-f file] [-d] + ml-search.py [-i/-I] [-t/-s/-f] books [-t title] [-s series] [-a archive] [-f file] [-d] Search and print a list of books by title, series, archive or file name. @@ -117,7 +119,7 @@ Extension search Usage:: - ml-search.py [-i] [-I] [-t ...] ext [name] + ml-search.py [-i/-I] [-t/-s/-f] ext [name] Search and print a list of extensions by name. @@ -126,7 +128,7 @@ Genres search Usage:: - ml-search.py [-i] [-I] [-t ...] genres [-n name] [-t title] + ml-search.py [-i/-I] [-t/-s/-f] genres [-n name] [-t title] Search and print a list of genres by name and title. @@ -140,7 +142,7 @@ Language search Usage:: - ml-search.py [-i] [-I] [-t ...] lang [name] + ml-search.py [-i/-I] [-t/-s/-f] lang [name] Search and print a list of languages by name. diff --git a/m_librarian/search.py b/m_librarian/search.py index c4b5325..63078ce 100644 --- a/m_librarian/search.py +++ b/m_librarian/search.py @@ -29,11 +29,6 @@ def _search_with_operator(table, case_sensitive, comparison_op, values, return AND(*_expressions) -def _search_exact(table, case_sensitive, values, expressions): - return _search_with_operator(table, case_sensitive, '__eq__', values, - expressions) - - def _search_start(table, case_sensitive, values, expressions): return _search_with_operator(table, case_sensitive, 'startswith', values, expressions) @@ -44,6 +39,11 @@ def _search_substring(table, case_sensitive, values, expressions): expressions) +def _search_full(table, case_sensitive, values, expressions): + return _search_with_operator(table, case_sensitive, '__eq__', values, + expressions) + + def _search(table, search_type, case_sensitive, values, expressions, orderBy=None): _search_f = globals()['_search_%s' % search_type] diff --git a/scripts/ml-search.py b/scripts/ml-search.py index fa85f90..81d74f9 100755 --- a/scripts/ml-search.py +++ b/scripts/ml-search.py @@ -20,7 +20,7 @@ def _guess_case_sensitivity(values): return False -def _search_authors(case_sensitive, args): +def _search_authors(case_sensitive, search_type, args): if (args.surname or args.name or args.misc_name) and args.fullname: sys.stderr.write( "Cannot search by names and full name at the same time\n") @@ -42,7 +42,7 @@ def _search_authors(case_sensitive, args): )) if case_sensitive is None: case_sensitive = _guess_case_sensitivity(values) - for author in search_authors(args.search_type, case_sensitive, values, + for author in search_authors(search_type, case_sensitive, values, expressions, orderBy=('surname', 'name', 'misc_name')): names = filter(None, (author.surname, author.name, author.misc_name)) @@ -51,7 +51,7 @@ def _search_authors(case_sensitive, args): (u"(%s: %d)" % (_('books'), author.count)).encode(default_encoding) -def _search_books(case_sensitive, args): +def _search_books(case_sensitive, search_type, args): values = {} for column in 'title', 'series', 'archive', 'file': value = getattr(args, column) @@ -59,7 +59,7 @@ def _search_books(case_sensitive, args): values[column] = unicode(value, default_encoding) if case_sensitive is None: case_sensitive = _guess_case_sensitivity(values) - for book in search_books(args.search_type, case_sensitive, values, + for book in search_books(search_type, case_sensitive, values, orderBy='title'): print book.title.encode(default_encoding) if args.details > 0: @@ -72,20 +72,20 @@ def _search_books(case_sensitive, args): print -def _search_extensions(case_sensitive, args): +def _search_extensions(case_sensitive, search_type, args): if args.name: values = {'name': args.name} if case_sensitive is None: case_sensitive = _guess_case_sensitivity(values) else: values = {} - for ext in search_extensions(args.search_type, case_sensitive, values, + for ext in search_extensions(search_type, case_sensitive, values, orderBy='name'): print ext.name.encode(default_encoding), \ (u"(%s: %d)" % (_('books'), ext.count)).encode(default_encoding) -def _search_genres(case_sensitive, args): +def _search_genres(case_sensitive, search_type, args): values = {} for column in 'name', 'title': value = getattr(args, column) @@ -93,7 +93,7 @@ def _search_genres(case_sensitive, args): values[column] = unicode(value, default_encoding) if case_sensitive is None: case_sensitive = _guess_case_sensitivity(values) - for genre in search_genres(args.search_type, case_sensitive, values, + for genre in search_genres(search_type, case_sensitive, values, orderBy='name'): names = filter(None, (genre.name, genre.title)) fullname = u' '.join(names) @@ -101,14 +101,14 @@ def _search_genres(case_sensitive, args): (u"(%s: %d)" % (_('books'), genre.count)).encode(default_encoding) -def _search_languages(case_sensitive, args): +def _search_languages(case_sensitive, search_type, args): if args.name: values = {'name': args.name} if case_sensitive is None: case_sensitive = _guess_case_sensitivity(values) else: values = {} - for lang in search_languages(args.search_type, case_sensitive, values, + for lang in search_languages(search_type, case_sensitive, values, orderBy='name'): print lang.name.encode(default_encoding), \ (u"(%s: %d)" % (_('books'), lang.count)).encode(default_encoding) @@ -116,19 +116,18 @@ def _search_languages(case_sensitive, args): if __name__ == '__main__': main_parser = argparse.ArgumentParser(description='Search') - main_parser.add_argument('-i', '--ignore-case', - action='store_true', + main_parser.add_argument('-i', '--ignore-case', action='store_true', help='ignore case ' '(default is to guess)') - main_parser.add_argument('-I', '--case-sensitive', - action='store_true', - help='don\'t ignore case ') - main_parser.add_argument('-t', '--search-type', - choices=['exact', 'start', 'substring'], - default='start', - help='search type: ' - 'exact match, substring at the start ' - '(this is the default), substring anywhere') + main_parser.add_argument('-I', '--case-sensitive', action='store_true', + help='don\'t ignore case') + main_parser.add_argument('-t', '--start', action='store_true', + help='search substring at the start ' + '(this is the default)') + main_parser.add_argument('-s', '--substring', action='store_true', + help='search substring anywhere') + main_parser.add_argument('-f', '--full', action='store_true', + help='match the entire string') subparsers = main_parser.add_subparsers(help='Commands') parser = subparsers.add_parser('authors', help='Search authors') @@ -162,6 +161,7 @@ if __name__ == '__main__': parser.set_defaults(func=_search_languages) args = main_parser.parse_args() + if args.case_sensitive: if args.ignore_case: sys.stderr.write( @@ -175,5 +175,21 @@ if __name__ == '__main__': case_sensitive = False else: case_sensitive = None # guess case sensitivity + + if int(args.start) + int(args.substring) + int(args.full) > 1: + sys.stderr.write( + "Cannot search case sensitive and case insensitive " + "at the same time\n") + main_parser.print_help() + sys.exit(1) + if args.start: + search_type = 'start' + elif args.substring: + search_type = 'substring' + elif args.full: + search_type = 'full' + else: + search_type = 'start' + open_db() - args.func(case_sensitive, args) + args.func(case_sensitive, search_type, args) -- 2.39.5