Esempio n. 1
0
def analyse(src_path, files, title, description, author):
    """
    Checks exif for all files in src_path
    :param src_path: Path to the image files
    :param files: List with valid file names
    :param title: String with new title, or None, if tag should not be changed
    :param description: String with new description, or None, if tag should not be changed
    :param author: String for author tag. Can be None

    Returns list with dict() for every image file, for instance:
        return [
          dict(name='image001.jpg',
               title=dict(old=None, new="new title', changed=True, overwrite=True),
               description=dict(old=None, new="new title', changed=True, overwrite=True)
               author=dict(old=None, new="new author', changed=True, overwrite=True)
               )
        ]
        'changed' is True, if tag will be set
        'overwrite' is True, if old value would be overwritten (needs force)
    """
    src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL
    # files = list_jpg(src_dir)
    exifs = images_get_exifs(src_dir, files, report=False)

    ret = []
    for each in exifs:
        ret.append(dict(name=each['name'], title=_analyze_tag(title, each['title']),
                        description=_analyze_tag(description, each['description']),
                        author=_analyze_tag(author, each['author'])))

    # print('analyse() ret=' + str(ret))

    return ret
Esempio n. 2
0
def analyse(_task, _dest):
    """
    Checks export to dest from given task.
    task: dictionary with keys 'task' (foldername/taskname),
                                'name' (task name),
                                'folder' (folder name)
    dest: String with absolut path
    Returns list with dict() for every source file, for instance:
        return [dict(name='image001.jpg', exists='true',
                src_time=1474878288.2156258,
                dst_time=1474878288.2156258)] or dst_time=None
    """
    src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL
    files = list_jpg(src_dir)
    # for file in files:
    # print('export_analyse() file=' + str(file) + ' '
    # + time_readable(os.path.getatime(src_dir + '/' + file)))

    ret = []
    for file in files:
        exists = os.path.exists(_dest + '/' + file)
        if exists:
            dst_time = os.path.getatime(_dest + '/' + file)
        else:
            dst_time = None

        ret.append(
            dict(name=file,
                 exists=exists,
                 src_time=os.path.getatime(src_dir + '/' + file),
                 dst_time=dst_time))

    # print('export_analyse() ret=' + str(ret))

    return ret
Esempio n. 3
0
File: show.py Progetto: chs8691/fow
def tasks():
    """
    Reports infos about all tasks.
    """
    actual = task.get_actual()
    # dir02 = os.listdir(get_path(DIR_02))
    dir02 = [f.name for f in os.scandir(get_path(DIR_02)) if f.is_dir()]
    dir02.sort()
    for each_folder in dir02:
        print(' ' + each_folder)
        # tasks = os.listdir(get_path(DIR_02) + '/' + each_folder)
        tasks = [
            f.name for f in os.scandir(get_path(DIR_02) + '/' + each_folder)
            if f.is_dir()
        ]

        tasks.sort()
        for each_task in tasks:
            stats = get_short_status(
                get_path(DIR_02) + '/' + each_folder + '/' + each_task)
            jpgs = len([s for s in stats if s['jpg']])
            raws = len([s for s in stats if s['raw']])
            finals = len([s for s in stats if s['final']])
            if jpgs == 0:
                jtext = '---'
            else:
                jtext = '{:>3}'.format(str(jpgs))
            if raws == 0:
                rtext = '---'
            else:
                rtext = '{:>3}'.format(str(raws))
            if finals == 0:
                ftext = '---'
            else:
                ftext = '{:>3}'.format(str(finals))

            if actual['folder'] == each_folder and \
                            actual['name'] == each_task:
                start = '*    '
            else:
                start = '     '

            print(start + jtext + ' ' + rtext + ' ' + ftext + ' ' +
                  str(each_task))
Esempio n. 4
0
File: show.py Progetto: chs8691/fow
def tasks():
    """
    Reports infos about all tasks.
    """
    actual = task.get_actual()
    # dir02 = os.listdir(get_path(DIR_02))
    dir02 = [f.name for f in os.scandir(get_path(DIR_02)) if f.is_dir()]
    dir02.sort()
    for each_folder in dir02:
        print(' ' + each_folder)
        # tasks = os.listdir(get_path(DIR_02) + '/' + each_folder)
        tasks = [f.name for f in os.scandir(get_path(DIR_02) + '/' + each_folder) if f.is_dir()]

        tasks.sort()
        for each_task in tasks:
            stats = get_short_status(get_path(DIR_02) + '/' + each_folder + '/'
                                     + each_task)
            jpgs = len([s for s in stats if s['jpg']])
            raws = len([s for s in stats if s['raw']])
            finals = len([s for s in stats if s['final']])
            if jpgs == 0:
                jtext = '---'
            else:
                jtext = '{:>3}'.format(str(jpgs))
            if raws == 0:
                rtext = '---'
            else:
                rtext = '{:>3}'.format(str(raws))
            if finals == 0:
                ftext = '---'
            else:
                ftext = '{:>3}'.format(str(finals))

            if actual['folder'] == each_folder and \
                            actual['name'] == each_task:
                start = '*    '
            else:
                start = '     '

            print(start + jtext + ' ' + rtext + ' ' + ftext + ' '
                  + str(each_task))
Esempio n. 5
0
def analyse(_task, _dest):
    """
    Checks export to dest from given task.
    task: dictionary with keys 'task' (foldername/taskname),
                                'name' (task name),
                                'folder' (folder name)
    dest: String with absolut path
    Returns list with dict() for every source file, for instance:
        return [dict(name='image001.jpg', exists='true',
                src_time=1474878288.2156258,
                dst_time=1474878288.2156258)] or dst_time=None
    """
    src_dir = task.get_task_path(task.get_actual()['task']) + '/' + DIR_FINAL
    files = list_jpg(src_dir)
    # for file in files:
    # print('export_analyse() file=' + str(file) + ' '
    # + time_readable(os.path.getatime(src_dir + '/' + file)))

    ret = []
    for file in files:
        exists = os.path.exists(_dest + '/' + file)
        if exists:
            dst_time = os.path.getatime(_dest + '/' + file)
        else:
            dst_time = None

        ret.append(dict(
            name=file,
            exists=exists,
            src_time=os.path.getatime(src_dir + '/' + file),
            dst_time=dst_time
        ))

    # print('export_analyse() ret=' + str(ret))

    return ret
