6 Commits

2 changed files with 155 additions and 111 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
.venv/

View File

@@ -73,7 +73,7 @@ class readable_dir(argparse.Action):
# check distance values are valid
class distance_values(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
m = re.match('^(\d+)\s?(m|km)$', values)
m = re.match(r'^(\d+)\s?(m|km)$', values)
if m:
# convert to int in meters
values = int(m.group(1))
@@ -128,7 +128,7 @@ def reverseGeolocateInit(longitude, latitude):
'error_message': ''
}
# error if long/lat is not valid
latlong_re = re.compile('^\d+\.\d+$')
latlong_re = re.compile(r'^\d+\.\d+$')
if not latlong_re.match(str(longitude)) or not latlong_re.match(str(latitude)):
geolocation['status'] = 'ERROR'
geolocation['error_message'] = 'Latitude {} or Longitude {} are not valid'.format(latitude, longitude)
@@ -201,7 +201,7 @@ def reverseGeolocateOpenStreetMap(longitude, latitude):
# dict with location, city, state, country, country code
# if not fillable, entry is empty
# SAMPLE: http://maps.googleapis.com/maps/api/geocode/json?latlng=<latitude>,<longitude>&language=<lang>&sensor=false&key=<api key>
def reverseGeolocateGoogle(longitude, latitude):
def reverseGeolocateGoogle(longitude, latitude): # noqa: C901
# init
geolocation = reverseGeolocateInit(longitude, latitude)
temp_geolocation = geolocation.copy()
@@ -238,7 +238,7 @@ def reverseGeolocateGoogle(longitude, latitude):
'CountryCode': ['country'],
'Country': ['country'],
'State': ['administrative_area_level_1', 'administrative_area_level_2'],
'City': ['locality'],
'City': ['locality', 'administrative_area_level_3'],
'Location': ['sublocality_level_1', 'sublocality_level_2', 'route'],
}
# print("Error: {}".format(response.json()['status']))
@@ -328,7 +328,7 @@ def convertLongToDMS(lat_long):
# number used in google/lr internal
def longLatReg(longitude, latitude):
# regex
latlong_re = re.compile('^(\d+),(\d+\.\d+)([NESW]{1})$')
latlong_re = re.compile(r'^(\d+),(\d+\.\d+)([NESW]{1})$')
# dict for loop
lat_long = {
'longitude': longitude,
@@ -520,7 +520,7 @@ def formatLen(string, length):
# RETURN: number found in the BK string or 0 for none
# DESC : gets the BK number for sorting in the file list
def fileSortNumber(file):
m = re.match('.*\.BK\.(\d+)\.xmp$', file)
m = re.match(r'.*\.BK\.(\d+)\.xmp$', file)
return int(m.group(1)) if m is not None else 0
@@ -644,7 +644,9 @@ parser = argparse.ArgumentParser(
# xmp folder (or folders), or file (or files)
# note that the target directory or file needs to be writeable
parser.add_argument('-i', '--include-source',
parser.add_argument(
'-i',
'--include-source',
required=True,
nargs='*',
action=writable_dir_folder,
@@ -653,7 +655,9 @@ parser.add_argument('-i', '--include-source',
help='The source folder or folders with the XMP files that need reverse geo encoding to be set. Single XMP files can be given here'
)
# exclude folders
parser.add_argument('-x', '--exclude-source',
parser.add_argument(
'-x',
'--exclude-source',
nargs='*',
action=writable_dir_folder,
dest='exclude_sources',
@@ -663,7 +667,9 @@ parser.add_argument('-x', '--exclude-source',
# LR database (base folder)
# get .lrcat file in this folder
parser.add_argument('-l', '--lightroom',
parser.add_argument(
'-l',
'--lightroom',
# required=True,
action=readable_dir,
dest='lightroom_folder',
@@ -672,7 +678,9 @@ parser.add_argument('-l', '--lightroom',
)
# strict LR check with base path next to the file base name
parser.add_argument('-s', '--strict',
parser.add_argument(
'-s',
'--strict',
dest='lightroom_strict',
action='store_true',
help='Do strict check for Lightroom files including Path in query'
@@ -682,7 +690,9 @@ parser.add_argument('-s', '--strict',
# FLAG: default: only set not filled
# other: overwrite all or overwrite if one is missing, overwrite specifc field (as defined below)
# fields: Location, City, State, Country, CountryCode
parser.add_argument('-f', '--field',
parser.add_argument(
'-f',
'--field',
action='append',
type=str.lower, # make it lowercase for check
choices=['overwrite', 'location', 'city', 'state', 'country', 'countrycode'],
@@ -694,7 +704,9 @@ parser.add_argument('-f', '--field',
'If with overwrite the field will be overwritten if already set, else it will be always skipped.'
)
parser.add_argument('-d', '--fuzzy-cache',
parser.add_argument(
'-d',
'--fuzzy-cache',
type=str.lower,
action=distance_values,
nargs='?',
@@ -707,70 +719,99 @@ parser.add_argument('-d', '--fuzzy-cache',
)
# Google Maps API key to overcome restrictions
parser.add_argument('-g', '--google',
parser.add_argument(
'-g',
'--google',
dest='google_api_key',
metavar='GOOGLE API KEY',
help='Set a Google API Maps key to overcome the default lookup limitations'
)
# use open street maps
parser.add_argument('-o', '--openstreetmap',
parser.add_argument(
'-o',
'--openstreetmap',
dest='use_openstreetmap',
action='store_true',
help='Use openstreetmap instead of Google'
)
# email of open street maps requests
parser.add_argument('-e', '--email',
parser.add_argument(
'-e',
'--email',
dest='email',
metavar='EMIL ADDRESS',
help='An email address for OpenStreetMap'
)
# write api/email settings to config file
parser.add_argument('-w', '--write-settings',
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',
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'
)
# only list unset ones
parser.add_argument('-u', '--unset-only',
parser.add_argument(
'-u',
'--unset-only',
dest='unset_only',
action='store_true',
help='Only list unset XMP files'
)
# only list unset GPS codes
parser.add_argument(
'-p',
'--unset-gps-only',
dest='unset_gps_only',
action='store_true',
help='Only list unset XMP files for GPS fields'
)
# don't try to do auto adjust in list view
parser.add_argument('-a', '--no-autoadjust',
parser.add_argument(
'-a',
'--no-autoadjust',
dest='no_autoadjust',
action='store_true',
help='Don\'t try to auto adjust columns'
)
# compact view, compresses columns down to a minimum
parser.add_argument('-c', '--compact',
parser.add_argument(
'-c',
'--compact',
dest='compact_view',
action='store_true',
help='Very compact list view'
)
# Do not create backup files
parser.add_argument('-n', '--nobackup',
parser.add_argument(
'-n',
'--nobackup',
dest='no_xmp_backup',
action='store_true',
help='Do not create a backup from the XMP file'
)
# verbose args for more detailed output
parser.add_argument('-v', '--verbose',
parser.add_argument(
'-v',
'--verbose',
action='count',
dest='verbose',
help='Set verbose output level'
@@ -837,7 +878,7 @@ if args.email and not args.use_openstreetmap:
error = True
# if email and not basic valid email (@ .)
if args.email:
if not re.match('^.+@.+\.[A-Za-z]{1,}$', args.email):
if not re.match(r'^.+@.+\.[A-Za-z]{1,}$', args.email):
print("Not a valid email for OpenStreetMap: {}".format(args.email))
error = True
# on error exit here
@@ -980,6 +1021,8 @@ if args.lightroom_folder:
cur = lrdb.cursor()
# flag that we have Lightroom DB
use_lightroom = True
if args.debug:
print("### USE Lightroom {}".format(use_lightroom))
# on error exit here
if error:
@@ -1088,7 +1131,7 @@ if args.read_only:
# ### MAIN WORK LOOP
# now we just loop through each file and work on them
for xmp_file in work_files:
for xmp_file in work_files: # noqa: C901
if not args.read_only:
print("---> {}: ".format(xmp_file), end='')
@@ -1111,7 +1154,7 @@ for xmp_file in work_files:
print("### => XMP: {}:{} => {}".format(xmp_fields[xmp_field], xmp_field, data_set[xmp_field]))
if args.read_only:
# view only if list all or if data is unset
if not args.unset_only or (args.unset_only and '' in data_set.values()):
if (not args.unset_only and not args.unset_gps_only) or (args.unset_only and '' in data_set.values()) or (args.unset_gps_only and (not data_set['GPSLatitude'] or not data_set['GPSLongitude'])):
# for read only we print out the data formatted
# headline check, do we need to print that
count['read'] = printHeader(header_line.format(page_no=page_no, page_all=page_all), count['read'], header_repeat)
@@ -1287,7 +1330,7 @@ for xmp_file in work_files:
with open(xmp_file, 'w') as fptr:
fptr.write(xmp.serialize_to_str(omit_packet_wrapper=True))
else:
print("[TEST] Would write {} ".format(data_set, xmp_file), end='')
print("[TEST] Would write {} {}".format(data_set, xmp_file), end='')
if from_cache:
print("[UPDATED FROM CACHE]")
else: