diff --git a/scripts/python/README.md b/scripts/python/README.md index 361e068d..3f74edbc 100644 --- a/scripts/python/README.md +++ b/scripts/python/README.md @@ -48,14 +48,16 @@ the heading with the keyword name. ## Changing the status of a keyword in Appendix A -To change the status color of a keyword in the status column in the alphabetical listing of keywords -in Appendix A, run for example: +To change the status of a keyword in the status column in the alphabetical listing +of keywords in Appendix A, run for example: ``` -$ fodt-set-ketword-status --keyword=CSKIN --color=green +$ fodt-set-keyword-status --keyword=CSKIN --color=green --opm-flow ``` -this will change the color from orange to green. +this will change the color from orange to green and add the text "OPM Flow" to indicate +that the keyword is specific to OPM flow. If the keyword is not specific to OPM flow, +just omit the `--opm-flow` flag. ## Submitting a PR for a change to a `.fodt` file diff --git a/scripts/python/src/fodt/add_keyword_status.py b/scripts/python/src/fodt/add_keyword_status.py index c9bfe19a..4f8586fb 100644 --- a/scripts/python/src/fodt/add_keyword_status.py +++ b/scripts/python/src/fodt/add_keyword_status.py @@ -20,23 +20,41 @@ from fodt.constants import ClickOptions, Directories, FileExtensions, KeywordStatus from fodt.xml_helpers import XMLHelper -class AppendixStatusColorHandler(xml.sax.handler.ContentHandler): - def __init__(self, keyword: str, status: KeywordStatus) -> None: +class AppendixKeywordHandler(xml.sax.handler.ContentHandler): + def __init__(self, keyword: str, status: KeywordStatus, opm_flow: bool) -> None: self.keyword = keyword self.status = status + self.opm_flow = opm_flow self.in_section = False self.in_table_row = False self.in_table_cell = False + self.in_table_cell_p = False self.current_tag_name = None self.content = io.StringIO() self.current_keyword = None - self.keyword_found = False + self.keyword_handled = False + self.found_table_cell = False self.office_body_found = False self.in_table_cell_style = False self.orange_styles = set() self.green_styles = set() + self.start_tag_open = False # For empty tags, do not close with /> def characters(self, content: str): + if self.start_tag_open: + # NOTE: characters() is only called if there is content between the start + # tag and the end tag. If there is no content, characters() is not called. + self.content.write(">") + self.start_tag_open = False + if self.in_table_cell_p: + if self.opm_flow: + content = "OPM Flow" + else: + content = "" + self.keyword_handled = True + self.current_keyword = None + self.in_table_cell_p = False + self.found_table_cell = False self.content.write(XMLHelper.escape(content)) def collect_table_cell_styles(self, attrs: xml.sax.xmlreader.AttributesImpl) -> None: @@ -58,14 +76,27 @@ def collect_table_cell_styles(self, attrs: xml.sax.xmlreader.AttributesImpl) -> def endElement(self, name: str): - if not self.keyword_found: + if not self.keyword_handled: if name == "table:table-row": self.in_table_row = False elif self.in_table_row and name == "table:table-cell": self.in_table_cell = False elif self.in_table_cell_style and name == "style:style": self.in_table_cell_style = False - self.content.write(XMLHelper.endtag(name)) + if self.in_table_cell_p and name == "text:p" and self.start_tag_open and self.opm_flow: + self.content.write(">") + self.start_tag_open = False + content = "OPM Flow" + self.keyword_handled = True + self.current_keyword = None + self.in_table_cell_p = False + self.found_table_cell = False + self.content.write(XMLHelper.escape(content)) + if self.start_tag_open: + self.content.write("/>") + self.start_tag_open = False + else: + self.content.write(XMLHelper.endtag(name)) def get_content(self) -> str: return self.content.getvalue() @@ -81,6 +112,7 @@ def handle_table_row( self.in_table_row = True self.current_keyword = None elif self.in_table_row and name == 'table:table-cell': + self.in_table_cell = True if (self.current_keyword is not None) and self.current_keyword == self.keyword: logging.info(f"Found keyword {self.keyword}.") # We have already found the keyword name within this table row @@ -93,11 +125,7 @@ def handle_table_row( else: raise ValueError(f"Invalid status value: {self.status}.") logging.info(f"Successfully changed status of keyword {self.keyword}.") - self.current_keyword = None - self.in_table_cell = False - self.keyword_found = True - else: - self.in_table_cell = True + self.found_table_cell = True elif self.in_table_cell and name == 'text:a': if "xlink:href" in attrs.getNames(): href = attrs.getValue("xlink:href") @@ -105,6 +133,11 @@ def handle_table_row( # we want to extract the keyword name from this string if match := re.match(r"#\d+.\d+.\d+.(\w+)\s+", href): self.current_keyword = match.group(1) + elif self.in_table_cell and name == 'text:p': + if self.found_table_cell: + logging.info(f"Found text:p element for keyword {self.keyword}.") + # replace the content of the text:p element with the new status + self.in_table_cell_p = True return attrs def select_table_cell_styles(self) -> None: @@ -128,7 +161,10 @@ def startDocument(self): self.content.write(XMLHelper.header) def startElement(self, name:str, attrs: xml.sax.xmlreader.AttributesImpl): - if not self.keyword_found: + if self.start_tag_open: + self.content.write(">") # Close the start tag + self.start_tag_open = False + if not self.keyword_handled: if not self.office_body_found: if name == 'style:style': if "style:family" in attrs.getNames(): @@ -143,14 +179,18 @@ def startElement(self, name:str, attrs: xml.sax.xmlreader.AttributesImpl): self.office_body_found = True else: attrs = self.handle_table_row(name, attrs) - self.content.write(XMLHelper.starttag(name, attrs)) + self.start_tag_open = True + self.content.write(XMLHelper.starttag(name, attrs, close_tag=False)) class UpdateKeywordStatus: - def __init__(self, maindir: str, keyword: str, status: KeywordStatus) -> None: + def __init__( + self, maindir: str, keyword: str, status: KeywordStatus, opm_flow: bool + ) -> None: self.keyword = keyword self.status = status self.maindir = maindir + self.opm_flow = opm_flow def update(self) -> None: self.filename = Path(self.maindir) / Directories.appendices / f"A.{FileExtensions.fodt}" @@ -158,10 +198,10 @@ def update(self) -> None: raise FileNotFoundError(f"File {self.filename} not found.") # parse the xml file parser = xml.sax.make_parser() - handler = AppendixStatusColorHandler(self.keyword, self.status) + handler = AppendixKeywordHandler(self.keyword, self.status, self.opm_flow) parser.setContentHandler(handler) parser.parse(self.filename) - if handler.keyword_found: + if handler.keyword_handled: # Take a backup of the file tempfile_ = tempfile.mktemp() shutil.copy(self.filename, tempfile_) @@ -176,16 +216,22 @@ def update(self) -> None: @click.command() @ClickOptions.maindir(required=False) @click.option("--keyword", type=str, required=True, help="Keyword to change status for.") -@click.option("--status", type=str, required=True, help="New status for keyword.") -def set_keyword_status(maindir: str, keyword: str, status: str) -> None: +@click.option("--color", type=str, required=True, help="New status color for keyword.") +@click.option("--opm-flow", type=bool, default=False, is_flag=True, help="Flow specific keyword") +def set_keyword_status( + maindir: str, + keyword: str, + color: str, + opm_flow: bool +) -> None: """Change the status of a keyword in Appendix A.""" logging.basicConfig(level=logging.INFO) try: - status = KeywordStatus[status.upper()] + color = KeywordStatus[color.upper()] except ValueError: raise ValueError(f"Invalid status value: {status}.") - logging.info(f"Setting status of keyword {keyword} to {status}.") - UpdateKeywordStatus(maindir, keyword, status).update() + logging.info(f"Updating parameters for keyword {keyword}: Color: {color}, flow-specific keyword: {opm_flow}.") + UpdateKeywordStatus(maindir, keyword, color, opm_flow).update() if "__name__" == "__main__": set_keyword_status() \ No newline at end of file