Esempio n. 6
0
def cmd_show(cmd_list):
    """
    Processing step reporting
    """

    atom_short = dict(name='short', short='s', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=OPTIONAL_PARAM)

    # atomNone must be mandatory for rules with more than one path
    ret = check_rules(cmd_list, [[
        dict(atom=atom_none, obligat=True),
        dict(atom=atom_short, obligat=False)
    ]])
    if ret['message'] is not None:
        return

    if ret['options'][''] == 'inbox':
        if 'short' in ret['options']:
            show.in_summary(plump.get_path(plump.DIR_00))
        else:
            show.show_in(plump.get_path(plump.DIR_00))
        return

    if ret['options'][''] == 'import':
        if 'short' in ret['options']:
            show.in_summary(plump.get_path(plump.DIR_01))
        else:
            show.show_in(plump.get_path(plump.DIR_01))
        return

    if ret['options'][''] == 'in':
        if 'short' in ret['options']:
            print('inbox:')
            show.in_summary(plump.get_path(plump.DIR_00))
            print('import:')
            show.in_summary(plump.get_path(plump.DIR_01))
        else:
            print('inbox:')
            show.show_in(plump.get_path(plump.DIR_00))
            print('import:')
            show.show_in(plump.get_path(plump.DIR_01))
        return

    if ret['options'][''] == 'tasks':
        if 'short' in ret['options']:
            show.tasks_summary()
        else:
            show.tasks()
        return

    # if 'task' in args['args'] or len(args['args']) == 0:
    if ret['options'][''] in ('task', None):
        if task.get_actual() is None:
            print('No actual task. ' +
                  'Use "task --create <task>" to create one.')
        else:
            print('Actual task is ' + task.get_actual()['task'] + '.')
            if 'short' in ret['options']:
                show.task_summary(
                    plump.get_path(plump.DIR_02) + '/' +
                    task.get_actual()['task'])
            else:
                show.show_task(
                    plump.get_path(plump.DIR_02) + '/' +
                    task.get_actual()['task'], False)
        return
Esempio n. 7
0
def cmd_task(cmd_list):
    """
    Task manipulation.
    """

    # Command needs an existing fow.
    if not plump.is_fow():
        return

    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_none = dict(name='', short='', args=NONE_PARAM)
    atom_create = dict(name='create', short='c', args=MANDATORY_PARAM)
    atom_activate = dict(name='activate', short='a', args=MANDATORY_PARAM)
    atom_next = dict(name='next', short='n', args=NONE_PARAM)
    atom_previous = dict(name='previous', short='p', args=NONE_PARAM)
    atom_short = dict(name='short', short='s', args=NONE_PARAM)
    atom_long = dict(name='long', short='l', args=NONE_PARAM)
    atom_raw_import = dict(name='raw-import', short='r', args=NONE_PARAM)
    atom_fill_final = dict(name='fill-final', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)

    ret = check_rules(cmd_list, [[dict(atom=atom_create, obligat=True)],
                                 [dict(atom=atom_activate, obligat=True)],
                                 [
                                     dict(atom=atom_none, obligat=True),
                                     dict(atom=atom_short, obligat=False)
                                 ],
                                 [
                                     dict(atom=atom_none, obligat=True),
                                     dict(atom=atom_long, obligat=False)
                                 ], [dict(atom=atom_next, obligat=True)],
                                 [dict(atom=atom_previous, obligat=True)],
                                 [
                                     dict(atom=atom_raw_import, obligat=True),
                                     dict(atom=atom_test, obligat=False)
                                 ],
                                 [
                                     dict(atom=atom_fill_final, obligat=True),
                                     dict(atom=atom_test, obligat=False)
                                 ]])

    if ret['message'] is not None:
        return

    # print("cmd_task() ret={}".format(str(ret)))

    # --- Options to change the actual task (activate or create)---#
    if 'create' in ret['options'] or 'activate' in ret['options']:
        if 'create' in ret['options']:
            path_arg = ret['options']['create']
        else:
            path_arg = ret['options']['activate']

        # arg for option '' is the path, Path may not end with '/'
        if path_arg is not None and len(path_arg) > 0 and path_arg[-1] == '/':
            path_arg = path_arg[0:-1]

        # Extract folder and task name
        if path_arg.count('/') > 2:
            print('Path too long, use [[' + plump.DIR_02 +
                  ']/<folder>/]]<task>')
            return

        # print("cmd_task() path_arg={}".format(str(path_arg)))
        # Dictionary with all task parts
        path = dict(folder=None, task=None, ft=None, path=None)
        if path_arg.count('/') == 2:
            # print(args['args'][0])
            if not path_arg.startswith(plump.DIR_02 + '/'):
                print('Invalid path. Try [[' + plump.DIR_02 +
                      '/]<folder>/]]<task>.')
                return
            else:
                parts = path_arg.split('/')
                path['folder'] = parts[-2]
                path['task'] = parts[-1]

        elif path_arg.count('/') == 1:
            parts = path_arg.split('/')
            path['folder'] = parts[-2]
            path['task'] = parts[-1]

        else:
            path['task'] = path_arg

        # If only task is given, take the active folder
        if path['folder'] is None:
            if task.get_actual() is None:
                print('No actual task set, please specify the folder, too: ' +
                      '[[' + plump.DIR_02 + '/]<folder>/]]<task>')
                return
            path['folder'] = task.get_actual()['folder']

        # For convenience usage
        path['ft'] = path['folder'] + '/' + path['task']
        path['path'] = plump.get_path(plump.DIR_02) + '/' + path['ft']

        # task --create <task>
        if 'create' in ret['options']:
            if os.path.exists(path['path']):
                print('task ' + str(path['ft']) + ' already exists.' +
                      ' Choose a different name to create a new task.')
                return

            os.makedirs(path['path'])
            os.mkdir(path['path'] + '/' + plump.DIR_FINAL)
            os.mkdir(path['path'] + '/' + plump.DIR_JPG)
            os.mkdir(path['path'] + '/' + plump.DIR_RAW)
            os.mkdir(path['path'] + '/' + plump.DIR_WORK)
            os.mkdir(path['path'] + '/' + plump.DIR_VIDEO)
            config.set_item(plump.TASK, path['ft'])
            return

        if 'activate' in ret['options']:
            # print('path =' + str(path))
            if not os.path.exists(path['path']):
                print(
                    'task ' + str(path['ft']) + ' does not exist.' +
                    ' To create a new task use "task --create [<folder>/]<task>"'
                )
                return

            config.set_item(plump.TASK, path['ft'])
            return

    # --- Options for the actual task ---#

    # task --short
    # task
    # task --long
    if 'short' in ret['options'] or 'long' in ret['options'] or len(
            ret['options']) == 1:
        if task.get_actual() is None:
            print('No actual task. ' +
                  'Use "task --create <task>" to create one.')
        else:
            if 'short' in ret['options']:
                print('Actual task {}. Showing a summary.'.format(
                    task.get_actual()['task']))
                show.task_summary(
                    plump.get_path(plump.DIR_02) + '/' +
                    task.get_actual()['task'])
            elif 'long' in ret['options']:
                print('Actual task is {}. Listing all image files.'.format(
                    task.get_actual()['task']))
                show.show_task(
                    plump.get_path(plump.DIR_02) + '/' +
                    task.get_actual()['task'], False)
            else:
                print(
                    'Actual task is {}. Listing image files in final.'.format(
                        task.get_actual()['task']))
                show.show_task(
                    plump.get_path(plump.DIR_02) + '/' +
                    task.get_actual()['task'], True)
        return

    # task --raw-import
    # task --raw-import --test
    if 'raw-import' in ret['options']:
        if task.get_actual() is None:
            print('No actual task set, please specify the folder, too: ' +
                  '[' + plump.get_path(plump.DIR_02) + '/]<folder>/<task>')
            return

        task.move_corresponding_raws(
            plump.get_path(plump.DIR_02) + '/' + task.get_actual()['task'] +
            '/' + plump.DIR_JPG,
            plump.get_path(plump.DIR_01) + '/' + plump.DIR_RAW,
            plump.get_path(plump.DIR_02) + '/' + task.get_actual()['task'] +
            '/' + plump.DIR_RAW, 'test' in ret['options'])
        return

    # task --fill-final
    # task --fill-final --test
    if 'fill-final' in ret['options']:
        if task.get_actual() is None:
            print('No actual task set, please specify the folder, too: ' +
                  '[' + plump.get_path(plump.DIR_02) + '/]<folder>/<task>')
            return

        plump.copy_missing_jpgs(
            plump.get_path(plump.DIR_02) + '/' + task.get_actual()['task'] +
            '/' + plump.DIR_JPG,
            plump.get_path(plump.DIR_02) + '/' + task.get_actual()['task'] +
            '/' + plump.DIR_FINAL, 'test' in ret['options'])
        return

    # task --next
    # task --previous
    if 'next' in ret['options'] or 'previous' in ret['options']:
        if 'previous' in ret['options']:
            offset = -1
        else:
            offset = 1
        old_triple = task.get_task_triple(offset)
        if old_triple is None:
            print('No actual task found.')
            return

        if old_triple['p_task'] is None:
            print('Seems to be only one task. Switching not possible.')
            return

        config.set_item(
            plump.TASK, '{0}/{1}'.format(old_triple['a_task']['subdir'],
                                         old_triple['a_task']['task']))

        new_triple = task.get_task_triple(0)

        print('   {0}/{1}'.format(str(new_triple['p_task']['subdir']),
                                  str(new_triple['p_task']['task'])))
        print('*  {0}/{1}'.format(str(new_triple['a_task']['subdir']),
                                  str(new_triple['a_task']['task'])))
        print('   {0}/{1}'.format(str(new_triple['n_task']['subdir']),
                                  str(new_triple['n_task']['task'])))
        return
