Beispiel #1
0
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()
Beispiel #2
0
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
    )
Beispiel #3
0
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
    )
Beispiel #4
0
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,
    )
Beispiel #5
0
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)
Beispiel #6
0
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)
Beispiel #7
0
def test_check_dependencies(mocker):
    mocker.patch('shutil.which', return_value='exiftool')
    mocker.patch('sys.exit')

    check_dependencies()
    assert not sys.exit.called
Beispiel #8
0
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)
Beispiel #9
0
def test_check_dependencies(mocker):
    mocker.patch('shutil.which', return_value='exiftool')
    mocker.patch('sys.exit')

    check_dependencies()
    assert not sys.exit.called
Beispiel #10
0
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)
Beispiel #11
0
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,
    )