Skip to content

Commit

Permalink
Update pyhit from moosetools (idaholab#17989)
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen committed Jun 9, 2021
1 parent a2bdca5 commit abb500c
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 82 deletions.
48 changes: 34 additions & 14 deletions python/pyhit/pyhit.py
@@ -1,18 +1,17 @@
#* This file is part of the MOOSE framework
#* https://www.mooseframework.org
#* This file is part of MOOSETOOLS repository
#* https://www.github.com/idaholab/moosetools
#*
#* All rights reserved, see COPYRIGHT for full restrictions
#* https://github.com/idaholab/moose/blob/master/COPYRIGHT
#* https://github.com/idaholab/moosetools/blob/main/COPYRIGHT
#*
#* Licensed under LGPL 2.1, please see LICENSE for details
#* https://www.gnu.org/licenses/lgpl-2.1.html

"""Wrapper for hit parser."""
import os
import subprocess
import moosetree
from moosetools import moosetree
import hit
from mooseutils import message


class Node(moosetree.Node):
"""
Expand All @@ -31,10 +30,10 @@ def __init__(self, parent=None, hitnode=None, offset=0):
elif hitnode is None:
hitnode = hit.NewSection('')
super().__init__(parent, hitnode.path())
self.__hitnode = hitnode # hit.Node object
self.__hitblockcomment = None # hit.Comment object for this block
self.__hitparamcomments = dict() # hit.Comment objects for the parameters within this block
self.__hitoffset = offset # hit index used for inserting new hit nodes
self.__hitnode = hitnode # hit.Node object
self.__hitblockcomment = None # hit.Comment object for this block
self.__hitparamcomments = dict() # hit.Comment objects for the parameters within this block
self.__hitoffset = offset # hit index used for inserting new hit nodes
self.__reinitComments()

@property
Expand Down Expand Up @@ -221,6 +220,24 @@ def line(self, name=None, default=None):

return default

def filename(self, name=None, default=None):
"""
Return the file name for node itself or for the supplied *name*.
When the *name* is not included the file name for the beginning of the block is returned;
and when it is included the file name is returned.
When *name* is used and the parameter is not located, the *default* is returned.
"""
if name is None:
return self.__hitnode.filename()

for child in self.__hitnode.children(hit.NodeType.Field):
if child.path() == name:
return child.filename()

return default

def __getitem__(self, name):
"""
Provides operator [] access to the parameters of this node.
Expand Down Expand Up @@ -282,6 +299,7 @@ def __reinitComments(self):
self.__hitblockcomment = comment
break


def load(filename, root=None):
"""
Read and parse a HIT file given in *filename*.
Expand All @@ -296,17 +314,19 @@ def load(filename, root=None):
elif isinstance(filename, str):
content = filename
else:
message.mooseError("Unable to load the hit file ", filename)
print("Unable to load the hit file ".format(filename))

return parse(content, root, filename)


def write(filename, root):
"""
Write the supplied tree in *root* to a text file *filename*.
"""
with open(filename, 'w') as fid:
fid.write(root.render() + "\n")


def parse(content, root=None, filename=''):
"""
Parse a hit tree from a *content* string and return a `pyhit.Node` object.
Expand All @@ -317,9 +337,8 @@ def parse(content, root=None, filename=''):
"""
hit_node = hit.parse(filename, content)
hit.explode(hit_node)
root = Node(root, hit_node) if root is not None else Node(None, hit_node)
_parse_hit(root, hit_node, filename)
return root
return _parse_hit(Node(root, hit_node), hit_node, filename)


def tokenize(content, filename=''):
"""
Expand All @@ -331,6 +350,7 @@ def tokenize(content, filename=''):
"""
return hit.tokenize(filename, content)


def _parse_hit(root, hit_node, filename):
"""Internal helper for parsing HIT tree"""
offset = 0
Expand Down
21 changes: 14 additions & 7 deletions python/pyhit/tests/test_examples.py
@@ -1,27 +1,33 @@
#!/usr/bin/env python3
#* This file is part of the MOOSE framework
#* https://www.mooseframework.org
#* This file is part of MOOSETOOLS repository
#* https://www.github.com/idaholab/moosetools
#*
#* All rights reserved, see COPYRIGHT for full restrictions
#* https://github.com/idaholab/moose/blob/master/COPYRIGHT
#* https://github.com/idaholab/moosetools/blob/main/COPYRIGHT
#*
#* Licensed under LGPL 2.1, please see LICENSE for details
#* https://www.gnu.org/licenses/lgpl-2.1.html

import os
import unittest
import pyhit
from moosetools import pyhit


class TestExamples(unittest.TestCase):
def tearDown(self):
filename = 'input_modified.i'
if os.path.isfile(filename):
os.remove(filename)

def test(self):

# MOOSEDOCS:example-begin
# Load the packages
import pyhit
import moosetree
from moosetools import pyhit
from moosetools import moosetree

# Read the file
root = pyhit.load('input.i')
root = pyhit.load(os.path.join(os.path.dirname(__file__), 'input.i'))

# Locate and modify "x_max" parameter for the mesh
mesh = moosetree.find(root, func=lambda n: n.fullpath == '/Mesh/gen')
Expand All @@ -41,5 +47,6 @@ def test(self):
self.assertIn("x_max = 4", out)
self.assertIn("Changed from 3 to 4", out)


if __name__ == '__main__':
unittest.main(module=__name__, verbosity=2)
81 changes: 45 additions & 36 deletions python/pyhit/tests/test_parser.py
@@ -1,9 +1,9 @@
#!/usr/bin/env python3
#* This file is part of the MOOSE framework
#* https://www.mooseframework.org
#* This file is part of MOOSETOOLS repository
#* https://www.github.com/idaholab/moosetools
#*
#* All rights reserved, see COPYRIGHT for full restrictions
#* https://github.com/idaholab/moose/blob/master/COPYRIGHT
#* https://github.com/idaholab/moosetools/blob/main/COPYRIGHT
#*
#* Licensed under LGPL 2.1, please see LICENSE for details
#* https://www.gnu.org/licenses/lgpl-2.1.html
Expand All @@ -12,20 +12,27 @@
import unittest
import pyhit


class TestHitLoad(unittest.TestCase):
"""
Test the load function.
"""
def setUp(self):
self._cwd = os.getcwd()
os.chdir(os.path.dirname(__file__))

def tearDown(self):
os.chdir(self._cwd)

def testRender(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
out = root.render()
self.assertIn('[A]', out)
self.assertIn('param = bar', out)
self.assertIn('comment', out)

def testBasic(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')

self.assertEqual(root.children[0].name, 'A')
self.assertEqual(root.children[0]['param'], 'foo')
Expand All @@ -45,26 +52,26 @@ def testBasic(self):
self.assertEqual(child.name, gold[i])

def testIterParam(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
for k, v in root.children[0].params():
self.assertEqual(k, 'param')
self.assertEqual(v, 'foo')

def testGetParam(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
p = root.get('nope', 'default')
self.assertEqual(p, 'default')

def testAddParam(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
self.assertIsNone(root(1).get('year'))
root(1)['year'] = 1980
self.assertEqual(len(root(1)), 2)
self.assertEqual(root(1).get('year'), 1980)

def testEditParam(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
self.assertIsNone(root(1).get('year'))
root(1)['year'] = 1980
Expand All @@ -75,13 +82,13 @@ def testEditParam(self):
self.assertEqual(root(1).get('year'), 1949)

def testRemoveParam(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(root(0)['param'], 'foo')
root(0).removeParam('param')
self.assertIsNone(root(0).get('param'))

def testAppend(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
sec = root(1).append('B-3')
self.assertEqual(len(root(1)), 3)
Expand All @@ -91,7 +98,7 @@ def testAppend(self):
self.assertEqual(sec.get('year'), 1980)

def testInsert(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
sec = root(1).insert(0, 'B-3')
self.assertEqual(len(root(1)), 3)
Expand All @@ -101,61 +108,61 @@ def testInsert(self):
self.assertEqual(sec.get('year'), 1980)

def testAppendWithKwargs(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
sec = root(1).append('B-3', year=1980)
self.assertEqual(len(root(1)), 3)
self.assertEqual(sec.get('year'), 1980)

def testRemoveSection(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root), 2)
root(1).remove()
self.assertEqual(len(root), 1)

def testAddSectionWithParameters(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(len(root(1)), 2)
sec = root(1).append('B-3', year=1980)
self.assertEqual(len(root(1)), 3)
self.assertEqual(sec.get('year'), 1980)

def testComment(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertEqual(root(1).comment(), "section comment")
self.assertEqual(root(0,0).comment(), "sub-section comment")
self.assertEqual(root(1,0,0).comment('type'), "param comment")
self.assertEqual(root(0, 0).comment(), "sub-section comment")
self.assertEqual(root(1, 0, 0).comment('type'), "param comment")

def testSetComment(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
root(1).setComment('update section comment')
self.assertEqual(root(1).comment(), "update section comment")

root(0,0).setComment('update sub-section comment')
self.assertEqual(root(0,0).comment(), "update sub-section comment")
root(0, 0).setComment('update sub-section comment')
self.assertEqual(root(0, 0).comment(), "update sub-section comment")

root(1,0,0).setComment('type', 'update param comment')
self.assertEqual(root(1,0,0).comment('type'), "update param comment")
root(1, 0, 0).setComment('type', 'update param comment')
self.assertEqual(root(1, 0, 0).comment('type'), "update param comment")

def testAddComment(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')

root(0).setComment('Section A')
self.assertEqual(root(0).comment(), "Section A")

root(1,0).setComment('Section B-1')
self.assertEqual(root(1,0).comment(), "Section B-1")
root(1, 0).setComment('Section B-1')
self.assertEqual(root(1, 0).comment(), "Section B-1")

root(0,0).setComment('param', "inline comment")
self.assertEqual(root(0,0).comment('param'), "inline comment")
root(0, 0).setComment('param', "inline comment")
self.assertEqual(root(0, 0).comment('param'), "inline comment")

def testRemoveComment(self):
root = pyhit.load(os.path.join('..', '..', 'test_files', 'test.hit'))
root = pyhit.load('test.hit')
self.assertIn("type = test # param comment", root.render())
self.assertIn("# section comment", root.render())

root(1,0,0).setComment("type", None)
self.assertIsNone(root(1,0,0).comment())
root(1, 0, 0).setComment("type", None)
self.assertIsNone(root(1, 0, 0).comment())
self.assertNotIn("type = test # param comment", root.render())

root(1).setComment(None)
Expand All @@ -167,15 +174,17 @@ def testCreate(self):
bcs = root.append('BCs')
bcs.append('left', type='NeumannBC', value=1980, boundary='left')
self.assertEqual(len(root), 1)
out = root.render()
out = root.render()
self.assertIn('[BCs]', out)
self.assertIn('type = NeumannBC', out)
self.assertIn('boundary = left', out)

def testTestRoot(self):
root = pyhit.load(os.path.join('..', '..', 'testroot'))
self.assertIn('app_name', root)
self.assertEqual(root['app_name'], 'moose_python')
def testNodeLocation(self):
root = pyhit.load('test.hit')
self.assertEqual(root.children[0].line(), 1)
self.assertEqual(root.children[1].line(), 10)
self.assertEqual(root.children[0].filename(), 'test.hit')
self.assertEqual(root.children[1].filename(), 'test.hit')


if __name__ == '__main__':
Expand Down

0 comments on commit abb500c

Please sign in to comment.