Esempio n. 8
0
def cmd_gps(cmd_list):
    """
    Adds geo locations from gps files
    """

    atom_none = dict(name='', short='', args=NONE_PARAM)
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_source = dict(name='source', short='s', args=MANDATORY_PARAM)
    atom_write = dict(name='write', short='w', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_map = dict(name='map', short='m', args=NONE_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_verbose = dict(name='verbose', short='v', args=NONE_PARAM)

    ret = check_rules(cmd_list, [[
        dict(atom=atom_none, obligat=True),
        dict(atom=atom_source, obligat=False),
        dict(atom=atom_write, obligat=False),
        dict(atom=atom_test, obligat=False),
        dict(atom=atom_write, obligat=False),
        dict(atom=atom_verbose, obligat=False),
        dict(atom=atom_force, obligat=False)
    ],
                                 [
                                     dict(atom=atom_path, obligat=True),
                                     dict(atom=atom_source, obligat=False),
                                     dict(atom=atom_test, obligat=False),
                                     dict(atom=atom_verbose, obligat=False),
                                     dict(atom=atom_force, obligat=False)
                                 ],
                                 [
                                     dict(atom=atom_map, obligat=True),
                                     dict(atom=atom_path, obligat=False)
                                 ]])

    if ret['message'] is not None:
        return

    # print('cmd_gps() options_matrix=' + str(options_matrix))
    # arg validation
    # image path as destination
    # image path as path argument
    # if 'path' in options['names']:
    if 'path' in ret['options']:
        if not os.path.exists(plump.get_path(ret['options'][''])):
            print(((
                "'{0}' is not an existing sub dir within this fow. " +
                "Maybe the directory is temporary not available or you have to "
                + "write the correct path.")).format(str(ret['options'][''])))
            return
        # Validated absolute path to the images
        image_path = plump.get_path(ret['options'][''])

    # elif ret['options'][''] is not None:
    #     key = 'gps.{}'.format(ret['options'][''])
    #     if config.read_item(key) is None:
    #         print(
    #             "Value {0} not configured. Maybe you have to set it first with
    # config -s '{0}=fow-subdir-to-images'".format(
    #                 key))
    #         return
    #     if not os.path.exists(plump.get_path(config.read_item(key))):
    #         print((("Destination points to a non existing sub dir: '{0}'. " +
    #                 "Maybe the directory is temporary not available or you have to" +
    #                 " change the destination with 'config -s {1}=fow-subdir-to-images'"))
    #               .format(str(config.read_item(key)), key))
    #         return
    #     # Validated absolute path to the images
    #     image_path = plump.get_path(config.read_item(key))

    # image path is the actual final
    else:
        if task.get_actual() is None:
            print('No active task.')
            return
        elif not os.path.exists(task.get_actual()['path']):
            print(
                "Actual task '{0}' is not an existing sub dir within this fow."
                .format(str(task.get_actual()['path'])))
            return
        else:
            image_path = '{}/{}'.format(task.get_actual()['path'],
                                        plump.DIR_FINAL)

    # Now we have a valid, existing absolute path to the images
    # Just show map
    if 'map' in ret['options']:
        fow_gps.map(image_path)
        return

    # track path as source argument
    if 'source' in ret['options']:
        if not os.path.exists(ret['options']['source']):
            print("'{0}' is not an existing, accessible directory. ".format(
                str(ret['options']['source'])))
            return
        # Validated absolute path to the images
        track_path = ret['options']['source']

    else:
        if config.read_item(plump.GPS_TRACK_PATH) is None:
            print(
                '{0} not set. Define the path to tracks folder with config -s {0}=/your/tracks/path'
                .format(plump.GPS_TRACK_PATH))
            return
        elif not os.path.exists(config.read_item(plump.GPS_TRACK_PATH)):
            print((
                "Invalid path to track files: '{0}'. May the directory is temporary not available or you have to"
                + " change it with 'config -s {1}=/your/tracks/path'").format(
                    str(config.read_item(plump.GPS_TRACK_PATH)),
                    plump.GPS_TRACK_PATH))
            return
        # Validated absolute path to the images
        track_path = config.read_item(plump.GPS_TRACK_PATH)

    # gps --write
    if 'write' in ret['options']:
        if not os.path.exists(
                os.path.join(task.get_actual()['path'], plump.DIR_WORK)):
            print("Missing sub directory {}.".format(plump.DIR_WORK))
            return
        else:
            write_path = os.path.join(task.get_actual()['path'],
                                      plump.DIR_WORK)
    else:
        write_path = None

    analysis = fow_gps.analyse(track_path, image_path, write_path)
    # print('cmd_gps() analysis=' + str(analysis))

    # gps --verbose
    if 'verbose' in ret['options']:
        verbose = True
    else:
        verbose = False

    # gps --test
    if 'test' in ret['options']:
        fow_gps.test(analysis, verbose, write_path)
        return

    # gps
    else:
        fow_gps.do(analysis, True, verbose, write_path)
Esempio n. 9
0
def cmd_exif(cmd_list):
    """
    Set exif values
    """
    atom_none = dict(name='', short='', args=OPTIONAL_PARAM)
    atom_title = dict(name='title', short='t', args=MANDATORY_PARAM)
    atom_description = dict(name='description',
                            short='d',
                            args=MANDATORY_PARAM)
    atom_author = dict(name='author', short='a', args=NONE_PARAM)
    atom_check = dict(name='check', short='c', args=NONE_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_verbose = dict(name='verbose', short='v', args=NONE_PARAM)

    # If none has an optional parameter, no other option in the same rule should have an optional parameter, too.
    ret = check_rules(cmd_list,
                      [[
                          dict(atom=atom_none, obligat=True),
                          dict(atom=atom_verbose, obligat=False),
                      ],
                       [
                           dict(atom=atom_none, obligat=True),
                           dict(atom=atom_title, obligat=True),
                           dict(atom=atom_description, obligat=False),
                           dict(atom=atom_author, obligat=False),
                           dict(atom=atom_check, obligat=False),
                           dict(atom=atom_force, obligat=False),
                           dict(atom=atom_verbose, obligat=False),
                       ],
                       [
                           dict(atom=atom_none, obligat=True),
                           dict(atom=atom_title, obligat=False),
                           dict(atom=atom_description, obligat=True),
                           dict(atom=atom_author, obligat=False),
                           dict(atom=atom_check, obligat=False),
                           dict(atom=atom_force, obligat=False),
                           dict(atom=atom_verbose, obligat=False),
                       ],
                       [
                           dict(atom=atom_none, obligat=True),
                           dict(atom=atom_title, obligat=False),
                           dict(atom=atom_description, obligat=False),
                           dict(atom=atom_author, obligat=True),
                           dict(atom=atom_check, obligat=False),
                           dict(atom=atom_force, obligat=False),
                           dict(atom=atom_verbose, obligat=False),
                       ]])

    if ret['message'] is not None:
        return

    # Get author
    if 'author' in ret['options']:
        try:
            author = config.read_pickle()["{}.{}".format(
                plump.EXIF_PREFIX, 'author')]
            if len(str(author)) == 0:
                print(
                    "Destination value not defined. Create it with config -s '{}.author=<value>' first."
                    .format(plump.EXIF_PREFIX))
                return
            # Replace year
            author = author.replace("{YYYY}", str(datetime.now().year))

        except (TypeError, KeyError):
            print(
                "xDestination value not defined. Create it with config -s '{}.author=<value>' first."
                .format(plump.EXIF_PREFIX))
            return
    else:
        author = None

    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)

    # None, '*', 1,2,3 or a file name
    files = fow_exif.check_images(src_path, ret['options'][''])
    # print("cmd_exif() files={}".format(str(files)))
    if files is None:
        print("No images found")
        return

    if 'title' in ret['options']:
        title = ret['options']['title']
    else:
        title = None

    if 'description' in ret['options']:
        description = ret['options']['description']
    else:
        description = None

    analysis = fow_exif.analyse(src_path, files, title, description, author)

    # print("cmd_exif() value=" + str(analysis))

    if title is None and description is None and author is None:
        fow_exif.show(analysis, src_dir, 'verbose' in ret['options'])
        return

    if 'check' in ret['options']:
        fow_exif.test(analysis, src_dir, title is not None, description
                      is not None, author is not None, 'force'
                      in ret['options'], 'verbose' in ret['options'])
        return

    # exif --force
    if 'force' not in ret['options']:
        overwritten_tags = [
            a for a in analysis if a['title']['overwrite']
            or a['description']['overwrite'] or a['author']['overwrite']
        ]
        if len(overwritten_tags) > 0:
            print("Value(s) would be overwritten, use --force to to this.")
            return

    # Do it!
    fow_exif.do(analysis, src_path, title is not None, description is not None,
                author is not None, 'verbose' in ret['options'])
Esempio n. 10
0
def cmd_export(cmd_list):
    """
    Copy finals to external destinations.
    """
    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=MANDATORY_PARAM)

    ret = check_rules(cmd_list, [[
        dict(atom=atom_path, obligat=True),
        dict(atom=atom_force, obligat=False),
        dict(atom=atom_test, obligat=False)
    ],
                                 [
                                     dict(atom=atom_none, obligat=True),
                                     dict(atom=atom_force, obligat=False),
                                     dict(atom=atom_test, obligat=False)
                                 ]])

    if ret['message'] is not None:
        return

    # Get destination
    if 'path' in ret['options']:
        destination = ret['options']['path']
    else:
        try:
            destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' +
                                               ret['options']['']]
        except:
            print(
                "Destination value not defined. Create it with config -s='export.{}' first."
                .format(ret['options']['']))
            return

    if destination is None:
        print('Destination not valid. See "help export".')
        return

    # Extract task specific subdirectory {1} or {2}, if given
    m = re.compile('(.*)(/{[12]}/?)').match(destination)

    # Direct path
    if m is None:
        if not os.path.exists(destination):
            print('Destination directory not reachable: ' + destination)
            return

    # Task specific path
    else:
        root_dir = m.group(1)
        if os.path.exists(m.group(1)):
            # Resolve subdirectory placeholder: task name
            if destination.endswith(('{1}', '{1}/')):
                destination = root_dir + '/' + task.get_actual()['name']
            # Resolve subdirectory placeholder: folder + task name
            elif destination.endswith(('{2}', '{2}/')):
                destination = root_dir + '/' + task.get_actual()['task']
        else:
            print('Destination root directory not reachable: ' + root_dir)
            return

    print('destination={}'.format(destination))
    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)
    files = plump.list_jpg(src_path)

    # [dict(name='image001.jpg', exists='true')]
    analysis = export.analyse(task.get_actual(), destination)
    if 'test' in ret['options']:
        export.test(analysis, src_dir, destination)
        return

    # export --force
    if 'force' in ret['options']:
        print(
            str(len(files)) + ' images in ' + task.get_actual()['task'] + '/' +
            plump.DIR_FINAL)
        print('Destination: ' + destination)
        export.copy(analysis, src_path, destination)

    # export
    else:
        exists = False
        for item in analysis:
            if item['exists']:
                exists = True
        if exists:
            print('Files would be overwritten! ' +
                  'Use --test to list the file(s) ' +
                  'or use --force to overwrite the image(s). ')
        else:
            print(
                str(len(files)) + ' images in ' + task.get_actual()['task'] +
                '/' + plump.DIR_FINAL)
            print('Destination: ' + destination)
            export.copy(analysis, src_path, destination)
Esempio n. 11
0
File: main.py Progetto: chs8691/fow
def cmd_show(cmd_list):
    """
    Processing step reporting
    """

    atom_short = dict(name='short', short='s', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=OPTIONAL_PARAM)

    # atomNone must be mandatory for rules with more than one path
    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_short, obligat=False)
                          ]
                      ])
    if ret['message'] is not None:
        return

    if ret['options'][''] == 'inbox':
        if 'short' in ret['options']:
            show.in_summary(plump.get_path(plump.DIR_00))
        else:
            show.show_in(plump.get_path(plump.DIR_00))
        return

    if ret['options'][''] == 'import':
        if 'short' in ret['options']:
            show.in_summary(plump.get_path(plump.DIR_01))
        else:
            show.show_in(plump.get_path(plump.DIR_01))
        return

    if ret['options'][''] == 'in':
        if 'short' in ret['options']:
            print('inbox:')
            show.in_summary(plump.get_path(plump.DIR_00))
            print('import:')
            show.in_summary(plump.get_path(plump.DIR_01))
        else:
            print('inbox:')
            show.show_in(plump.get_path(plump.DIR_00))
            print('import:')
            show.show_in(plump.get_path(plump.DIR_01))
        return

    if ret['options'][''] == 'tasks':
        if 'short' in ret['options']:
            show.tasks_summary()
        else:
            show.tasks()
        return

    # if 'task' in args['args'] or len(args['args']) == 0:
    if ret['options'][''] in ('task', None):
        if task.get_actual() is None:
            print('No actual task. ' +
                  'Use "task --create <task>" to create one.')
        else:
            print('Actual task is ' + task.get_actual()['task'] + '.')
            if 'short' in ret['options']:
                show.task_summary(plump.get_path(plump.DIR_02) + '/'
                                  + task.get_actual()['task'])
            else:
                show.show_task(plump.get_path(plump.DIR_02) + '/'
                               + task.get_actual()['task'], False)
        return
