Omaha #4781: Make improvements to spell checker.

Change-Id: I8e5c951166308ae06f0371711144ee12f8ec8b17

Former-commit-id: f473c8ba23b01cdb43be88bedb6c5bf83c2a196b
This commit is contained in:
David Gillingham 2015-09-01 14:10:07 -05:00 committed by Gerrit Code Review
parent c94adfbac9
commit c2ec09be70
6 changed files with 361 additions and 179 deletions

View file

@ -20,9 +20,10 @@
package com.raytheon.uf.viz.spellchecker.dialogs;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
@ -64,11 +65,11 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.localization.SaveableOutputStream;
import com.raytheon.uf.common.localization.exception.LocalizationException;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.viz.spellchecker.jobs.SpellCheckJob;
/**
@ -84,6 +85,9 @@ import com.raytheon.uf.viz.spellchecker.jobs.SpellCheckJob;
* 10/23/2014 #3685 randerso Changes to support mixed case
* 10/30/2014 #16693 lshi Add more swear words to the filter
* 03/30/2015 #4344 dgilling Make bad word filter configurable.
* 08/31/2015 #4781 dgilling Improve handling of proper nouns in all
* caps mode, move override dictionary to
* SITE level.
*
* </pre>
*
@ -96,78 +100,13 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(SpellCheckDlg.class);
private static final Pattern DIGITS = Pattern.compile("\\d");
private static final String SPELLCHECKER = "spellchecker";
private static final String SUGGESTION_BLACKLIST_PATH = FileUtil.join(
"spellchecker", "inappropriateWords.txt");
private static final String SUGGESTION_BLACKLIST_PATH = SPELLCHECKER
+ IPathManager.SEPARATOR + "inappropriateWords.txt";
private static final Pattern COMMENT = Pattern.compile("^#");
/**
* The event handler for the check word button. It doubles as the problem
* collector for its internal SpellCheckJob.
*
* @author wldougher
*/
class CheckWord extends SelectionAdapter implements
ISpellingProblemCollector {
private SpellCheckJob wordCheckJob;
private SpellingProblem wordProblem;
/*
* If there's a spelling problem with the replacement word, save the
* fact that it was wrong and jump to the end.
*
* @see
* org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept
* (org.eclipse.ui.texteditor.spelling.SpellingProblem)
*/
@Override
public void accept(SpellingProblem problem) {
wordProblem = problem;
endCollecting();
}
/*
*
* @seeorg.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#
* beginCollecting()
*/
@Override
public void beginCollecting() {
wordProblem = null;
}
/**
* Tell the user if the replacement word is spelled correctly or not.
*
* @seeorg.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#
* endCollecting
* ()
*/
@Override
public void endCollecting() {
if (wordProblem == null) {
wordCheckLbl.setText("The word is correct");
} else {
wordCheckLbl.setText(wordProblem.getMessage());
}
}
/**
* The action taken when the check word button is clicked.
*/
@Override
public void widgetSelected(SelectionEvent evt) {
wordCheckJob = new SpellCheckJob("wordCheck");
wordCheckJob.setCollector(this);
wordCheckJob.setText(replaceWithTF.getText());
wordCheckJob.schedule();
}
}
/**
* A pattern to recognize "add to dictionary" proposals
*/
@ -189,9 +128,10 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
.getSystemColor(SWT.COLOR_RED));
/**
* The simple name of the user spelling dictionary file
* The path to the site level spelling dictionary file
*/
private static final String SPELLDICT = "spelldict";
private static final String SPELLDICT = SPELLCHECKER
+ IPathManager.SEPARATOR + "spelldict.txt";
private Button addWordBtn;
@ -260,7 +200,7 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
private boolean userDEncodingWasDefault;
private LocalizationFile userDLFile;
private LocalizationFile siteDictionary;
private String userDToRestore;
@ -268,10 +208,6 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
private Label wordCheckLbl;
private String category = "WORKSTATION";
private String source = "SPELL_CHECKER";
private boolean sentenceWasDefault;
private boolean sentenceToRestore;
@ -290,39 +226,24 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
private Collection<String> suggestionsBlacklist;
private final boolean isMixedCase;
/**
* Constructor.
*
* @param parent
* Parent shell.
* @param styledTest
* control containing the text to spell check
*/
public SpellCheckDlg(Shell parent, StyledText styledText) {
super(parent, SWT.NONE);
this.styledText = styledText;
init();
}
/**
* Constructor. This version allows the client to pass in the category and
* source used for message posting.
*
* @param parent
* the parent shell
* @param styledText
* control containing the text to spell check
* @param category
* Alert VIZ category
* @param source
* Alert VIZ source
* @param isMixedCase
* whether or not this product is in mixed case mode.
*/
public SpellCheckDlg(Shell parent, StyledText styledText, String category,
String source) {
public SpellCheckDlg(Shell parent, StyledText styledText,
boolean isMixedCase) {
super(parent, SWT.NONE);
this.styledText = styledText;
this.category = category;
this.source = source;
this.isMixedCase = isMixedCase;
this.siteDictionary = getAdditionalDictionary();
init();
}
@ -402,14 +323,28 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
return;
}
/* skip any locked text ranges */
StyleRange styleRange = styledText.getStyleRangeAtOffset(problem
.getOffset());
if ((styleRange != null) && (!styleRange.isUnstyled())
&& (!styleRange.similarTo(REDSTYLE))) {
scanForErrors();
return;
}
/* skip any word we set to ignore */
styledText.setSelectionRange(problem.getOffset(), problem.getLength());
String badWord = styledText.getSelectionText();
if (ignoreAll.contains(badWord)) {
scanForErrors();
return;
}
this.problem = problem;
addWordProposal = null;
styledText.setSelectionRange(problem.getOffset(), problem.getLength());
styledText.showSelection();
String badWord = styledText.getSelectionText();
misspelledLbl.setText(badWord);
java.util.List<String> suggestions = new ArrayList<>();
boolean foundProperNoun = false;
ICompletionProposal[] proposals = problem.getProposals();
if ((proposals != null) && (proposals.length > 0)) {
for (ICompletionProposal proposal : proposals) {
@ -417,9 +352,22 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
Matcher pdMatch = CHANGE_TO.matcher(pdString);
if (pdMatch.matches()) {
String replString = pdMatch.group(1);
/*
* To prevent improperly flagging proper nouns in all caps
* mode, we'll assume that if the spell checker suggests the
* same spelling but a different case that the word is
* correct and scan ahead for the next spelling mistake.
*/
if ((!isMixedCase)
&& (badWord.equalsIgnoreCase(replString))) {
foundProperNoun = true;
break;
}
if (!suggestionsBlacklist
.contains(replString.toUpperCase())) {
suggestionList.add(replString);
suggestions.add(replString);
}
}
Matcher addMatch = ADD_TO.matcher(pdString);
@ -427,42 +375,33 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
addWordProposal = proposal;
}
}
if (suggestionList.getItemCount() > 0) {
suggestionList.select(0);
replaceWithTF.setText(suggestionList.getItem(0));
}
}
StyleRange styleRange = styledText.getStyleRangeAtOffset(problem
.getOffset());
if ((styleRange == null) || styleRange.isUnstyled()
|| styleRange.similarTo(REDSTYLE)) {
if (ignoreAll.contains(badWord)) {
scanForErrors();
} else {
replaceBtn.setEnabled(true);
ignoreBtn.setEnabled(true);
if (addWordProposal != null) {
addWordBtn.setEnabled(true);
}
replaceAllBtn.setEnabled(true);
ignoreAllBtn.setEnabled(true);
checkWordBtn.setEnabled(true);
}
} else { // skip locked text ranges
if (foundProperNoun) {
scanForErrors();
return;
}
// Skip "misspellings" that contain numbers. I use Matcher here because
// for some reason, Eclipse's spell checker API's preference for this
// does absolutely nothing.
// TODO: Remove this code when Eclipse spell checking properly respects
// PreferenceConstants.SPELLING_IGNORE_DIGITS
Matcher containsDigits = DIGITS.matcher(badWord);
if (containsDigits.find()) {
scanForErrors();
/*
* We have an actual spelling error to present to the user, so now let's
* update all the UI.
*/
misspelledLbl.setText(badWord);
suggestionList.setItems(suggestions.toArray(new String[0]));
if (suggestionList.getItemCount() > 0) {
suggestionList.select(0);
replaceWithTF.setText(suggestionList.getItem(0));
}
styledText.showSelection();
replaceBtn.setEnabled(true);
ignoreBtn.setEnabled(true);
if (addWordProposal != null) {
addWordBtn.setEnabled(true);
}
replaceAllBtn.setEnabled(true);
ignoreAllBtn.setEnabled(true);
checkWordBtn.setEnabled(true);
}
/*
@ -646,7 +585,20 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
IDocument dummyDoc = new Document();
addWordProposal.apply(dummyDoc);
try {
userDLFile.save();
/*
* TODO how will this work in later iterations of the
* Localization API? Right now the eclipse internal spell
* checker engine controls reads/writes to our locally
* cached version of the file. We call save here to send the
* updated file up to the localization store.
*
* Probably need to consider sub-classing the eclipse spell
* checker in a way that allows us to control writes to the
* localization files to prevent potential collision issues
* with multiple users trying to update the SITE-level
* dictionary.
*/
siteDictionary.save();
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"Error saving user dictionary", e);
@ -926,44 +878,113 @@ public class SpellCheckDlg extends Dialog implements ISpellingProblemCollector {
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_MIXED, false);
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_UPPER, false);
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_SENTENCE, true);
// In SpellCheckDlg.accept() above, we do the work of this preference,
// since the spell checker will still return errors that contain digits.
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_DIGITS, true);
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_DIGITS, false);
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_NON_LETTERS, true);
xstore.setValue(PreferenceConstants.SPELLING_IGNORE_SINGLE_LETTERS,
true);
// Find/create the user dictionary
// Since eclipse doesn't support more than a master and user dictionary,
// we have a master user dictionary template which contains common words
// not in our master dictionary.
IPathManager pathManager = PathManagerFactory.getPathManager();
LocalizationContext ctx = pathManager.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.USER);
userDLFile = pathManager.getLocalizationFile(ctx, SPELLDICT);
if (!userDLFile.exists()) {
File userDFile = userDLFile.getFile();
if (!userDFile.exists()) {
try {
userDFile.createNewFile();
LocalizationFile defaultDLFile = pathManager
.getLocalizationFile(pathManager.getContext(
LocalizationType.CAVE_STATIC,
LocalizationLevel.BASE), SPELLDICT);
FileUtil.copyFile(defaultDLFile.getFile(), userDFile);
userDLFile.save();
} catch (IOException e) {
statusHandler.handle(Priority.PROBLEM,
"Error creating user dictionary", e);
} catch (LocalizationException e) {
statusHandler.handle(Priority.PROBLEM,
"Error creating user dictionary", e);
}
}
}
String pathSpec = userDLFile.getFile().getAbsolutePath();
xstore.setValue(PreferenceConstants.SPELLING_USER_DICTIONARY, pathSpec);
xstore.setValue(PreferenceConstants.SPELLING_USER_DICTIONARY,
siteDictionary.getFile().getAbsolutePath());
xstore.setValue(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING,
DICTIONARY_ENCODING);
}
private LocalizationFile getAdditionalDictionary() {
/*
* Since eclipse doesn't support more than a master and user dictionary,
* we have a master user dictionary template (which we install at SITE
* level) which contains common words not in our master dictionary.
*/
IPathManager pathManager = PathManagerFactory.getPathManager();
LocalizationContext siteCtx = pathManager.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.SITE);
LocalizationFile siteDictionary = pathManager.getLocalizationFile(
siteCtx, SPELLDICT);
if (!siteDictionary.exists()) {
LocalizationContext baseCtx = pathManager.getContext(
LocalizationType.CAVE_STATIC, LocalizationLevel.BASE);
LocalizationFile dictionaryTemplate = pathManager
.getLocalizationFile(baseCtx, SPELLDICT);
try (SaveableOutputStream outStream = siteDictionary
.openOutputStream();
InputStream inStream = dictionaryTemplate.openInputStream()) {
byte[] copyBuffer = new byte[4096];
while (inStream.available() > 0) {
int bytesRead = inStream.read(copyBuffer);
outStream.write(copyBuffer, 0, bytesRead);
}
outStream.save();
} catch (IOException | LocalizationException e) {
statusHandler.error("Error creating site spelling dictionary.",
e);
}
}
return siteDictionary;
}
/**
* The event handler for the check word button. It doubles as the problem
* collector for its internal SpellCheckJob.
*
* @author wldougher
*/
class CheckWord extends SelectionAdapter implements
ISpellingProblemCollector {
private SpellCheckJob wordCheckJob;
private SpellingProblem wordProblem;
/*
* If there's a spelling problem with the replacement word, save the
* fact that it was wrong and jump to the end.
*
* @see
* org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#accept
* (org.eclipse.ui.texteditor.spelling.SpellingProblem)
*/
@Override
public void accept(SpellingProblem problem) {
wordProblem = problem;
endCollecting();
}
/*
*
* @seeorg.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#
* beginCollecting()
*/
@Override
public void beginCollecting() {
wordProblem = null;
}
/**
* Tell the user if the replacement word is spelled correctly or not.
*
* @seeorg.eclipse.ui.texteditor.spelling.ISpellingProblemCollector#
* endCollecting
* ()
*/
@Override
public void endCollecting() {
if (wordProblem == null) {
wordCheckLbl.setText("The word is correct");
} else {
wordCheckLbl.setText(wordProblem.getMessage());
}
}
/**
* The action taken when the check word button is clicked.
*/
@Override
public void widgetSelected(SelectionEvent evt) {
wordCheckJob = new SpellCheckJob("wordCheck");
wordCheckJob.setCollector(this);
wordCheckJob.setText(replaceWithTF.getText());
wordCheckJob.schedule();
}
}
}

