216 lines
7.7 KiB
Python
216 lines
7.7 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Delta script to convert the ugcCitiesString to ugcCities list
|
||
|
# the wfo field is not added as it is only required for NHA and they already have it
|
||
|
#
|
||
|
|
||
|
import imp, glob, os, pprint, re, sys
|
||
|
|
||
|
AREA_DICTIONARY_PATH = "/awips2/edex/data/utility/cave_static/site/*/gfe/userPython/textUtilities/regular/*AreaDictionary.py"
|
||
|
SUFFIX = ".orig_ugcCity"
|
||
|
|
||
|
HEADER_PATTERN = re.compile("(.*\n)\s*AreaDictionary\s*=\s*{", re.MULTILINE | re.DOTALL)
|
||
|
|
||
|
SURF_HEADER = """
|
||
|
##
|
||
|
# This software was developed and / or modified by Raytheon Company,
|
||
|
# pursuant to Contract DG133W-05-CQ-1067 with the US Government.
|
||
|
#
|
||
|
# U.S. EXPORT CONTROLLED TECHNICAL DATA
|
||
|
# This software product contains export-restricted data whose
|
||
|
# export/transfer/disclosure is restricted by U.S. law. Dissemination
|
||
|
# to non-U.S. persons whether in the United States or abroad requires
|
||
|
# an export license or other authorization.
|
||
|
#
|
||
|
# Contractor Name: Raytheon Company
|
||
|
# Contractor Address: 6825 Pine Street, Suite 340
|
||
|
# Mail Stop B8
|
||
|
# Omaha, NE 68106
|
||
|
# 402.291.0100
|
||
|
#
|
||
|
# See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||
|
# further licensing information.
|
||
|
##
|
||
|
# Example using site TBW
|
||
|
#
|
||
|
# Additional Edit Areas that needed to be created:
|
||
|
#
|
||
|
# landSeaAreas:
|
||
|
# SRF_850, SRF_853, SRF_856
|
||
|
#
|
||
|
# surfAreas:
|
||
|
# NorthCoast1 (listed with FLZ139), SouthCoast (along GMZ850)
|
||
|
# NorthCoast2 (listed with FLZ142), SouthCoast (along GMZ850)
|
||
|
#
|
||
|
# TBW always runs with the same combinations:
|
||
|
# FLZ139-FLZ142-FLZ148-FLZ149
|
||
|
# FLZ050-FLZ151-FLZ155-FLZ160
|
||
|
# FLZ162-FLZ165
|
||
|
# Thus, additional entries need only be listed for at least one zone
|
||
|
# in each combination.
|
||
|
#
|
||
|
# If you want to combine zones on-the-fly, you should list additional areas
|
||
|
# for each zone and the system will take care to combine them appropriately.
|
||
|
# For example, note that the "surfAreas" are listed for both FLZ039 and FLZ042.
|
||
|
# When they are combined, the surfAreas are reported just once, as desired.
|
||
|
# ----------------------------------------------------------------------------
|
||
|
#
|
||
|
"""
|
||
|
|
||
|
STANDARD_HEADER = """
|
||
|
# ----------------------------------------------------------------------------
|
||
|
# This software is in the public domain, furnished "as is", without technical
|
||
|
# support, and with no warranty, express or implied, as to its usefulness for
|
||
|
# any purpose.
|
||
|
#
|
||
|
# AreaDictionary
|
||
|
# AreaDictionary file
|
||
|
#
|
||
|
# Author: GFE Installation Script
|
||
|
# ----------------------------------------------------------------------------
|
||
|
|
||
|
# Format:
|
||
|
# AreaDictionary = {
|
||
|
# "editArea" : {
|
||
|
# "ugcCode": "STZxxx",
|
||
|
# "ugcName": "EditAreaName",
|
||
|
# "ugcCities": ['City1', 'City2'],
|
||
|
# "ugcTimeZone": "MST7MDT",
|
||
|
# "fullStateName": "COLORADO",
|
||
|
# "partOfState": "NORTHEAST",
|
||
|
# "stateAbbr": "CO",
|
||
|
# "independentCity": 0,
|
||
|
# "locationName": "GeneralAreaName",
|
||
|
# }
|
||
|
# ...
|
||
|
# }
|
||
|
# ugcTimeZone: This field should be replace with the correct time zone
|
||
|
# for that zone. If it is different from the time zone of
|
||
|
# the local WFO, it's time zone will appear in the header of
|
||
|
# some products in parentheses.
|
||
|
# Using any other strings to define
|
||
|
# the time zone may produce undesirable results.
|
||
|
# The time zone may also be a list of time zones in case
|
||
|
# a forecast zone happens to cover an area that contains
|
||
|
# two time zones.
|
||
|
# e.g. "ugcTimeZone" : ["MST7MDT", "PST8PDT"]
|
||
|
#
|
||
|
# ugcCode: This field contains the ugc coding for this area, such as COZ023
|
||
|
#
|
||
|
# ugcName: This field contains the descriptive name for this area. It
|
||
|
# is used in various products, including Hazard products. This is
|
||
|
# the official county or zone name.
|
||
|
#
|
||
|
# locationName: This field is optional, but provides an alternate name that
|
||
|
# is used in the text of some products to describe the area. The
|
||
|
# FFA product uses this value if available.
|
||
|
#
|
||
|
# ugcCities: This field contains the list of cities for hazard and routine
|
||
|
# products.
|
||
|
#
|
||
|
# fullStateName: This field is used in hazard products to fully describe
|
||
|
# the state in which this edit area resides.
|
||
|
#
|
||
|
# partOfState: This field describes the location within a state (such as
|
||
|
# NORTHEAST) for this area. It is used in hazard products.
|
||
|
#
|
||
|
# stateAbbr: State Abbreviation for the fullStateName.
|
||
|
#
|
||
|
# independentCity: Set to 0 or 1. Some counties (FIPS coding) are actually
|
||
|
# cities. Setting the flag to 1 will instruct those formatters
|
||
|
# to mention independent cities, rather than include this "county"
|
||
|
# in the county list of the product.
|
||
|
#
|
||
|
# wfo: The wfo(s) with responsibility for the area
|
||
|
#
|
||
|
#
|
||
|
"""
|
||
|
|
||
|
pp = pprint.PrettyPrinter()
|
||
|
|
||
|
def writeAreaDictionary(header, areaDict, path):
|
||
|
|
||
|
# if header is None choose the appropriate default header
|
||
|
if header is None:
|
||
|
if os.path.basename(path) == "SurfAreaDictionary.py":
|
||
|
header = SURF_HEADER
|
||
|
else:
|
||
|
header = STANDARD_HEADER
|
||
|
|
||
|
s = header + "AreaDictionary = "+ pp.pformat(areaDict)
|
||
|
|
||
|
# if the backup file doesn't already exist create it
|
||
|
if not os.path.exists(path + SUFFIX):
|
||
|
os.rename(path, path + SUFFIX)
|
||
|
|
||
|
# write out the new file
|
||
|
with open(path, "w") as out:
|
||
|
out.write(s)
|
||
|
|
||
|
def main():
|
||
|
for path in glob.iglob(AREA_DICTIONARY_PATH):
|
||
|
# only process AreaDictionary and SurfAreaDictionary
|
||
|
if os.path.basename(path) not in ["AreaDictionary.py", "SurfAreaDictionary.py"]:
|
||
|
print "Skipping %s..." % path
|
||
|
continue
|
||
|
|
||
|
print "Processing %s..." % path
|
||
|
|
||
|
# attempt to read file contents and extract header
|
||
|
header = None
|
||
|
try:
|
||
|
with open(path, 'r') as file:
|
||
|
contents = file.read()
|
||
|
|
||
|
m = HEADER_PATTERN.match(contents)
|
||
|
if m is not None:
|
||
|
header = m.group(1)
|
||
|
except:
|
||
|
print "Unable to read header, default header will be used"
|
||
|
|
||
|
module = imp.load_source('module', path)
|
||
|
if not hasattr(module, "AreaDictionary"):
|
||
|
print "No AreaDictionary found, skipping!"
|
||
|
continue
|
||
|
|
||
|
areaDict = module.AreaDictionary
|
||
|
|
||
|
for key in areaDict:
|
||
|
entry = areaDict[key]
|
||
|
try:
|
||
|
if "ugcCityString" in entry:
|
||
|
# remove any leading or trailing whitespace
|
||
|
cityString = entry["ugcCityString"].strip()
|
||
|
|
||
|
# remove leading ...
|
||
|
if cityString.startswith("..."):
|
||
|
cityString = cityString[3:]
|
||
|
|
||
|
# remove trailing ...
|
||
|
if cityString.endswith("..."):
|
||
|
cityString = cityString[:-3]
|
||
|
|
||
|
# remove any leading or trailing whitespace again
|
||
|
cityString = cityString.strip()
|
||
|
|
||
|
# if any cities then create the ugcCities list
|
||
|
if len(cityString) > 0:
|
||
|
cityList = cityString.split("...")
|
||
|
entry["ugcCities"] = cityList
|
||
|
|
||
|
# remove the old ugcCityString entry
|
||
|
del entry["ugcCityString"]
|
||
|
except:
|
||
|
print "Bad ugcCityString in %s: '%s'" % (path, cityString)
|
||
|
|
||
|
|
||
|
writeAreaDictionary(header, areaDict, path)
|
||
|
|
||
|
# delete the module and anything in it's namespace
|
||
|
for x in dir(module):
|
||
|
exec "del module."+x
|
||
|
del module
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|