Esempio n. 12
0
File: main.py Progetto: chs8691/fow
def cmd_gps(cmd_list):
    """
    Adds geo locations from gps files
    """

    atom_none = dict(name='', short='', args=NONE_PARAM)
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_source = dict(name='source', short='s', args=MANDATORY_PARAM)
    atom_write = dict(name='write', short='w', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_map = dict(name='map', short='m', args=NONE_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_verbose = dict(name='verbose', short='v', args=NONE_PARAM)

    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_source, obligat=False),
                              dict(atom=atom_write, obligat=False),
                              dict(atom=atom_test, obligat=False),
                              dict(atom=atom_write, obligat=False),
                              dict(atom=atom_verbose, obligat=False),
                              dict(atom=atom_force, obligat=False)
                          ],
                          [
                              dict(atom=atom_path, obligat=True),
                              dict(atom=atom_source, obligat=False),
                              dict(atom=atom_test, obligat=False),
                              dict(atom=atom_verbose, obligat=False),
                              dict(atom=atom_force, obligat=False)
                          ],
                          [
                              dict(atom=atom_map, obligat=True),
                              dict(atom=atom_path, obligat=False)
                          ]
                      ])

    if ret['message'] is not None:
        return

    # print('cmd_gps() options_matrix=' + str(options_matrix))
    # arg validation
    # image path as destination
    # image path as path argument
    # if 'path' in options['names']:
    if 'path' in ret['options']:
        if not os.path.exists(plump.get_path(ret['options'][''])):
            print((("'{0}' is not an existing sub dir within this fow. " +
                    "Maybe the directory is temporary not available or you have to " +
                    "write the correct path."))
                  .format(str(ret['options'][''])))
            return
        # Validated absolute path to the images
        image_path = plump.get_path(ret['options'][''])

    # elif ret['options'][''] is not None:
    #     key = 'gps.{}'.format(ret['options'][''])
    #     if config.read_item(key) is None:
    #         print(
    #             "Value {0} not configured. Maybe you have to set it first with
    # config -s '{0}=fow-subdir-to-images'".format(
    #                 key))
    #         return
    #     if not os.path.exists(plump.get_path(config.read_item(key))):
    #         print((("Destination points to a non existing sub dir: '{0}'. " +
    #                 "Maybe the directory is temporary not available or you have to" +
    #                 " change the destination with 'config -s {1}=fow-subdir-to-images'"))
    #               .format(str(config.read_item(key)), key))
    #         return
    #     # Validated absolute path to the images
    #     image_path = plump.get_path(config.read_item(key))

    # image path is the actual final
    else:
        if task.get_actual() is None:
            print('No active task.')
            return
        elif not os.path.exists(task.get_actual()['path']):
            print("Actual task '{0}' is not an existing sub dir within this fow."
                  .format(str(task.get_actual()['path'])))
            return
        else:
            image_path = '{}/{}'.format(task.get_actual()['path'], plump.DIR_FINAL)

    # Now we have a valid, existing absolute path to the images
    # Just show map
    if 'map' in ret['options']:
        fow_gps.map(image_path)
        return

    # track path as source argument
    if 'source' in ret['options']:
        if not os.path.exists(ret['options']['source']):
            print("'{0}' is not an existing, accessible directory. "
                  .format(str(ret['options']['source'])))
            return
        # Validated absolute path to the images
        track_path = ret['options']['source']

    else:
        if config.read_item(plump.GPS_TRACK_PATH) is None:
            print('{0} not set. Define the path to tracks folder with config -s {0}=/your/tracks/path'
                  .format(plump.GPS_TRACK_PATH))
            return
        elif not os.path.exists(config.read_item(plump.GPS_TRACK_PATH)):
            print(("Invalid path to track files: '{0}'. May the directory is temporary not available or you have to" +
                   " change it with 'config -s {1}=/your/tracks/path'")
                  .format(str(config.read_item(plump.GPS_TRACK_PATH)), plump.GPS_TRACK_PATH))
            return
        # Validated absolute path to the images
        track_path = config.read_item(plump.GPS_TRACK_PATH)

    # gps --write
    if 'write' in ret['options']:
        if not os.path.exists(os.path.join(task.get_actual()['path'], plump.DIR_WORK)):
            print("Missing sub directory {}.".format(plump.DIR_WORK))
            return
        else:
            write_path = os.path.join(task.get_actual()['path'], plump.DIR_WORK)
    else:
        write_path = None

    analysis = fow_gps.analyse(track_path, image_path, write_path)
    # print('cmd_gps() analysis=' + str(analysis))

    # gps --verbose
    if 'verbose' in ret['options']:
        verbose = True
    else:
        verbose = False

    # gps --test
    if 'test' in ret['options']:
        fow_gps.test(analysis, verbose, write_path)
        return

    # gps
    else:
        fow_gps.do(analysis, True, verbose, write_path)
