replacetools

This module implements tools for file related string substitutions.

Module replacetools implements the following members:

  • xml_replace() Read the content of an XML template file (XMLT), apply the given replacements to its substitution markers, and write the result into an XML file with the same name but ending with xml instead of xmlt.


hydpy.exe.replacetools.xml_replace(filename: str, *, printflag: bool = True, **replacements: str)None[source]

Read the content of an XML template file (XMLT), apply the given replacements to its substitution markers, and write the result into an XML file with the same name but ending with xml instead of xmlt.

First, we write an XMLT file, containing a regular HTML comment, a readily defined element e1, and some other elements with substitutions markers. Substitution markers are HTML comments starting and ending with the | character:

>>> from hydpy import xml_replace, TestIO
>>> with TestIO():
...     with open("test1.xmlt", "w") as templatefile:
...         _ = templatefile.write(
...             "<!--a normal comment-->\n"
...             "<e1>element 1</e1>\n"
...             "<e2><!--|e2|--></e2>\n"
...             "<e3><!--|e3_|--></e3>\n"
...             "<e4><!--|e4=element 4|--></e4>\n"
...             "<e2><!--|e2|--></e2>")

Function xml_replace() can both be called within a Python session and from a command line. We start with the first type of application.

Each substitution marker must be met by a keyword argument unless it holds a default value (e4). All arguments are converted to a str object (e3). Template files can use the same substitution marker multiple times (e2):

>>> with TestIO():
...     xml_replace("test1", e2="E2", e3_=3, e4="ELEMENT 4")
template file: test1.xmlt
target file: test1.xml
replacements:
  e2 --> E2 (given argument)
  e3_ --> 3 (given argument)
  e4 --> ELEMENT 4 (given argument)
  e2 --> E2 (given argument)
>>> with TestIO():
...     with open("test1.xml") as targetfile:
...         print(targetfile.read())
<!--a normal comment-->
<e1>element 1</e1>
<e2>E2</e2>
<e3>3</e3>
<e4>ELEMENT 4</e4>
<e2>E2</e2>

Without custom values, xml_replace() applies predefined default values, if available (e4):

>>> with TestIO():
...     xml_replace("test1", e2="E2", e3_=3)    
template file: test1.xmlt
target file: test1.xml
replacements:
  e2 --> E2 (given argument)
  e3_ --> 3 (given argument)
  e4 --> element 4 (default argument)
  e2 --> E2 (given argument)
>>> with TestIO():
...     with open("test1.xml") as targetfile:
...         print(targetfile.read())
<!--a normal comment-->
<e1>element 1</e1>
<e2>E2</e2>
<e3>3</e3>
<e4>element 4</e4>
<e2>E2</e2>

Missing and useless keyword arguments result in errors:

>>> with TestIO():
...     xml_replace("test1", e2="E2")
Traceback (most recent call last):
...
RuntimeError: While trying to replace the markers `e2, e3_, and e4` of the XML template file `test1.xmlt` with the available keywords `e2`, the following error occurred: Marker `e3_` cannot be replaced.
>>> with TestIO():
...     xml_replace("test1", e2="e2", e3_="E3", e4="e4", e5="e5")
Traceback (most recent call last):
...
RuntimeError: While trying to replace the markers `e2, e3_, and e4` of the XML template file `test1.xmlt` with the available keywords `e2, e3_, e4, and e5`, the following error occurred: Keyword(s) `e5` cannot be used.

Using different default values for the same substitution marker is not allowed:

>>> from hydpy import pub, TestIO, xml_replace
>>> with TestIO():
...     with open("test2.xmlt", "w") as templatefile:
...         _ = templatefile.write(
...             "<e4><!--|e4=element 4|--></e4>\n"
...             "<e4><!--|e4=ELEMENT 4|--></e4>")
>>> with TestIO():
...     xml_replace("test2", e4=4)
template file: test2.xmlt
target file: test2.xml
replacements:
  e4 --> 4 (given argument)
  e4 --> 4 (given argument)
>>> with TestIO():
...     with open("test2.xml") as targetfile:
...         print(targetfile.read())
<e4>4</e4>
<e4>4</e4>
>>> with TestIO():
...     xml_replace("test2")
Traceback (most recent call last):
...
RuntimeError: Template file `test2.xmlt` defines different default values for marker `e4`.

As mentioned above, function xml_replace() is registered as a “script function” and can thus be used via command line:

>>> pub.scriptfunctions["xml_replace"].__name__
'xml_replace'
>>> pub.scriptfunctions["xml_replace"].__module__
'hydpy.exe.replacetools'

Use script hyd to execute function xml_replace():

>>> from hydpy import run_subprocess
>>> with TestIO():
...     result = run_subprocess(
...         'hyd.py xml_replace test1 e2="Element 2" e3_=3')
template file: test1.xmlt
target file: test1.xml
replacements:
  e2 --> Element 2 (given argument)
  e3_ --> 3 (given argument)
  e4 --> element 4 (default argument)
  e2 --> Element 2 (given argument)
>>> with TestIO():
...     with open("test1.xml") as targetfile:
...         print(targetfile.read())
<!--a normal comment-->
<e1>element 1</e1>
<e2>Element 2</e2>
<e3>3</e3>
<e4>element 4</e4>
<e2>Element 2</e2>