Add betterhelp docstring.
This commit is contained in:
parent
84b35c3eaa
commit
94130e4803
1 changed files with 277 additions and 18 deletions
|
@ -3,6 +3,7 @@ import os
|
|||
import re
|
||||
import sys
|
||||
|
||||
from voussoirkit import betterhelp
|
||||
from voussoirkit import interactive
|
||||
from voussoirkit import pathclass
|
||||
from voussoirkit import spinal
|
||||
|
@ -393,6 +394,258 @@ def tag_breplace_argparse(args):
|
|||
tag.add_synonym(tag_name)
|
||||
photodb.commit()
|
||||
|
||||
DOCSTRING = '''
|
||||
Etiquette CLI
|
||||
=============
|
||||
|
||||
{add_tag}
|
||||
|
||||
{remove_tag}
|
||||
|
||||
{digest}
|
||||
|
||||
{easybake}
|
||||
|
||||
{export_symlinks}
|
||||
|
||||
{init}
|
||||
|
||||
{purge_deleted_files}
|
||||
|
||||
{purge_empty_albums}
|
||||
|
||||
{search}
|
||||
|
||||
{show_associated_directories}
|
||||
|
||||
{set_searchhidden}
|
||||
|
||||
{unset_searchhidden}
|
||||
|
||||
{tag_breplace}
|
||||
|
||||
At any time, you may add --silent, --quiet, --debug, --loud to change logging.
|
||||
|
||||
You can add --yes to avoid the "Commit?" prompt.
|
||||
|
||||
TO SEE DETAILS ON EACH COMMAND, RUN
|
||||
> etiquette_cli.py <command> --help
|
||||
'''
|
||||
|
||||
SUB_DOCSTRINGS = dict(
|
||||
add_tag='''
|
||||
add_tag:
|
||||
Add a tag to files by a filename glob.
|
||||
|
||||
> etiquette_cli.py add_tag tag_name glob_pattern
|
||||
'''.strip(),
|
||||
|
||||
remove_tag='''
|
||||
remove_tag:
|
||||
Remove a tag from files by a filename glob.
|
||||
|
||||
> etiquette_cli.py remove_tag tag_name glob_pattern
|
||||
'''.strip(),
|
||||
|
||||
digest='''
|
||||
digest:
|
||||
Digest a directory, adding new files as Photos into the database.
|
||||
|
||||
> etiquette_cli.py digest directory <flags>
|
||||
|
||||
flags:
|
||||
--no_albums:
|
||||
Do not create any albums the directories. By default, albums are created
|
||||
and nested to match the directory structure.
|
||||
|
||||
--ratelimit X:
|
||||
Limit the ingest of new Photos to only one per X seconds. This can be
|
||||
used to reduce system load or to make sure that two photos don't get the
|
||||
same `created` timestamp.
|
||||
|
||||
--no_recurse:
|
||||
Do not recurse into subdirectories. Only create Photos from files in
|
||||
the current directory.
|
||||
'''.strip(),
|
||||
|
||||
easybake='''
|
||||
easybake:
|
||||
Create and manipulate tags by easybake strings.
|
||||
|
||||
> etiquette_cli.py easybake eb_string
|
||||
'''.strip(),
|
||||
|
||||
export_symlinks='''
|
||||
export_symlinks:
|
||||
Search for photos or albums, then create symlinks pointing to the results.
|
||||
|
||||
THIS IS STILL A BIT EXPERIMENTAL.
|
||||
This can be used to gather up search results for the purpose of further
|
||||
uploading, transfering, etc. with other applications.
|
||||
Symlinks point to files (if result is a photo) or directories (if result is
|
||||
an album with an associated directory).
|
||||
Albums are limited to only one associated directory since the output
|
||||
symlink can't point to two places at once.
|
||||
|
||||
> etiquette_cli.py export_symlinks --destination directory --search searchargs
|
||||
> etiquette_cli.py export_symlinks --destination directory --album-search searchargs
|
||||
|
||||
flags:
|
||||
--destination:
|
||||
A path to a directory into which the symlinks will be placed.
|
||||
|
||||
--dry:
|
||||
Print the results without actually creating the symlinks.
|
||||
|
||||
--prune:
|
||||
In the destination directory, any existing symlinks whose target no
|
||||
longer exists will be deleted.
|
||||
|
||||
See search --help for more info about searchargs.
|
||||
'''.strip(),
|
||||
|
||||
init='''
|
||||
init:
|
||||
Create a new Etiquette database in the current directory.
|
||||
|
||||
> etiquette_cli.py init
|
||||
'''.strip(),
|
||||
|
||||
purge_deleted_files='''
|
||||
purge_deleted_files:
|
||||
Delete any Photo objects whose file no longer exists on disk.
|
||||
|
||||
> etiquette_cli.py purge_deleted_files
|
||||
'''.strip(),
|
||||
|
||||
purge_empty_albums='''
|
||||
purge_empty_albums:
|
||||
Delete any albums which have no child albums or photos.
|
||||
|
||||
Consider running purge_deleted_files first, so that albums containing
|
||||
deleted files will get cleared out and then caught by this function.
|
||||
|
||||
> etiquette_cli.py purge_empty_albums
|
||||
'''.strip(),
|
||||
|
||||
search='''
|
||||
search:
|
||||
Search for photos and albums with complex operators.
|
||||
|
||||
> etiquette_cli.py search searchargs
|
||||
> etiquette_cli.py search --album-search searchargs
|
||||
|
||||
Searchargs:
|
||||
--area X-Y:
|
||||
Photo/video width*height between X and Y.
|
||||
|
||||
--width X-Y:
|
||||
Photo/video width between X and Y.
|
||||
|
||||
--height X-Y:
|
||||
Photo/video height between X and Y.
|
||||
|
||||
--ratio X-Y:
|
||||
Photo/video aspect ratio between X and Y.
|
||||
|
||||
--bytes X-Y:
|
||||
File size in bytes between X and Y.
|
||||
|
||||
--duration X-Y:
|
||||
Media duration between X and Y seconds.
|
||||
|
||||
--author X:
|
||||
Photo authored by user with username X.
|
||||
|
||||
--created X-Y:
|
||||
Photo creation date between X and Y unix timestamp.
|
||||
|
||||
--extension A,B,C:
|
||||
Photo with any extension of A, B, C...
|
||||
|
||||
--extension_not A,B,C:
|
||||
Photo without any extension of A, B, C...
|
||||
|
||||
--filename X:
|
||||
Search terms for Photo's filename.
|
||||
|
||||
--has_tags yes/no/null:
|
||||
If yes, Photo must have at least one tag.
|
||||
If no, Photo must have no tags.
|
||||
If null, doesn't matter.
|
||||
|
||||
--has_thumbnail yes/no/null:
|
||||
|
||||
--is_searchhidden yes/no/null:
|
||||
|
||||
--mimetype A,B,C:
|
||||
Photo with any mimetype of A, B, C...
|
||||
|
||||
--tag_musts A,B,C:
|
||||
Photo must have all tags A and B and C...
|
||||
|
||||
--tag_mays A,B,C:
|
||||
Photo must have at least one tag of A, B, C...
|
||||
|
||||
--tag_forbids A,B,C:
|
||||
Photo must not have any tags of A, B, C...
|
||||
|
||||
--tag_expression X:
|
||||
Complex expression string to match tags.
|
||||
|
||||
--limit X:
|
||||
Limit results to first X items.
|
||||
|
||||
--offset X:
|
||||
Skip the first X items.
|
||||
|
||||
--orderby X-Y:
|
||||
Order the results by property X in direction Y. E.g. created-desc or
|
||||
bytes-asc.
|
||||
'''.strip(),
|
||||
|
||||
show_associated_directories='''
|
||||
show_associated_directories:
|
||||
Show the associated directories for albums.
|
||||
|
||||
> etiquette_cli.py show_associated_directories
|
||||
> etiquette_cli.py show_associated_directories --albums id id id
|
||||
> etiquette_cli.py show_associated_directories --album-search searchargs
|
||||
|
||||
See search --help for more info about searchargs.
|
||||
'''.strip(),
|
||||
|
||||
set_searchhidden='''
|
||||
set_searchhidden:
|
||||
Mark photos as searchhidden.
|
||||
|
||||
> etiquette_cli.py set_searchhidden --photos id id id
|
||||
> etiquette_cli.py set_searchhidden --search searchargs
|
||||
|
||||
See search --help for more info about searchargs.
|
||||
'''.strip(),
|
||||
|
||||
unset_searchhidden='''
|
||||
unset_searchhidden:
|
||||
Unmark photos as searchhidden.
|
||||
|
||||
> etiquette_cli.py unset_searchhidden --photos id id id
|
||||
> etiquette_cli.py unset_searchhidden --search searchargs
|
||||
|
||||
See search --help for more info about searchargs.
|
||||
'''.strip(),
|
||||
|
||||
tag_breplace='''
|
||||
tag_breplace:
|
||||
For all tags in the database, use find-and-replace to rename the tags.
|
||||
|
||||
> etiquette_cli.py tag_breplace replace_from replace_to
|
||||
'''.strip(),
|
||||
|
||||
)
|
||||
|
||||
DOCSTRING = betterhelp.add_previews(DOCSTRING, SUB_DOCSTRINGS)
|
||||
|
||||
def main(argv):
|
||||
global LOG_LEVEL
|
||||
(LOG_LEVEL, argv) = vlogging.get_level_by_argv(argv)
|
||||
|
@ -432,11 +685,6 @@ def main(argv):
|
|||
p_remove_tag.add_argument('--yes', dest='autoyes', action='store_true')
|
||||
p_remove_tag.set_defaults(func=lambda args: add_remove_tag_argparse(args, action='remove'))
|
||||
|
||||
p_easybake = subparsers.add_parser('easybake')
|
||||
p_easybake.add_argument('eb_strings', nargs='+')
|
||||
p_easybake.add_argument('--yes', dest='autoyes', action='store_true')
|
||||
p_easybake.set_defaults(func=easybake_argparse)
|
||||
|
||||
p_digest = subparsers.add_parser('digest', aliases=['digest_directory', 'digest-directory'])
|
||||
p_digest.add_argument('directory')
|
||||
p_digest.add_argument('--no_albums', '--no-albums', dest='make_albums', action='store_false', default=True)
|
||||
|
@ -445,6 +693,11 @@ def main(argv):
|
|||
p_digest.add_argument('--yes', dest='autoyes', action='store_true')
|
||||
p_digest.set_defaults(func=digest_directory_argparse)
|
||||
|
||||
p_easybake = subparsers.add_parser('easybake')
|
||||
p_easybake.add_argument('eb_strings', nargs='+')
|
||||
p_easybake.add_argument('--yes', dest='autoyes', action='store_true')
|
||||
p_easybake.set_defaults(func=easybake_argparse)
|
||||
|
||||
p_export_symlinks = subparsers.add_parser('export_symlinks', aliases=['export-symlinks'])
|
||||
p_export_symlinks.add_argument('--destination', dest='destination', required=True)
|
||||
p_export_symlinks.add_argument('--dry', dest='dry_run', action='store_true')
|
||||
|
@ -509,20 +762,26 @@ def main(argv):
|
|||
|
||||
##
|
||||
|
||||
args = parser.parse_args(primary_args)
|
||||
def pp(args):
|
||||
args.photo_search_args = p_search.parse_args(photo_search_args) if photo_search_args else None
|
||||
args.album_search_args = p_search.parse_args(album_search_args) if album_search_args else None
|
||||
args.photo_id_args = [id for arg in photo_id_args for id in stringtools.comma_space_split(arg)]
|
||||
args.album_id_args = [id for arg in album_id_args for id in stringtools.comma_space_split(arg)]
|
||||
args.any_id_args = bool(
|
||||
args.photo_search_args or
|
||||
args.album_search_args or
|
||||
args.photo_id_args or
|
||||
args.album_id_args
|
||||
)
|
||||
return args
|
||||
|
||||
photo_search_args = p_search.parse_args(photo_search_args) if photo_search_args else None
|
||||
album_search_args = p_search.parse_args(album_search_args) if album_search_args else None
|
||||
photo_id_args = [id for arg in photo_id_args for id in stringtools.comma_space_split(arg)]
|
||||
album_id_args = [id for arg in album_id_args for id in stringtools.comma_space_split(arg)]
|
||||
|
||||
args.photo_search_args = photo_search_args
|
||||
args.album_search_args = album_search_args
|
||||
args.photo_id_args = photo_id_args
|
||||
args.album_id_args = album_id_args
|
||||
args.any_id_args = bool(photo_search_args or album_search_args or photo_id_args or album_id_args)
|
||||
|
||||
return args.func(args)
|
||||
return betterhelp.subparser_main(
|
||||
primary_args,
|
||||
parser,
|
||||
main_docstring=DOCSTRING,
|
||||
sub_docstrings=SUB_DOCSTRINGS,
|
||||
args_postprocessor=pp,
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main(sys.argv[1:]))
|
||||
|
|
Loading…
Reference in a new issue