View file

@ -113,7 +113,6 @@ import com.raytheon.uf.viz.spellchecker.dialogs.SpellCheckDlg;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.gfe.Activator;
import com.raytheon.viz.gfe.GFEPreference;
import com.raytheon.viz.gfe.constants.StatusConstants;
import com.raytheon.viz.gfe.core.DataManager;
import com.raytheon.viz.gfe.dialogs.formatterlauncher.ConfigData.ProductStateEnum;
import com.raytheon.viz.gfe.product.ProductFileUtil;
@ -849,9 +848,8 @@ public class ProductEditorComp extends Composite implements
@Override
public void widgetSelected(SelectionEvent event) {
SpellCheckDlg spellCheckDlg = new SpellCheckDlg(parent
.getShell(), ProductEditorComp.this.getTextEditorST(),
StatusConstants.CATEGORY_GFE,
StatusConstants.SUBCATEGORY_TEXTFORMATTER);
.getShell(), getTextEditorST(), MixedCaseProductSupport
.isMixedCase(getNNNid()));
spellCheckDlg.open();
}
});

View file

@ -150,7 +150,6 @@ import com.raytheon.uf.viz.core.auth.UserController;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.notification.jobs.NotificationManagerJob;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.core.status.StatusConstants;
import com.raytheon.uf.viz.spellchecker.dialogs.SpellCheckDlg;
import com.raytheon.uf.viz.ui.menus.DiscoverMenuContributions;
import com.raytheon.viz.core.mode.CAVEMode;
@ -350,6 +349,7 @@ import com.raytheon.viz.ui.dialogs.SWTMessageBox;
* 15Jun2015 4441 randerso Unconditionally convert text to upper case for QC
* 8Jul2015 DR 15044 dhuffman Implemented tabbing and tabs to spaces.
* Aug 31, 2015 4749 njensen Changed setCloseCallback to addCloseCallback
* Sep 02, 2015 4781 dgilling Used different constructor for SpellCheckDlg.
*
* </pre>
*
@ -3993,8 +3993,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
int numberOfSpaces = (textEditor.getTabs() - caretOffsetOnLine
% textEditor.getTabs());
String spaces = "";
for (int x = 0; x < numberOfSpaces; x++)
for (int x = 0; x < numberOfSpaces; x++) {
spaces += ' ';
}
textEditor.insert(spaces);
textEditor.setCaretOffset(textEditor.getCaretOffset()
+ numberOfSpaces);
@ -6591,9 +6592,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
* Displays the spell checker dialog to initiate spell checking.
*/
private void checkSpelling() {
StdTextProduct product = getStdTextProduct();
SpellCheckDlg spellCheckDlg = new SpellCheckDlg(shell, textEditor,
StatusConstants.CATEGORY_WORKSTATION,
StatusConstants.SUBCATEGORY_CONNECTIVITY);
MixedCaseProductSupport.isMixedCase(product.getNnnid()));
spellCheckDlg.open();
}

