Add list data only flag
With the -r flag data will only be read from the XMP files and printed out and no other action (LR lookup, Maps lookup) is performed
This commit is contained in:
@@ -26,7 +26,7 @@ reverse_geolocate.py [-h] -x
|
||||
[-l LIGHTROOM FOLDER] [-s]
|
||||
[-f <overwrite, location, city, state, country, countrycode>]
|
||||
[-g GOOGLE API KEY] [-o] [-e EMIL ADDRESS] [-w]
|
||||
[-n] [-v] [--debug] [--test]
|
||||
[-r] [-n] [-v] [--debug] [--test]
|
||||
|
||||
### Arguments
|
||||
|
||||
@@ -40,6 +40,7 @@ Argument | Argument Value | Description
|
||||
-o, --openstreetmap | | Use OpenStreetMap instead of the default google maps
|
||||
-e, --email | email address | For OpenStreetMap with a large number of access
|
||||
-g, --google | Google Maps API Key | If available, to avoid the access limitations to the reverse location lookup
|
||||
-r, --read-only | | Read only data from the XMP files and print them out. No LR DB connection is done or any map lookups
|
||||
-w, --write-settings | | Write the Google API key or the OpenStreetMap email into the settings file
|
||||
-v, --verbose | | More verbose output. Currently not used
|
||||
--debug | | Full detailed debug output. Will print out alot of data
|
||||
|
||||
@@ -9,14 +9,11 @@
|
||||
# * all data is translated into English with long vowl system (aka ou or oo is ō)
|
||||
# MUST HAVE: Python XMP Toolkit (http://python-xmp-toolkit.readthedocs.io/)
|
||||
|
||||
import argparse
|
||||
import argparse, sqlite3, requests, configparser, textwrap
|
||||
import os, sys, re
|
||||
# Note XMPFiles does not work with sidecar files, need to read via XMPMeta
|
||||
from libxmp import XMPMeta, XMPError, consts
|
||||
import sqlite3
|
||||
import requests
|
||||
from shutil import copyfile
|
||||
import configparser
|
||||
|
||||
##############################################################
|
||||
### FUNCTIONS
|
||||
@@ -293,6 +290,12 @@ def longLatReg(longitude, latitude):
|
||||
lat_long[element] *= -1
|
||||
return lat_long
|
||||
|
||||
# wrapper calls for DMS to Lat/Long
|
||||
def convertDMStoLat(lat_long):
|
||||
return longLatReg('0,0.0N', lat_long)['latitude']
|
||||
def convertDMStoLong(lat_long):
|
||||
return longLatReg(lat_long, '0,0.0N')['longitude']
|
||||
|
||||
# METHOD: checkOverwrite
|
||||
# PARAMS: data: value field, key: XMP key, field_controls: array from args
|
||||
# RETURN: true/false
|
||||
@@ -325,6 +328,32 @@ def checkOverwrite(data, key, field_controls):
|
||||
))
|
||||
return status
|
||||
|
||||
# METHOD: shortenPath
|
||||
# PARAMS: path = string, length = int
|
||||
# RETURN: shortend path with ... in front
|
||||
# DESC : shortes a path from the left so it fits into lenght
|
||||
def shortenPath(path, length = 30):
|
||||
length = length - 3;
|
||||
if len(path) > length:
|
||||
path = "{} {}".format("..", path[len(path) - length:])
|
||||
return path;
|
||||
|
||||
# METHOD: printHeader
|
||||
# PARAMS: header string, header seperator, line counter, print header counter trigger
|
||||
# RETURN: line counter +1
|
||||
# DESC : prints header line and header seperator line
|
||||
def printHeader(header, header_seperator, lines = 0, header_line = 0):
|
||||
if lines == header_line:
|
||||
# blank line, might be used for page numbers, or other info
|
||||
print("{}".format(''))
|
||||
# print header
|
||||
print("{}".format(header))
|
||||
# print line with length of header string
|
||||
# print("{}".format('-' * len(header)))
|
||||
print("{}".format(header_seperator))
|
||||
lines += 1
|
||||
return lines
|
||||
|
||||
##############################################################
|
||||
### ARGUMENT PARSNING
|
||||
##############################################################
|
||||
@@ -398,12 +427,19 @@ parser.add_argument('-e', '--email',
|
||||
)
|
||||
|
||||
# write api/email settings to config file
|
||||
parser.add_argument('-w', '--write-seettings',
|
||||
parser.add_argument('-w', '--write-settings',
|
||||
dest = 'config_write',
|
||||
action = 'store_true',
|
||||
help = 'Write Google API or OpenStreetMap email to config file'
|
||||
)
|
||||
|
||||
# only read data and print on screen, do not write anything
|
||||
parser.add_argument('-r', '--read-only',
|
||||
dest = 'read_only',
|
||||
action = 'store_true',
|
||||
help = 'Read current values from the XMP file only, do not read from LR or lookup any data and write back'
|
||||
)
|
||||
|
||||
# Do not create backup files
|
||||
parser.add_argument('-n', '--nobackup',
|
||||
dest = 'no_xmp_backup',
|
||||
@@ -559,6 +595,7 @@ cur = ''
|
||||
# count variables
|
||||
count = {
|
||||
'all': 0,
|
||||
'read': 0,
|
||||
'map': 0,
|
||||
'cache': 0,
|
||||
'lightroom': 0,
|
||||
@@ -632,15 +669,57 @@ for xmp_file_source in args.xmp_sources:
|
||||
|
||||
if args.debug:
|
||||
print("### Work Files {}".format(work_files))
|
||||
# if we have read only we print list format style
|
||||
if args.read_only:
|
||||
# various string lengths
|
||||
format_length ={
|
||||
'filename': 40,
|
||||
'latitude': 18,
|
||||
'longitude': 18,
|
||||
'code': 4,
|
||||
'country': 20,
|
||||
'state': 20,
|
||||
'city': 25,
|
||||
'location': 30
|
||||
}
|
||||
# after how many lines do we reprint the header
|
||||
header_repeat = 40;
|
||||
# the formatted line for the output
|
||||
format_line = " {filename:<" + str(format_length['filename']) + "} | {latitude:>" + str(format_length['latitude']) + "} | {longitude:>" + str(format_length['longitude']) + "} | {code:<" + str(format_length['code']) + "} | {country:<" + str(format_length['country']) + "} | {state:<" + str(format_length['state']) + "} | {city:<" + str(format_length['city']) + "} | {location:<" + str(format_length['location']) + "} "
|
||||
# header line
|
||||
header = format_line.format(
|
||||
filename = "File",
|
||||
latitude = "Latitude",
|
||||
longitude = "Longitude",
|
||||
code = 'Code',
|
||||
country = 'Country',
|
||||
state = 'State',
|
||||
city = 'City',
|
||||
location = 'Location'
|
||||
)
|
||||
# header seperator line
|
||||
header_seperator = "{}+{}+{}+{}+{}+{}+{}+{}".format(
|
||||
'-' * (format_length['filename'] + 2),
|
||||
'-' * (format_length['latitude'] + 2),
|
||||
'-' * (format_length['longitude'] + 2),
|
||||
'-' * (format_length['code'] + 2),
|
||||
'-' * (format_length['country'] + 2),
|
||||
'-' * (format_length['state'] + 2),
|
||||
'-' * (format_length['city'] + 2),
|
||||
'-' * (format_length['location'] + 2)
|
||||
)
|
||||
# print header
|
||||
printHeader(header, header_seperator)
|
||||
# now we just loop through each file and work on them
|
||||
for xmp_file in work_files:
|
||||
if not args.read_only:
|
||||
print("---> {}: ".format(xmp_file), end = '')
|
||||
#### ACTION FLAGs
|
||||
write_file = False
|
||||
lightroom_data_ok = True
|
||||
#### LIGHTROOM DB READING
|
||||
# read in data from DB if we uave lightroom folder
|
||||
if use_lightroom:
|
||||
if use_lightroom and not args.read_only:
|
||||
# get the base file name, we need this for lightroom
|
||||
xmp_file_basename = os.path.splitext(os.path.split(xmp_file)[1])[0]
|
||||
# for strict check we need to get the full path, and add / as the LR stores the last folder with /
|
||||
@@ -676,9 +755,24 @@ for xmp_file in work_files:
|
||||
data_set[xmp_field] = xmp.get_property(xmp_fields[xmp_field], xmp_field)
|
||||
if args.debug:
|
||||
print("### => XMP: {}:{} => {}".format(xmp_fields[xmp_field], xmp_field, data_set[xmp_field]))
|
||||
if args.read_only:
|
||||
# for read only we print out the data formatted
|
||||
# headline check, do we need to print that
|
||||
count['read'] = printHeader(header, header_seperator, count['read'], header_repeat)
|
||||
# the data content
|
||||
print(format_line.format(
|
||||
filename = shortenPath(xmp_file, format_length['filename']), # shorten from the left
|
||||
latitude = str(convertDMStoLat(data_set['GPSLatitude']))[:format_length['latitude']], # cut off from the right
|
||||
longitude = str(convertDMStoLong(data_set['GPSLongitude']))[:format_length['longitude']],
|
||||
code = data_set['CountryCode'][:2].center(4), # is only 2 chars
|
||||
country = textwrap.shorten(data_set['Country'], width = format_length['country'], placeholder = '..'), # shorten from the right
|
||||
state = textwrap.shorten(data_set['State'], width = format_length['state'], placeholder = '..'),
|
||||
city = textwrap.shorten(data_set['City'], width = format_length['city'], placeholder = '..'),
|
||||
location = textwrap.shorten(data_set['Location'], width = format_length['location'], placeholder = '..')
|
||||
))
|
||||
else:
|
||||
# create a duplicate copy for later checking if something changed
|
||||
data_set_original = data_set.copy()
|
||||
|
||||
# check if LR exists and use this to compare to XMP data
|
||||
# is LR GPS and no XMP GPS => use LR and set XMP
|
||||
# same for location names
|
||||
@@ -771,23 +865,25 @@ for xmp_file in work_files:
|
||||
count['skipped'] += 1
|
||||
|
||||
# close DB connection
|
||||
lrdb.close()
|
||||
|
||||
# end stats
|
||||
print("{}".format('=' * 37))
|
||||
print("XMP Files found : {:7,}".format(count['all']))
|
||||
print("Updated : {:7,}".format(count['changed']))
|
||||
print("Skipped : {:7,}".format(count['skipped']))
|
||||
print("New GeoLocation from Map : {:7,}".format(count['map']))
|
||||
print("GeoLocation from Cache : {:7,}".format(count['cache']))
|
||||
print("Failed reverse GeoLocate : {:7,}".format(count['failed']))
|
||||
if use_lightroom:
|
||||
print("GeoLocaction from Lightroom : {:7,}".format(count['lightroom']))
|
||||
print("No Lightroom data found : {:7,}".format(count['not_found']))
|
||||
print("More than one found in LR : {:7,}".format(count['many_found']))
|
||||
# if we have failed data
|
||||
if len(failed_files) > 0:
|
||||
print("{}".format('-' * 37))
|
||||
lrdb.close()
|
||||
|
||||
# end stats only if we write
|
||||
print("{}".format('=' * 39))
|
||||
print("XMP Files found : {:9,}".format(count['all']))
|
||||
if not args.read_only:
|
||||
print("Updated : {:9,}".format(count['changed']))
|
||||
print("Skipped : {:9,}".format(count['skipped']))
|
||||
print("New GeoLocation from Map : {:9,}".format(count['map']))
|
||||
print("GeoLocation from Cache : {:9,}".format(count['cache']))
|
||||
print("Failed reverse GeoLocate : {:9,}".format(count['failed']))
|
||||
if use_lightroom:
|
||||
print("GeoLocaction from Lightroom : {:9,}".format(count['lightroom']))
|
||||
print("No Lightroom data found : {:9,}".format(count['not_found']))
|
||||
print("More than one found in LR : {:9,}".format(count['many_found']))
|
||||
# if we have failed data
|
||||
if len(failed_files) > 0:
|
||||
print("{}".format('-' * 39))
|
||||
print("Files that failed to update:")
|
||||
print("{}".format(', '.join(failed_files)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user