Commit 815bc30d authored by Thanassis Tsiodras's avatar Thanassis Tsiodras

Moving to Python3, for good.

parents f205b620 ddd0bdf8
[flake8]
ignore = E501,E225,C103
max-line-length = 160
......@@ -4,3 +4,6 @@
tests-coverage/output
tests-coverage/smp2.asn
tests-coverage/datatypessimulink.cat
tests-coverage/datatypessimulink.pkg
tests-coverage/Simulink_DataView_asn.m
*swp
# Change Log
## 2.1.0
- Major update of the PySide B mapper (API updates)
- Bug fix in the Python A mapper
## 2.0.0
- Moved to Python3
- Added type annotations, checked via mypy
- Added git commit hooks to check via flake8 AND pylint
- Configuration files used to customize the checks for the project's
naming conventions.
- Many bugs identified and fixed.
## 1.2.3
- ctypes backend: emit all ENUMERATED values in DV.py
## 1.2.0
- Not using SWIG anymore for the Python mappers
## 1.1.2
- pyside_b_mapper: added combo box for the asn1 value editor
## 1.1.1
- support empty SEQUENCEs (MyType ::= SEQUENCE {}) - except for Simulink
PY_SRC:=$(wildcard dmt/asn2dataModel.py dmt/aadl2glueC.py dmt/smp2asn.py dmt/*mappers/[a-zA-Z]*py dmt/commonPy/[a-zA-Z]*py)
PY_SRC:=$(filter-out dmt/B_mappers/antlr.main.py dmt/A_mappers/Stubs.py, ${PY_SRC})
# Python3.5 includes an older version of typing, which by default has priority over
# the one installed in $HOME/.local via setup.py.
#
# To address this, we find where our pip-installed typing lives:
TYPING_FOLDER:=$(shell pip3 show typing | grep ^Location | sed 's,^.*: ,,')
export PYTHONPATH=${TYPING_FOLDER}
all: flake8 pylint mypy coverage
flake8:
@echo Performing syntax checks via flake8...
@flake8 ${PY_SRC} || exit 1
pylint:
@echo Performing static analysis via pylint...
@pylint --disable=I --rcfile=pylint.cfg ${PY_SRC} | grep -v '^$$' | sed -n '/^Report/q;p'
mypy:
@echo Performing type analysis via mypy...
@mypy --disallow-untyped-defs --check-untyped-defs ${PY_SRC} || exit 1
coverage:
@echo Performing coverage checks...
@$(MAKE) -C tests-coverage || exit 1
.PHONY: flake8 pylint mypy coverage
TASTE Data Modelling Technologies
=================================
[![Build and Test Status of Data Modelling Tools on Circle CI](https://circleci.com/gh/ttsiodras/DataModellingTools.svg?&style=shield&circle-token=9df10d36b6b4ccd923415a5890155b7bf54b95c5)](https://circleci.com/gh/ttsiodras/DataModellingTools/tree/master)
TASTE Data Modelling Tools
==========================
These are the tools used by the European Space Agency's [TASTE toolchain](https://taste.tuxfamily.org/)
to automate handling of the Data Modelling. They include more than two
dozen codegenerators that automatically create the 'glue'; the run-time translation
bridges that allow code generated by modelling tools (Simulink, SCADE, OpenGeode, etc)
to "speak" to one another, via ASN.1 marshalling.
For the encoders and decoders of the messages
themselves, TASTE uses [ASN1SCC](https://github.com/ttsiodras/asn1scc) - an ASN.1
compiler specifically engineered for safety-critical environments.
For more details, visit the [TASTE site](https://taste.tuxfamily.org/).
Installation
------------
For using the tools, this should suffice:
$ sudo apt-get install libxslt1-dev libxml2-dev zlib1g-dev python3-pip
$ pip3 install --user --upgrade .
For developing the tools, the packaged Makefile allow for easy static-analysis
via the dominant Python static analyzers and syntax checkers:
$ make flake8 # check for pep8 compliance
$ make pylint # static analysis with pylint
$ make mypy # type analysis with mypy
Contents
--------
What is packaged:
- **commonPy** (*library*)
Contains the basic API for parsing ASN.1 (via invocation of
[ASN1SCC](https://github.com/ttsiodras/asn1scc) and simplification
of the generated XML AST representation to the Python classes
inside `asnAST.py`.
inside `asnAST.py`. The class diagram with the AST classes
is [packaged in the code](dmt/commonPy/asnAST.py#L42).
- **asn2aadlPlus** (*utility*)
Converts the type declarations inside ASN.1 grammars to AADL
declarations (used by the Ellidiss GUI to create the final systems)
declarations, that are used by [Ocarina](https://github.com/OpenAADL/ocarina)
to generate the executable containers.
- **asn2dataModel** (*utility*)
Reads the ASN.1 specification of the exchanged messages, and generates
the semantically equivalent Modeling tool/Modeling language declarations
(e.g. SCADE/Lustre, Matlab/Simulink statements, etc).
(e.g. SCADE/Lustre, Matlab/Simulink, etc).
The actual mapping logic exists in plugins, called *A mappers*
(`simulink_A_mapper.py` handles Simulink/RTW, `scade6_A_mapper.py`
handles SCADE5, `ada_A_mapper.py` generates Ada types,
handles SCADE6, `ada_A_mapper.py` generates Ada types,
`sqlalchemy_A_mapper.py`, generates SQL definitions via SQLAlchemy, etc)
- **aadl2glueC** (*utility*)
......@@ -29,23 +65,22 @@ TASTE Data Modelling Technologies
Reads the AADL specification of the system, and then generates the runtime
bridge-code that will map the message data structures from those generated
by [ASN1SCC](https://github.com/ttsiodras/asn1scc) to/from those generated
by the modeling tool used to functionally model the subsystem (e.g. SCADE,
ObjectGeode, Matlab/Simulink, C, Ada, etc).
CHANGELOG
1.2.5
python_B_mapper: load PythonAccess.so from current folder
by the modeling tool (that is used to functionally model the subsystem -
e.g. SCADE, ObjectGeode, Matlab/Simulink, C, Ada, etc).
1.2.3
ctypes backend: emit all ENUMERATED values in DV.py
Contact
-------
1.2.0
Not using SWIG anymore for the Python mappers
For bug reports, please use the Issue Tracker; for any other communication,
contact me at:
1.1.2
pyside_b_mapper: added combo box for the asn1 value editor
Thanassis Tsiodras
Real-time Embedded Software Engineer
System, Software and Technology Department
European Space Agency
1.1.1
support empty SEQUENCEs (MyType ::= SEQUENCE {}) - except for Simulink
ESTEC
Keplerlaan 1, PO Box 299
NL-2200 AG Noordwijk, The Netherlands
Athanasios.Tsiodras@esa.int | www.esa.int
T +31 71 565 5332
This diff is collapsed.
../commonPy/recursiveMapper.py
\ No newline at end of file
og_B_mapper.py
\ No newline at end of file
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
asn2aadlPlus converts ASN.1 modules to AADL (v1 or v2) for use in TASTE
"""
from asn2aadlPlus import main
__version__ = 1.0
../commonPy/createInternalTypes.py
\ No newline at end of file
machine:
post:
- pyenv global 3.4.4 system
dependencies:
cache_directories:
- "~/.apt-cache"
pre:
- sudo rm -rf /var/cache/apt/archives && sudo ln -s ~/.apt-cache /var/cache/apt/archives && mkdir -p ~/.apt-cache/partial
- sudo apt-get update
- sudo apt-get install libxslt-dev libxml2-dev mono-complete
- wget -O - -q https://github.com/ttsiodras/asn1scc/releases/download/3.2.81/asn1scc-bin-3.2.81.tar.gz | tar zxvf -
- wget -O - -q https://github.com/ttsiodras/DataModellingTools/files/335591/antlr-2.7.7.tar.gz | tar zxvf - ; cd antlr-2.7.7/lib/python ; pip2 install .
override:
- pip3 install -r requirements.txt
test:
override:
- PATH=$PATH:$(pwd)/asn1scc make
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This module contains the shared API for parsing ASN.1
"""
import configMT
import asnParser
import asnAST
import utility
import createInternalTypes
import verify
import recursiveMapper
import cleanupNodes
__version__ = "1.2.5"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -21,7 +21,7 @@
import os
import re
import copy
import DV_Types
import DV_Types # pylint: disable=import-error
from ctypes import (
cdll, c_void_p, c_ubyte, c_double, c_uint,
c_longlong, c_bool, c_int, c_long
......@@ -102,7 +102,7 @@ class DataStream(object):
# print "Reading",
msg = ""
pData = c_void_p(GetBitstreamBuffer(self._bs))
for i in xrange(0, GetStreamCurrentLength(self._bs)):
for i in range(0, GetStreamCurrentLength(self._bs)):
b = GetBufferByte(pData, i)
msg += chr(b)
# print b, ",",
......@@ -115,7 +115,7 @@ class DataStream(object):
self._bs.count = strLength
pData = c_void_p(GetBitstreamBuffer(self._bs))
# print "Writing",
for i in xrange(0, strLength):
for i in range(0, strLength):
b = ord(data[i])
# print b, ",",
SetBufferByte(pData, i, b)
......@@ -219,8 +219,8 @@ An example for SetLength:
return "Choose the information you want - whole-structure or sequence dump not supported."
def __getattr__(self, x):
self._Caccessor += "_"+Clean(x)
self._accessPath += "."+x
self._Caccessor += "_" + Clean(x)
self._accessPath += "." + x
return self
def __setattr__(self, name, value):
......@@ -237,7 +237,7 @@ An example for SetLength:
def Get(self, **args): # postfix="", reset=True
try:
bridgeFuncName = Clean(self._nodeTypeName) + "_" + self._Caccessor + "_Get"+args.get("postfix", "")
bridgeFuncName = Clean(self._nodeTypeName) + "_" + self._Caccessor + "_Get" + args.get("postfix", "")
if bridgeFuncName not in DV_Types.funcTypeLookup:
raise AsnCoderError("Function %s not found in lookup - contact support." % bridgeFuncName)
resType = DV_Types.funcTypeLookup[bridgeFuncName]
......@@ -253,7 +253,7 @@ An example for SetLength:
'long': c_long
}.get(resType, None)
if cTypesResultType is None:
raise AsnCoderError("Result type of %s is not yet supported in the Python mapper - contact support." % resType)
raise AsnCoderError("Result type of %s not yet supported in the Python mapper - contact support." % resType)
bridgeFunc = getattr(JMP, bridgeFuncName)
bridgeFunc.restype = cTypesResultType
retVal = bridgeFunc(self._ptr, *self._params)
......@@ -269,22 +269,23 @@ An example for SetLength:
def Set(self, value, **args): # postfix="", reset=True
try:
# print Clean(self._nodeTypeName) + "_" + self._Caccessor + "_Set"+postfix
bridgeFunc = getattr(JMP, Clean(self._nodeTypeName) + "_" + self._Caccessor + "_Set"+args.get("postfix", ""))
bridgeFunc = getattr(JMP, Clean(self._nodeTypeName) + "_" + self._Caccessor + "_Set" + args.get("postfix", ""))
if isinstance(value, float):
ctypesValue = c_double(value)
elif isinstance(value, (int, long)):
elif isinstance(value, int):
ctypesValue = c_longlong(value)
else:
ctypesValue = value
self._params.append(ctypesValue)
bridgeFunc(self._ptr, *self._params)
self._params.pop()
except Exception, e:
except Exception as e:
oldAP = self._accessPath
if args.get("reset", True):
self.Reset()
raise AsnCoderError("The access path you used (%s) or the value you tried to assign (%s) is not valid. %s" %
(oldAP, str(value), str(e)))
raise AsnCoderError(
"The access path you used (%s) or the value you tried to assign (%s) is not valid. %s" % (
oldAP, str(value), str(e)))
if args.get("reset", True):
self.Reset()
......@@ -297,8 +298,8 @@ An example for SetLength:
@staticmethod
def getErrCode(pErr):
errCode = 0
for i in xrange(4):
errCode = (errCode << 8) | GetBufferByte(pErr, (3-i))
for i in range(4):
errCode = (errCode << 8) | GetBufferByte(pErr, (3 - i))
return errCode
def Encode(self, bitstream, bACN=False):
......@@ -350,7 +351,7 @@ grep for the errorcode value inside ASN1SCC generated headers."""
self.SetLength(strLength, False)
self._Caccessor += "_iDx"
accessPath = self._accessPath
for idx in xrange(0, strLength):
for idx in range(0, strLength):
self._params.append(idx)
self._accessPath = accessPath + "[" + str(idx) + "]"
self.Set(ord(src[idx]), reset=False)
......@@ -362,7 +363,7 @@ grep for the errorcode value inside ASN1SCC generated headers."""
strLength = self.GetLength(False)
self._Caccessor += "_iDx"
accessPath = self._accessPath
for idx in xrange(0, strLength):
for idx in range(0, strLength):
self._params.append(idx)
self._accessPath = accessPath + "[" + str(idx) + "]"
retval += chr(self.Get(reset=False))
......
......@@ -2,9 +2,7 @@
# -*- coding: utf-8 -*-
"""
asn2dataModel converts ASN.1 modules to a variety of target languages
asn2dataModel converts ASN.1 modules to a variety of target languages
"""
from asn2dataModel import main
import msgPrinter
import msgPrinterASN1
__version__ = 1.0
from ..commonPy import __version__
......@@ -26,22 +26,26 @@ import os
import sys
import distutils.spawn as spawn
from commonPy.utility import panic
from typing import List
from ..commonPy.utility import panic
from ..commonPy.cleanupNodes import SetOfBadTypenames
from ..commonPy.asnAST import AsnBasicNode, AsnSequenceOrSet, AsnSequenceOrSetOf, AsnEnumerated, AsnChoice
from ..commonPy.asnParser import AST_Leaftypes
def Version():
print "Code generator: " + "$Id: ada_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $" # pragma: no cover
def Version() -> None:
print("Code generator: " + "$Id: ada_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $") # pragma: no cover
# Especially for the C mapper, since we need to pass the complete ASN.1 files list to ASN1SCC,
# the second param is not asnFile, it is asnFiles
def OnStartup(unused_modelingLanguage, asnFiles, outputDir):
#print "Use ASN1SCC to generate the structures for '%s'" % asnFile
def OnStartup(unused_modelingLanguage: str, asnFiles: List[str], outputDir: str, unused_badTypes: SetOfBadTypenames) -> None: # pylint: disable=invalid-sequence-index
# print "Use ASN1SCC to generate the structures for '%s'" % asnFile
asn1SccPath = spawn.find_executable('asn1.exe')
if not asn1SccPath:
panic("ASN1SCC seems not installed on your system (asn1.exe not found in PATH).\n") # pragma: no cover
panic("ASN1SCC seems to be missing from your system (asn1.exe not found in PATH).\n") # pragma: no cover
os.system(
("mono " if sys.argv[0].endswith('.py') and sys.platform.startswith('linux') else "") +
"\"{}\" -wordSize 8 -typePrefix asn1Scc -Ada -uPER -o \"".format(asn1SccPath) +
......@@ -49,33 +53,33 @@ def OnStartup(unused_modelingLanguage, asnFiles, outputDir):
os.system("rm -f \"" + outputDir + "\"/*.adb")
def OnBasic(nodeTypename, node, leafTypeDict):
def OnBasic(unused_nodeTypename: str, unused_node: AsnBasicNode, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSequence(nodeTypename, node, leafTypeDict):
def OnSequence(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSet(nodeTypename, node, leafTypeDict):
def OnSet(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnEnumerated(nodeTypename, node, leafTypeDict):
def OnEnumerated(unused_nodeTypename: str, unused_node: AsnEnumerated, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSequenceOf(nodeTypename, node, leafTypeDict):
def OnSequenceOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSetOf(nodeTypename, node, leafTypeDict):
def OnSetOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnChoice(nodeTypename, node, leafTypeDict):
def OnChoice(unused_nodeTypename: str, unused_node: AsnChoice, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnShutdown():
def OnShutdown(unused_badTypes: SetOfBadTypenames) -> None:
pass # pragma: no cover
......@@ -25,22 +25,26 @@ code generator A.'''
import os
import sys
import distutils.spawn as spawn
from typing import List
from commonPy.utility import panic
from ..commonPy.utility import panic
from ..commonPy.cleanupNodes import SetOfBadTypenames
from ..commonPy.asnAST import AsnBasicNode, AsnSequenceOrSet, AsnSequenceOrSetOf, AsnEnumerated, AsnChoice
from ..commonPy.asnParser import AST_Leaftypes
def Version():
print "Code generator: " + "$Id: c_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $" # pragma: no cover
def Version() -> None:
print("Code generator: " + "$Id: c_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $") # pragma: no cover
# Especially for the C mapper, since we need to pass the complete ASN.1 files list to ASN1SCC,
# the second param is not asnFile, it is asnFiles
def OnStartup(unused_modelingLanguage, asnFiles, outputDir):
#print "Use ASN1SCC to generate the structures for '%s'" % asnFile
def OnStartup(unused_modelingLanguage: str, asnFiles: List[str], outputDir: str, unused_badTypes: SetOfBadTypenames) -> None: # pylint: disable=invalid-sequence-index
# print "Use ASN1SCC to generate the structures for '%s'" % asnFile
asn1SccPath = spawn.find_executable('asn1.exe')
if not asn1SccPath:
panic("ASN1SCC seems not installed on your system (asn1.exe not found in PATH).\n") # pragma: no cover
panic("ASN1SCC seems to be missing from your system (asn1.exe not found in PATH).\n") # pragma: no cover
os.system(
("mono " if sys.argv[0].endswith('.py') and sys.platform.startswith('linux') else "") +
"\"{}\" -wordSize 8 -typePrefix asn1Scc -c -uPER -o \"".format(asn1SccPath) +
......@@ -53,33 +57,33 @@ def OnStartup(unused_modelingLanguage, asnFiles, outputDir):
os.system("rm -f \"" + outputDir + os.sep + os.path.basename(os.path.splitext(tmp)[0]) + ".c\"")
def OnBasic(nodeTypename, node, leafTypeDict):
def OnBasic(unused_nodeTypename: str, unused_node: AsnBasicNode, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSequence(nodeTypename, node, leafTypeDict):
def OnSequence(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSet(nodeTypename, node, leafTypeDict):
def OnSet(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnEnumerated(nodeTypename, node, leafTypeDict):
def OnEnumerated(unused_nodeTypename: str, unused_node: AsnEnumerated, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSequenceOf(nodeTypename, node, leafTypeDict):
def OnSequenceOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnSetOf(nodeTypename, node, leafTypeDict):
def OnSetOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnChoice(nodeTypename, node, leafTypeDict):
def OnChoice(unused_nodeTypename: str, unused_node: AsnChoice, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: no cover
def OnShutdown():
def OnShutdown(unused_badTypes: SetOfBadTypenames) -> None:
pass # pragma: no cover
......@@ -23,7 +23,7 @@ for line in open(sys.argv[1] + '.h', 'r'):
enums.append(line.strip().replace(",", "").split("="))
enums_dump = "\n ".join(
'printf("%s = %%d\\n", %s);' % (e,e)
'printf("%s = %%d\\n", %s);' % (e, e)
for e in choices
)
......@@ -32,7 +32,7 @@ enums_dump += "\n ".join(
for name, val in enums
)
uniq = os.getpid()
extractor_filename ="/tmp/enums_%d" % uniq
extractor_filename = "/tmp/enums_%d" % uniq
f = open(extractor_filename + ".c", 'w')
f.write("""
#include <stdio.h>
......@@ -41,11 +41,11 @@ f.write("""
void main()
{
%(enums_dump)s
}""" % {"enums_dump":enums_dump, "base":sys.argv[1]})
}""" % {"enums_dump": enums_dump, "base": sys.argv[1]})
f.close()
if 0 != os.system(
"gcc -o %s -I. %s.c" % (extractor_filename, extractor_filename)):
print "Failed to extract CHOICE enum values..."
cmd = "gcc -o %s -I. %s.c" % (extractor_filename, extractor_filename)
if os.system(cmd) != 0:
print("Failed to extract CHOICE enum values...")
sys.exit(1)
os.system(extractor_filename)
os.unlink(extractor_filename + ".c")
......
......@@ -21,74 +21,78 @@
# This is an evolving test implementation of mapping ASN.1 constructs
# to SDL. It is used by the backend of Semantix's code generator A.
#import re
# import re
from ..commonPy import asnParser
from ..commonPy.cleanupNodes import SetOfBadTypenames
from ..commonPy.asnAST import AsnBasicNode, AsnSequenceOrSet, AsnSequenceOrSetOf, AsnEnumerated, AsnChoice
from ..commonPy.asnParser import AST_Leaftypes
g_outputDir = ""
g_asnFile = ""
def Version():
print "Code generator: " + "$Id: og_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $" # pragma: no cover
def Version() -> None:
print("Code generator: " + "$Id: og_A_mapper.py 2382 2012-06-22 08:35:33Z ttsiodras $") # pragma: no cover
def OnStartup(unused_modelingLanguage, asnFile, outputDir):
def OnStartup(unused_modelingLanguage: str, asnFile: str, outputDir: str, unused_badTypes: SetOfBadTypenames) -> None:
global g_asnFile
g_asnFile = asnFile
global g_outputDir
g_outputDir = outputDir
def OnBasic(nodeTypename, node, leafTypeDict):
def OnBasic(unused_nodeTypename: str, unused_node: AsnBasicNode, unused_leafTypeDict: AST_Leaftypes) -> None:
pass
def OnSequence(nodeTypename, node, leafTypeDict):
def OnSequence(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass
def OnSet(nodeTypename, node, leafTypeDict):
def OnSet(unused_nodeTypename: str, unused_node: AsnSequenceOrSet, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: nocover
def OnEnumerated(nodeTypename, node, leafTypeDict):
def OnEnumerated(unused_nodeTypename: str, unused_node: AsnEnumerated, unused_leafTypeDict: AST_Leaftypes) -> None:
pass
def OnSequenceOf(nodeTypename, node, leafTypeDict):
def OnSequenceOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass
def OnSetOf(nodeTypename, node, leafTypeDict):
def OnSetOf(unused_nodeTypename: str, unused_node: AsnSequenceOrSetOf, unused_leafTypeDict: AST_Leaftypes) -> None:
pass # pragma: nocover
def OnChoice(nodeTypename, node, leafTypeDict):
def OnChoice(unused_nodeTypename: str, unused_node: AsnChoice, unused_leafTypeDict: AST_Leaftypes) -> None:
pass
# obsolete, now the grammar is re-created from the AST (PrintGrammarFromAST)
#
#def ClearUp(text):
# outputText = ""
# lParen = 0
# for c in text:
# if c == '(':
# lParen += 1
# if c == ')':
# lParen -= 1
# if 0 == lParen:
# outputText += c.replace('-', '_')
# else:
# outputText += c
# return outputText
def OnShutdown():
# text = open(g_asnFile, 'r').read()
# text = re.sub(r'^.*BEGIN', 'Datamodel DEFINITIONS ::= BEGIN', text)
# text = re.sub(r'--.*', '', text)
# def ClearUp(text):
# outputText = ""
# lParen = 0
# for c in text:
# if c == '(':
# lParen += 1
# if c == ')':
# lParen -= 1
# if 0 == lParen:
# outputText += c.replace('-', '_')
# else:
# outputText += c
# return outputText