Esempio n. 13
0
File: main.py Progetto: chs8691/fow
def cmd_task(cmd_list):
    """
    Task manipulation.
    """

    # Command needs an existing fow.
    if not plump.is_fow():
        return

    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_none = dict(name='', short='', args=NONE_PARAM)
    atom_create = dict(name='create', short='c', args=MANDATORY_PARAM)
    atom_activate = dict(name='activate', short='a', args=MANDATORY_PARAM)
    atom_next = dict(name='next', short='n', args=NONE_PARAM)
    atom_previous = dict(name='previous', short='p', args=NONE_PARAM)
    atom_short = dict(name='short', short='s', args=NONE_PARAM)
    atom_long = dict(name='long', short='l', args=NONE_PARAM)
    atom_raw_import = dict(name='raw-import', short='r', args=NONE_PARAM)
    atom_fill_final = dict(name='fill-final', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)

    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_create, obligat=True)
                          ],
                          [
                              dict(atom=atom_activate, obligat=True)
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_short, obligat=False)
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_long, obligat=False)
                          ],
                          [
                              dict(atom=atom_next, obligat=True)
                          ],
                          [
                              dict(atom=atom_previous, obligat=True)
                          ],
                          [
                              dict(atom=atom_raw_import, obligat=True),
                              dict(atom=atom_test, obligat=False)
                          ],
                          [
                              dict(atom=atom_fill_final, obligat=True),
                              dict(atom=atom_test, obligat=False)
                          ]
                      ])

    if ret['message'] is not None:
        return

    # print("cmd_task() ret={}".format(str(ret)))

    # --- Options to change the actual task (activate or create)---#
    if 'create' in ret['options'] or 'activate' in ret['options']:
        if 'create' in ret['options']:
            path_arg = ret['options']['create']
        else:
            path_arg = ret['options']['activate']

        # arg for option '' is the path, Path may not end with '/'
        if path_arg is not None and len(path_arg) > 0 and path_arg[-1] == '/':
            path_arg = path_arg[0:-1]

        # Extract folder and task name
        if path_arg.count('/') > 2:
            print('Path too long, use [[' + plump.DIR_02 + ']/<folder>/]]<task>')
            return

        # print("cmd_task() path_arg={}".format(str(path_arg)))
        # Dictionary with all task parts
        path = dict(folder=None, task=None, ft=None, path=None)
        if path_arg.count('/') == 2:
            # print(args['args'][0])
            if not path_arg.startswith(plump.DIR_02 + '/'):
                print('Invalid path. Try [[' + plump.DIR_02 +
                      '/]<folder>/]]<task>.')
                return
            else:
                parts = path_arg.split('/')
                path['folder'] = parts[-2]
                path['task'] = parts[-1]

        elif path_arg.count('/') == 1:
            parts = path_arg.split('/')
            path['folder'] = parts[-2]
            path['task'] = parts[-1]

        else:
            path['task'] = path_arg

        # If only task is given, take the active folder
        if path['folder'] is None:
            if task.get_actual() is None:
                print('No actual task set, please specify the folder, too: ' +
                      '[[' + plump.DIR_02 + '/]<folder>/]]<task>')
                return
            path['folder'] = task.get_actual()['folder']

        # For convenience usage
        path['ft'] = path['folder'] + '/' + path['task']
        path['path'] = plump.get_path(plump.DIR_02) + '/' + path['ft']

        # task --create <task>
        if 'create' in ret['options']:
            if os.path.exists(path['path']):
                print('task ' + str(path['ft']) + ' already exists.' +
                      ' Choose a different name to create a new task.')
                return

            os.makedirs(path['path'])
            os.mkdir(path['path'] + '/' + plump.DIR_FINAL)
            os.mkdir(path['path'] + '/' + plump.DIR_JPG)
            os.mkdir(path['path'] + '/' + plump.DIR_RAW)
            os.mkdir(path['path'] + '/' + plump.DIR_WORK)
            os.mkdir(path['path'] + '/' + plump.DIR_VIDEO)
            config.set_item(plump.TASK, path['ft'])
            return

        if 'activate' in ret['options']:
            # print('path =' + str(path))
            if not os.path.exists(path['path']):
                print('task ' + str(path['ft']) + ' does not exist.' +
                      ' To create a new task use "task --create [<folder>/]<task>"')
                return

            config.set_item(plump.TASK, path['ft'])
            return

    # --- Options for the actual task ---#

    # task --short
    # task
    # task --long
    if 'short' in ret['options'] or 'long' in ret['options'] or len(ret['options']) == 1:
        if task.get_actual() is None:
            print('No actual task. ' +
                  'Use "task --create <task>" to create one.')
        else:
            if 'short' in ret['options']:
                print('Actual task {}. Showing a summary.'.format(task.get_actual()['task']))
                show.task_summary(
                    plump.get_path(plump.DIR_02) + '/'
                    + task.get_actual()['task'])
            elif 'long' in ret['options']:
                print('Actual task is {}. Listing all image files.'.format(task.get_actual()['task']))
                show.show_task(
                    plump.get_path(plump.DIR_02) + '/'
                    + task.get_actual()['task'], False)
            else:
                print('Actual task is {}. Listing image files in final.'.format(task.get_actual()['task']))
                show.show_task(plump.get_path(plump.DIR_02) + '/'
                               + task.get_actual()['task'], True)
        return

    # task --raw-import
    # task --raw-import --test
    if 'raw-import' in ret['options']:
        if task.get_actual() is None:
            print('No actual task set, please specify the folder, too: ' +
                  '[' + plump.get_path(plump.DIR_02) + '/]<folder>/<task>')
            return

        task.move_corresponding_raws(
            plump.get_path(plump.DIR_02) + '/'
            + task.get_actual()['task']
            + '/' + plump.DIR_JPG,
            plump.get_path(plump.DIR_01) + '/' + plump.DIR_RAW,
            plump.get_path(plump.DIR_02) + '/' + task.get_actual()['task']
            + '/' + plump.DIR_RAW, 'test' in ret['options'])
        return

    # task --fill-final
    # task --fill-final --test
    if 'fill-final' in ret['options']:
        if task.get_actual() is None:
            print('No actual task set, please specify the folder, too: ' +
                  '[' + plump.get_path(plump.DIR_02) + '/]<folder>/<task>')
            return

        plump.copy_missing_jpgs(
            plump.get_path(plump.DIR_02) + '/' +
            task.get_actual()['task']
            + '/' + plump.DIR_JPG,
            plump.get_path(plump.DIR_02) + '/' +
            task.get_actual()['task']
            + '/' + plump.DIR_FINAL,
            'test' in ret['options'])
        return

    # task --next
    # task --previous
    if 'next' in ret['options'] or 'previous' in ret['options']:
        if 'previous' in ret['options']:
            offset = -1
        else:
            offset = 1
        old_triple = task.get_task_triple(offset)
        if old_triple is None:
            print('No actual task found.')
            return

        if old_triple['p_task'] is None:
            print('Seems to be only one task. Switching not possible.')
            return

        config.set_item(plump.TASK,
                        '{0}/{1}'.format(old_triple['a_task']['subdir'],
                                         old_triple['a_task']['task']))

        new_triple = task.get_task_triple(0)

        print('   {0}/{1}'.format(str(new_triple['p_task']['subdir']),
                                  str(new_triple['p_task']['task'])))
        print('*  {0}/{1}'.format(str(new_triple['a_task']['subdir']),
                                  str(new_triple['a_task']['task'])))
        print('   {0}/{1}'.format(str(new_triple['n_task']['subdir']),
                                  str(new_triple['n_task']['task'])))
        return