View file

@ -0,0 +1,158 @@
#!/usr/bin/env python
import errno
import glob
import logging
import os
import shutil
import subprocess
import xml.etree.ElementTree as ET
BASH_COMMAND = ['bash', '-c']
SOURCE_COMMAND_FORMAT = 'source {} && env'
SETUP_ENV_FILE = '/awips2/edex/bin/setup.env'
USER_DICT_GLOB_PATTERN = '/awips2/edex/data/utility/cave_static/user/*/spelldict'
CAVE_STATIC_SITE_LEVEL_PATH = '/awips2/edex/data/utility/cave_static/site/'
COMMON_STATIC_SITE_LEVEL_PATH = '/awips2/edex/data/utility/common_static/site/'
EDEX_STATIC_SITE_LEVEL_PATH = '/awips2/edex/data/utility/edex_static/site/'
SVC_BU_PROPS_PATH = 'config/gfe/svcbu.properties'
USER_ROLES_PATH = 'roles/userRoles.xml'
NEW_DICT_PATH = 'spellchecker/spelldict.txt'
NEW_ROLE_ID = 'com.raytheon.localization.site/cave_static/spellchecker'
logging.basicConfig(format="%(asctime)s %(levelname)s: %(message)s",
datefmt="%H:%M:%S",
level=logging.DEBUG)
log = logging.getLogger('migrateUserSpellingDictionaries')
def createDir(dir):
try:
os.makedirs(os.path.dirname(dir))
except OSError as e:
if e.errno != errno.EEXIST:
raise
def sourceEnvFileGetVariable(envFile, variable):
cmdArray = list(BASH_COMMAND)
cmdArray.append(SOURCE_COMMAND_FORMAT.format(envFile))
output = subprocess.check_output(cmdArray)
for line in output.splitlines():
if variable in line:
tokens = line.split('=')
return tokens[1].strip()
return ''
def getSiteID():
try:
return sourceEnvFileGetVariable(SETUP_ENV_FILE, "AW_SITE_IDENTIFIER")
except subprocess.CalledProcessError as e:
log.exception("Could not process [%s].", os.path.basename(SETUP_ENV_FILE))
return ''
def getPrimarySites(awSiteID):
svcBuPropsFile = os.path.join(EDEX_STATIC_SITE_LEVEL_PATH, awSiteID, SVC_BU_PROPS_PATH)
if os.path.isfile(svcBuPropsFile):
siteList = sourceEnvFileGetVariable(svcBuPropsFile, "PRIMARY_SITES")
if siteList:
return [site.strip() for site in siteList.split(',')]
return []
def main():
log.info("Running delta script for DR 4781: migrating USER spelling dictionaries to SITE.")
userDicts = glob.glob(USER_DICT_GLOB_PATTERN)
combinedDict = set()
for userDict in userDicts:
log.info("Migrating USER-level spelling dictionary [%s].", userDict)
try:
with open(userDict, 'r') as f:
spelling_entries = f.readlines()
combinedDict = combinedDict.union(spelling_entries)
except IOError:
log.warning("Skipping USER-level spelling dictionary [%s].", userDict, exc_info=1)
siteID = getSiteID()
if not siteID:
log.error("Could not determine this server's site ID.")
log.error("Delta script failed.")
return -1
siteDictFile = os.path.join(CAVE_STATIC_SITE_LEVEL_PATH, siteID, NEW_DICT_PATH)
log.info("Writing SITE-level spelling dictionary [%s].", siteDictFile)
try:
createDir(os.path.dirname(siteDictFile))
with open(siteDictFile, 'w') as f:
f.writelines(sorted(combinedDict))
except OSError:
log.exception("Could not create SITE directory for spelling dictionary.")
log.error("Delta script failed.")
return -1
except IOError:
log.exception("Could not write SITE spelling dictionary.")
log.error("Delta script failed.")
return -1
except Exception:
log.exception("Unknown error trying to create SITE spelling dictionary.")
log.error("Delta script failed.")
return -1
log.info("Updating userRoles.xml.")
siteUserRoles = os.path.join(COMMON_STATIC_SITE_LEVEL_PATH, siteID, USER_ROLES_PATH)
if os.path.isfile(siteUserRoles):
tree = ET.parse(siteUserRoles)
root = tree.getroot()
root.set('xmlns:ns2', 'group')
newPermission = ET.SubElement(root, "permission", {'id':NEW_ROLE_ID})
users = root.findall("user")
for user in users:
if user.get("userId") == "ALL":
newUserPermission = ET.SubElement(user, "userPermission")
newUserPermission.text = NEW_ROLE_ID
roughString = ET.tostring(root, 'utf-8')
finalString = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>' + '\n' + roughString
try:
with open(siteUserRoles, 'w') as f:
f.write(finalString)
except IOError:
log.exception("Could not update SITE-level userRoles.xml.")
log.error("Delta script failed.")
return -1
except Exception:
log.exception("Unknown error trying to update SITE-level userRoles.xml.")
log.error("Delta script failed.")
return -1
gfeSites = []
try:
gfeSites = getPrimarySites(siteID)
except Exception as e:
log.exception("Could not retrieve PRIMARY_SITES setting.")
log.error("Delta script failed.")
return -1
for site in gfeSites:
gfeSiteFile = os.path.join(CAVE_STATIC_SITE_LEVEL_PATH, site, NEW_DICT_PATH)
log.info("Writing SITE-level spelling dictionary [%s].", gfeSiteFile)
try:
createDir(os.path.dirname(gfeSiteFile))
shutil.copy(siteDictFile, gfeSiteFile)
except OSError:
log.exception("Could not create SITE directory for spelling dictionary.")
log.error("Delta script failed.")
return -1
except IOError:
log.exception("Could not write SITE spelling dictionary.")
log.error("Delta script failed.")
return -1
except Exception:
log.exception("Unknown error trying to create SITE spelling dictionary.")
log.error("Delta script failed.")
return -1
log.info("Delta script complete.")
if __name__ == '__main__':
main()

View file

@ -83,6 +83,9 @@
<permission id="com.raytheon.localization.site/cave_static/aviation/avnwatch">
</permission>
<permission id="com.raytheon.localization.site/cave_static/spellchecker">
</permission>
<permission id="com.raytheon.localization.site/common_static/radar/rmr/rmrAvailableRequests.xml">
</permission>
@ -157,6 +160,7 @@
<userPermission>com.raytheon.localization.site/common_static/python/events/productgen/formats</userPermission>
<userPermission>com.raytheon.localization.site/common_static/python/events/recommenders</userPermission>
<userPermission>com.raytheon.localization.site/common_static/python/textUtilities</userPermission>
<userPermission>com.raytheon.localization.site/cave_static/spellchecker</userPermission>
</user>
</nwsRoleData>