def test_check_dependencies_missing(mocker): mocker.patch('shutil.which', return_value=None) mocker.patch('sys.exit') with pytest.raises(Exception, match="Exiftool is not installed. \ Visit http://www.sno.phy.queensu.ca/~phil/exiftool/"): check_dependencies()
def main(argv): check_dependencies() move = False link = False date_regex = None dir_format = os.path.sep.join(['%Y', '%m', '%d']) try: opts, args = getopt.getopt(argv[2:], "d:r:mlh", ["date=", "regex=", "move", "link", "help"]) except getopt.GetoptError: help(version) sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help(version) sys.exit(2) if opt in ("-d", "--date"): if not arg: printer.print.error("Date format cannot be empty") dir_format = Date().parse(arg) if opt in ("-m", "--move"): move = True printer.line("Using move strategy!") if opt in ("-l", "--link"): link = True printer.line("Using link strategy!") if opt in ("-r", "--regex"): try: date_regex = re.compile(arg) except: printer.error("Provided regex is invalid!") sys.exit(2) if link and move: printer.error("Can't use move and link strategy together!") sys.exit(1) if len(argv) < 2: help(version) sys.exit(2) return Phockup( argv[0], argv[1], dir_format=dir_format, move=move, link=link, date_regex=date_regex )
def main(options): check_dependencies() return Phockup( options.input_dir, options.output_dir, dir_format=options.date, move=options.move, link=options.link, date_regex=options.regex, original_filenames=options.original_names, timestamp=options.timestamp, date_field=options.date_field, dry_run=options.dry_run, quiet=options.quiet, max_depth=options.maxdepth, )
def main(options): check_dependencies() return Phockup(options.input_dir, options.output_dir, dir_format=options.date, move=options.move, link=options.link, date_regex=options.regex, original_filenames=options.original_names, timestamp=options.timestamp, date_field=options.date_field, dry_run=options.dry_run, quiet=options.quiet, progress=options.progress, max_depth=options.maxdepth, file_type=options.file_type, max_concurrency=options.max_concurrency, no_date_dir=options.no_date_dir)
def test_check_dependencies_missing(mocker): mocker.patch('shutil.which', return_value=None) mocker.patch('sys.exit') check_dependencies() sys.exit.assert_called_once_with(1)
def test_check_dependencies(mocker): mocker.patch('shutil.which', return_value='exiftool') mocker.patch('sys.exit') check_dependencies() assert not sys.exit.called
def main(): check_dependencies() parser = argparse.ArgumentParser( description=PROGRAM_DESCRIPTION, formatter_class=argparse.RawTextHelpFormatter, ) parser.version = "v%s" % __version__ parser.add_argument( "-v", "--version", action="version", ) parser.add_argument( "-d", "--date", action="store", type=Date().parse, help="""Specify date format for OUTPUTDIR directories. You can choose different year format (e.g. 17 instead of 2017) or decide to skip the day directories and have all photos sorted in year/month. Supported formats: YYYY - 2016, 2017 ... YY - 16, 17 ... MM - 07, 08, 09 ... M - July, August, September ... m - Jul, Aug, Sept ... DD - 27, 28, 29 ... (day of month) DDD - 123, 158, 365 ... (day of year) Example: YYYY/MM/DD -> 2011/07/17 YYYY/M/DD -> 2011/July/17 YYYY/m/DD -> 2011/Jul/17 YY/m-DD -> 11/Jul-17 """, ) exclusive_group = parser.add_mutually_exclusive_group() exclusive_group.add_argument( "-m", "--move", action="store_true", help= """Instead of copying the process will move all files from the INPUTDIR to the OUTPUTDIR. This is useful when working with a big collection of files and the remaining free space is not enough to make a copy of the INPUTDIR. """, ) exclusive_group.add_argument( "-l", "--link", action="store_true", help= """Instead of copying the process will make hard links to all files in INPUTDIR and place them in the OUTPUTDIR. This is useful when working with working structure and want to create YYYY/MM/DD structure to point to same files. """, ) parser.add_argument( "-o", "--original-names", action="store_true", help= "Organize the files in selected format or using the default year/month/day format but keep original filenames.", ) parser.add_argument( "-t", "--timestamp", action="store_true", help= """Use the timestamp of the file (last modified date) if there is no EXIF date information. If the user supplies a regex, it will be used if it finds a match in the filename. This option is intended as "last resort" since the file modified date may not be accurate, nevertheless it can be useful if no other date information can be obtained. """, ) parser.add_argument( "-y", "--dry-run", action="store_true", help="Don't move any files, just show which changes would be done.", ) parser.add_argument( "--maxdepth", type=int, default=-1, choices=range(0, 255), metavar="1-255", help= "Descend at most 'maxdepth' levels (a non-negative integer) of directories", ) parser.add_argument( "-r", "--regex", action="store", type=re.compile, help= """Specify date format for date extraction from filenames if there is no EXIF date information. Example: {regex} can be used to extract the date from file names like the following IMG_27.01.2015-19.20.00.jpg. """, ) parser.add_argument( "-f", "--date-field", action="store", help="""Use a custom date extracted from the exif field specified. To set multiple fields to try in order until finding a valid date, use spaces to separate fields inside a string. Example: DateTimeOriginal "DateTimeOriginal CreateDate FileModifyDate" These fields are checked by default when this argument is not set: "SubSecCreateDate SubSecDateTimeOriginal CreateDate DateTimeOriginal" To get all date fields available for a file, do: exiftool -time:all -mimetype -j <file> """, ) parser.add_argument( "-q", "--quiet", action="store_true", help="""Run without output """, ) parser.add_argument( "input_dir", metavar="INPUTDIR", help="Specify the source directory where your photos are located.", ) parser.add_argument( "output_dir", metavar="OUTPUTDIR", help= "Specify the output directory where your photos should be exported.", ) args = parser.parse_args() return Phockup(args.input_dir, args.output_dir, dir_format=args.date, move=args.move, link=args.link, date_regex=args.regex, original_filenames=args.original_names, timestamp=args.timestamp, date_field=args.date_field, dry_run=args.dry_run, quiet=args.quiet, max_depth=args.maxdepth)
def main(argv): check_dependencies() move = False link = False date_regex = None dir_format = os.path.sep.join(['%Y', '%m', '%d']) original_filenames = False timestamp = False date_field = None dry_run = False try: opts, args = getopt.getopt(argv[2:], "d:r:f:mltoyh", ["date=", "regex=", "move", "link", "original-names", "timestamp", "date-field=", "dry-run", "help"]) except getopt.GetoptError: help(version) sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): help(version) sys.exit(2) if opt in ("-d", "--date"): if not arg: printer.error("Date format cannot be empty") dir_format = Date().parse(arg) if opt in ("-m", "--move"): move = True printer.line("Using move strategy") if opt in ("-l", "--link"): link = True printer.line("Using link strategy") if opt in ("-o", "--original-names"): original_filenames = True printer.line("Using original filenames") if opt in ("-r", "--regex"): try: date_regex = re.compile(arg) except: printer.error("Provided regex is invalid") if opt in ("-t", "--timestamp"): timestamp = True printer.line("Using file's timestamp") if opt in ("-y", "--dry-run"): dry_run = True printer.line("Dry run only, not moving files only showing changes") if opt in ("-f", "--date-field"): if not arg: printer.error("Date field cannot be empty") date_field = arg printer.line("Using as date field: %s" % date_field) if link and move: printer.error("Can't use move and link strategy together") if len(argv) < 2: help(version) sys.exit(2) return Phockup( argv[0], argv[1], dir_format=dir_format, move=move, link=link, date_regex=date_regex, original_filenames=original_filenames, timestamp=timestamp, date_field=date_field, dry_run=dry_run, )