Esempio n. 14
0
File: main.py Progetto: chs8691/fow
def cmd_export(cmd_list):
    """
    Copy finals to external destinations.
    """
    # 0: No param allowed, 1: param optional, 2: param obligatory
    # if not checkArgs(_arg_dict,
    #    {'-t': 0, '--test': 0, '-p': 2, '--path': 2}):
    #    return
    atom_path = dict(name='path', short='p', args=MANDATORY_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_test = dict(name='test', short='t', args=NONE_PARAM)
    atom_none = dict(name='', short='', args=MANDATORY_PARAM)

    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_path, obligat=True),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_test, obligat=False)
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_test, obligat=False)
                          ]
                      ])

    if ret['message'] is not None:
        return

    # Get destination
    if 'path' in ret['options']:
        destination = ret['options']['path']
    else:
        try:
            destination = config.read_pickle()[plump.EXPORT_PREFIX + '.' + ret['options']['']]
        except:
            print("Destination value not defined. Create it with config -s='export.{}' first."
                  .format(ret['options']['']))
            return

    if destination is None:
        print('Destination not valid. See "help export".')
        return

    # Extract task specific subdirectory {1} or {2}, if given
    m = re.compile('(.*)(/{[12]}/?)').match(destination)

    # Direct path
    if m is None:
        if not os.path.exists(destination):
            print('Destination directory not reachable: ' + destination)
            return

    # Task specific path
    else:
        root_dir = m.group(1)
        if os.path.exists(m.group(1)):
            # Resolve subdirectory placeholder: task name
            if destination.endswith(('{1}', '{1}/')):
                destination = root_dir + '/' + task.get_actual()['name']
            # Resolve subdirectory placeholder: folder + task name
            elif destination.endswith(('{2}', '{2}/')):
                destination = root_dir + '/' + task.get_actual()['task']
        else:
            print('Destination root directory not reachable: ' + root_dir)
            return

    print('destination={}'.format(destination))
    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)
    files = plump.list_jpg(src_path)

    # [dict(name='image001.jpg', exists='true')]
    analysis = export.analyse(task.get_actual(), destination)
    if 'test' in ret['options']:
        export.test(analysis, src_dir, destination)
        return

    # export --force
    if 'force' in ret['options']:
        print(str(len(files)) + ' images in ' + task.get_actual()['task']
              + '/' + plump.DIR_FINAL)
        print('Destination: ' + destination)
        export.copy(analysis, src_path, destination)

    # export
    else:
        exists = False
        for item in analysis:
            if item['exists']:
                exists = True
        if exists:
            print('Files would be overwritten! ' +
                  'Use --test to list the file(s) ' +
                  'or use --force to overwrite the image(s). ')
        else:
            print(str(len(files)) + ' images in ' + task.get_actual()['task']
                  + '/' + plump.DIR_FINAL)
            print('Destination: ' + destination)
            export.copy(analysis, src_path, destination)
Esempio n. 15
0
File: main.py Progetto: chs8691/fow
def cmd_exif(cmd_list):
    """
    Set exif values
    """
    atom_none = dict(name='', short='', args=OPTIONAL_PARAM)
    atom_title = dict(name='title', short='t', args=MANDATORY_PARAM)
    atom_description = dict(name='description', short='d', args=MANDATORY_PARAM)
    atom_author = dict(name='author', short='a', args=NONE_PARAM)
    atom_check = dict(name='check', short='c', args=NONE_PARAM)
    atom_force = dict(name='force', short='f', args=NONE_PARAM)
    atom_verbose = dict(name='verbose', short='v', args=NONE_PARAM)

    # If none has an optional parameter, no other option in the same rule should have an optional parameter, too.
    ret = check_rules(cmd_list,
                      [
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_verbose, obligat=False),
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_title, obligat=True),
                              dict(atom=atom_description, obligat=False),
                              dict(atom=atom_author, obligat=False),
                              dict(atom=atom_check, obligat=False),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_verbose, obligat=False),
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_title, obligat=False),
                              dict(atom=atom_description, obligat=True),
                              dict(atom=atom_author, obligat=False),
                              dict(atom=atom_check, obligat=False),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_verbose, obligat=False),
                          ],
                          [
                              dict(atom=atom_none, obligat=True),
                              dict(atom=atom_title, obligat=False),
                              dict(atom=atom_description, obligat=False),
                              dict(atom=atom_author, obligat=True),
                              dict(atom=atom_check, obligat=False),
                              dict(atom=atom_force, obligat=False),
                              dict(atom=atom_verbose, obligat=False),
                          ]
                      ])

    if ret['message'] is not None:
        return

    # Get author
    if 'author' in ret['options']:
        try:
            author = config.read_pickle()["{}.{}".format(plump.EXIF_PREFIX, 'author')]
            if len(str(author)) == 0:
                print("Destination value not defined. Create it with config -s '{}.author=<value>' first."
                      .format(plump.EXIF_PREFIX))
                return
            # Replace year
            author = author.replace("{YYYY}", str(datetime.now().year))

        except (TypeError, KeyError):
            print("xDestination value not defined. Create it with config -s '{}.author=<value>' first."
                  .format(plump.EXIF_PREFIX))
            return
    else:
        author = None

    if not task.check_actual():
        return

    src_dir = task.get_actual()['task'] + '/' + plump.DIR_FINAL
    src_path = task.get_task_path(src_dir)

    # None, '*', 1,2,3 or a file name
    files = fow_exif.check_images(src_path, ret['options'][''])
    # print("cmd_exif() files={}".format(str(files)))
    if files is None:
        print("No images found")
        return

    if 'title' in ret['options']:
        title = ret['options']['title']
    else:
        title = None

    if 'description' in ret['options']:
        description = ret['options']['description']
    else:
        description = None

    analysis = fow_exif.analyse(src_path, files, title, description, author)

    # print("cmd_exif() value=" + str(analysis))

    if title is None and description is None and author is None:
        fow_exif.show(analysis, src_dir, 'verbose' in ret['options'])
        return

    if 'check' in ret['options']:
        fow_exif.test(analysis, src_dir, title is not None, description is not None, author is not None,
                      'force' in ret['options'], 'verbose' in ret['options'])
        return

    # exif --force
    if 'force' not in ret['options']:
        overwritten_tags = [a for a in analysis if a['title']['overwrite'] or a['description']['overwrite']
                            or a['author']['overwrite']]
        if len(overwritten_tags) > 0:
            print("Value(s) would be overwritten, use --force to to this.")
            return

    # Do it!
    fow_exif.do(analysis, src_path, title is not None, description is not None, author is not None,
                'verbose' in ret['options'])