Skip to content

Commit

Permalink
Merge branch 'RuleWorld:main' into parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
cjarmstrong97 authored Sep 21, 2021
2 parents 29357ec + f34e29a commit 96e44ee
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 20 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,7 @@ Bugfix where the libroadrunner simulator object was not handled correctly.
New info subcommand, major updates to test suite, some updates to error reporting.

## 0.4.5
Early development version of a new visualize subcommand that automatically runs a visualize action on a model and returns the resulting file. New require keyword that quits if the current version is not equal to or greater than the required one.
Early development version of a new visualize subcommand that automatically runs a visualize action on a model and returns the resulting file. New require keyword that quits if the current version is not equal to or greater than the required one.

## 0.4.6
Minor bugfix for notebook template, numpy requirement removed for issue #11, fixes for issues #15, #16 and partially #21.
2 changes: 1 addition & 1 deletion bionetgen/assets/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0 4 5 alpha 0
0 4 6 alpha 0
15 changes: 10 additions & 5 deletions bionetgen/modelapi/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -541,17 +541,22 @@ class ActionBlock(ModelBlock):
def __init__(self) -> None:
super().__init__()
self.name = "actions"
AList = ActionList()
self._action_list = AList.possible_types
self.AList = ActionList()
self._action_list = self.AList.possible_types
self.items = []
self.before_model = []

def __setattr__(self, name, value) -> None:
self.__dict__[name] = value

def add_item(self, item_tpl) -> None:
name, value = item_tpl
# set the line
self.items.append(value)
# check to see if it's a before model action
if self.AList.is_before_model(name):
self.before_model.append(value)
else:
# set the line
self.items.append(value)

def __repr__(self) -> str:
# overwrites what the class representation
Expand Down Expand Up @@ -579,7 +584,7 @@ def __iter__(self):
return self.items.__iter__()

def __contains__(self, key) -> bool:
return key in self.items
return (key in self.items) or (key in [x.name for x in self.items])

def add_action(self, action_type, action_args) -> None:
"""
Expand Down
45 changes: 36 additions & 9 deletions bionetgen/modelapi/bngfile.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import bionetgen as bng
import subprocess
import os
import xmltodict
import sys
import os, re

from bionetgen.main import BioNetGen
from .utils import find_BNG_path, run_command, ActionList
Expand Down Expand Up @@ -104,14 +101,44 @@ def strip_actions(self, model_path, folder) -> str:
# open model and strip actions
with open(model_path, "r", encoding="UTF-8") as mf:
# read and strip actions
mlines = mf.readlines()
stripped_lines = filter(lambda x: self._not_action(x), mlines)
self.parsed_actions = list(
filter(lambda x: not self._not_action(x), mlines)
)
mstr = mf.read()
# TODO: Clean this up _a lot_
# this removes any new line escapes (\ \n) to continue
# to another line, so we can just remove the action lines
mstr = re.sub(r"\\\n", "", mstr)
mlines = mstr.split("\n")
stripped_lines = list(filter(lambda x: self._not_action(x), mlines))
# remove spaces, actions don't allow them
self.parsed_actions = [
x.replace(" ", "")
for x in filter(lambda x: not self._not_action(x), mlines)
]
# let's remove begin/end actions, rarely used but should be removed
remove_from = -1
remove_to = -1
for iline, line in enumerate(stripped_lines):
if re.match(r"\s*(begin)\s+(actions)\s*", line):
remove_from = iline
elif re.match(r"\s*(end)\s+(actions)\s*", line):
remove_to = iline
if remove_from > 0:
# we have a begin/end actions block
if remove_to < 0:
raise RuntimeError(
f'There is a "begin actions" statement at line {remove_from} without a matching "end actions" statement'
)
stripped_lines = (
stripped_lines[:remove_from] + stripped_lines[remove_to + 1 :]
)
if remove_to > 0:
if remove_from < 0:
raise RuntimeError(
f'There is an "end actions" statement at line {remove_to} without a matching "begin actions" statement'
)
# TODO: read stripped lines and store the actions
# open new file and write just the model
stripped_model = os.path.join(folder, model_file)
stripped_lines = [x + "\n" for x in stripped_lines]
with open(stripped_model, "w") as sf:
sf.writelines(stripped_lines)
return stripped_model
Expand Down
8 changes: 6 additions & 2 deletions bionetgen/modelapi/bngparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,18 @@ def _parse_model_bngpl(self, model_obj) -> None:
with TemporaryFile("w+") as xml_file:
if self.bngfile.generate_xml(xml_file):
# TODO: Add verbosity option to the library
# print("Parsing")
self.parse_xml(xml_file.read(), model_obj)
xmlstr = xml_file.read()
# < is not a valid XML character, we need to replace it
xmlstr = xmlstr.replace('relation="<', 'relation="&lt;')
self.parse_xml(xmlstr, model_obj)
model_obj.reset_compilation_tags()
else:
raise ValueError("XML file couldn't be generated")
elif model_file.endswith(".xml"):
with open(model_file, "r") as f:
xml_str = f.read()
# < is not a valid XML character, we need to replace it
xmlstr = xml_str.replace('relation="<', 'relation="&lt;')
self.parse_xml(xml_str, model_obj)
model_obj.reset_compilation_tags()
else:
Expand Down
9 changes: 8 additions & 1 deletion bionetgen/modelapi/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,14 @@ def __str__(self):
"""
write the model to str
"""
model_str = "begin model\n"
model_str = ""
# gotta check for "before model" type actions
if hasattr(self, "actions"):
ablock = getattr(self, "actions")
if len(ablock.before_model) > 0:
for baction in ablock.before_model:
model_str += str(baction) + "\n"
model_str += "begin model\n"
for block in self.block_order:
# ensure we didn't get new items into a
# previously inactive block, if we did
Expand Down
11 changes: 11 additions & 0 deletions bionetgen/modelapi/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ def __init__(self):
"resetConcentrations",
"resetParameters",
]
self.before_model = [
"setModelName",
"substanceUnits",
"version",
"setOption",
]
self.possible_types = (
self.normal_types + self.no_setter_syntax + self.square_braces
)
Expand Down Expand Up @@ -389,6 +395,11 @@ def __init__(self):
self.arg_dict["resetConcentrations"] = []
self.arg_dict["resetParameters"] = []

def is_before_model(self, action_name):
if action_name in self.before_model:
return True
return False


def find_BNG_path(BNGPATH=None):
"""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_bionetgen.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def test_action_loading():
# tests a BNGL file containing all BNG actions
all_action_model = os.path.join(*[tfold, "models", "actions", "all_actions.bngl"])
m1 = bng.bngmodel(all_action_model)
assert len(m1.actions) == 29
assert len(m1.actions) + len(m1.actions.before_model) == 29

no_action_model = os.path.join(*[tfold, "models", "actions", "no_actions.bngl"])
m2 = bng.bngmodel(no_action_model)
Expand Down

0 comments on commit 96e44ee

Please sign in to comment.