Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix support for display hints being applied #7

Merged
merged 1 commit into from
Oct 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions pysmi/codegen/intermediate.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,20 @@ def get_base_type(self, symName, module):

return baseSymType, symSubtype

def is_type_derived_from_tc(self, symName, module):
"""Is the given type derived from a Textual-Convention declaration?

Given that deriving simple types from textual conventions is currently
not supported altogether, this method tests only the immediate parent.

Any problems are ignored: if the given type is not definitely derived
from a textual convention, this method returns False.
"""
if module not in self.symbolTable or symName not in self.symbolTable[module]:
return False

return self.symbolTable[module][symName]["isTC"]

# Clause generation functions

# noinspection PyUnusedLocal
Expand Down Expand Up @@ -564,6 +578,19 @@ def gen_type_declaration(self, data):
outDict.update(attrs)
self.reg_sym(pysmiName, outDict)

# Establish if this type is derived from a Textual-Convention
# declaration, as needed for pysnmp code generation.
typeType = outDict["type"]["type"]
if (
typeType in self.symbolTable[self.moduleName[0]]
or typeType in self._importMap
):
module = self._importMap.get(typeType, self.moduleName[0])
isDerivedFromTC = self.is_type_derived_from_tc(typeType, module)
else:
isDerivedFromTC = False
outDict["type"]["tcbase"] = isDerivedFromTC

return outDict

# noinspection PyUnusedLocal
Expand Down
10 changes: 7 additions & 3 deletions pysmi/codegen/symtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,12 +351,14 @@ def gen_type_declaration(self, data, classmode=False):
pysmiName = self.trans_opers(origName)

if declaration:
parentType, attrs = declaration
parentType, attrs, isTC = declaration

if parentType: # skipping SEQUENCE case
symProps = {
"type": "TypeDeclaration",
"syntax": declaration, # (type, module), subtype
"syntax": (parentType, attrs), # (type, module), subtype
"origName": origName,
"isTC": isTC,
}

self.reg_sym(pysmiName, symProps, [declaration[0][0]])
Expand Down Expand Up @@ -555,13 +557,15 @@ def gen_simple_syntax(self, data, classmode=False):
def gen_type_declaration_rhs(self, data, classmode=False):
if len(data) == 1:
parentType, attrs = data[0] # just syntax
isTC = False

else:
# Textual convention
display, status, description, reference, syntax = data
parentType, attrs = syntax
isTC = True

return parentType, attrs
return parentType, attrs, isTC

# noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic
def gen_units(self, data, classmode=False):
Expand Down
6 changes: 5 additions & 1 deletion pysmi/codegen/templates/pysnmp/mib-definitions.j2
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,11 @@ class {{ symbol }}({{ definition['type']['type'] }}):
{% for symbol, definition in mib.items() if definition['class'] == 'textualconvention' %}


class {{ symbol }}({{ definition['type']['type'] }}, TextualConvention):
{% if definition['type']['tcbase'] %}
class {{ symbol }}({{ definition['type']['type'] }}):
{% else %}
class {{ symbol }}(TextualConvention, {{ definition['type']['type'] }}):
{% endif %}
status = "{{ definition.get('status', 'current') }}"
{% if 'displayhint' in definition %}
displayHint = {{ definition['displayhint']|pythonstr }}
Expand Down
57 changes: 54 additions & 3 deletions tests/test_imports_smiv2_pysnmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,18 @@ class ImportTypeTestCase(unittest.TestCase):
FROM SNMPv2-SMI
TEXTUAL-CONVENTION
FROM SNMPv2-TC
ImportedType1, Imported-Type-2, True
ImportedType1,
Imported-Type-2,
True,
ImportedType3
FROM IMPORTED-MIB;

testObject1 OBJECT-TYPE
SYNTAX ImportedType1
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { '01020304'H }
::= { 1 3 }

Test-Type-2 ::= TEXTUAL-CONVENTION
Expand All @@ -155,6 +159,7 @@ class ImportTypeTestCase(unittest.TestCase):
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 'aabbccdd'H }
::= { 1 4 }

False ::= TEXTUAL-CONVENTION
Expand All @@ -177,6 +182,20 @@ class ImportTypeTestCase(unittest.TestCase):
DESCRIPTION "Test object"
::= { 1 6 }

TestType3 ::= TEXTUAL-CONVENTION
DISPLAY-HINT "2d:"
STATUS current
DESCRIPTION "Test TC"
SYNTAX ImportedType3

testObject3 OBJECT-TYPE
SYNTAX TestType3
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { '000100020003'H }
::= { 1 7 }

END
"""

Expand All @@ -189,7 +208,7 @@ class ImportTypeTestCase(unittest.TestCase):
FROM SNMPv2-TC;

ImportedType1 ::= TEXTUAL-CONVENTION
DISPLAY-HINT "255a"
DISPLAY-HINT "1d:"
STATUS current
DESCRIPTION "Test TC with display hint"
SYNTAX OCTET STRING
Expand All @@ -204,6 +223,8 @@ class ImportTypeTestCase(unittest.TestCase):
DESCRIPTION "Test TC"
SYNTAX OCTET STRING

ImportedType3 ::= OCTET STRING

END
"""

Expand All @@ -230,10 +251,15 @@ def testObjectTypeLabel1(self):
def testObjectTypeDisplayHint1(self):
self.assertEqual(
self.ctx["testObject1"].getSyntax().getDisplayHint(),
"255a",
"1d:",
"bad display hint",
)

def testObjectTypePrettyValue1(self):
self.assertEqual(
self.ctx["testObject1"].getSyntax().prettyPrint(), "1:2:3:4", "bad defval"
)

def testObjectTypeName2(self):
self.assertEqual(self.ctx["test_object_2"].getName(), (1, 4), "bad value")

Expand All @@ -249,6 +275,13 @@ def testObjectTypeDisplayHint2(self):
"bad display hint",
)

def testObjectTypePrettyValue2(self):
self.assertEqual(
self.ctx["test_object_2"].getSyntax().prettyPrint(),
"aa:bb:cc:dd",
"bad defval",
)

def testObjectTypeNameReservedKeyword1(self):
self.assertEqual(self.ctx["_pysmi_global"].getName(), (1, 5), "bad value")

Expand All @@ -275,6 +308,24 @@ def testObjectTypeDisplayHintReservedKeyword2(self):
"bad display hint",
)

def testObjectTypeName3(self):
self.assertEqual(self.ctx["testObject3"].getName(), (1, 7), "bad value")

def testObjectTypeLabel3(self):
self.assertEqual(self.ctx["testObject3"].getLabel(), "testObject3", "bad label")

def testObjectTypeDisplayHint3(self):
self.assertEqual(
self.ctx["testObject3"].getSyntax().getDisplayHint(),
"2d:",
"bad display hint",
)

def testObjectTypePrettyValue3(self):
self.assertEqual(
self.ctx["testObject3"].getSyntax().prettyPrint(), "1:2:3", "bad defval"
)


class ImportSelfTestCase(unittest.TestCase):
"""
Expand Down
77 changes: 73 additions & 4 deletions tests/test_typedeclaration_smiv2_pysnmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,12 @@ class TypeDeclarationInheritanceTestCase(unittest.TestCase):
"""
TEST-MIB DEFINITIONS ::= BEGIN
IMPORTS
Unsigned32
OBJECT-TYPE
FROM SNMPv2-SMI
TEXTUAL-CONVENTION
FROM SNMPv2-TC;

TestTypeUnsigned32 ::= Unsigned32
TestTypeInteger ::= INTEGER

--
-- without constraints
Expand All @@ -359,14 +359,14 @@ class TypeDeclarationInheritanceTestCase(unittest.TestCase):
DISPLAY-HINT "d-1"
STATUS current
DESCRIPTION "Test TC 1"
SYNTAX Unsigned32
SYNTAX INTEGER

-- textual convention for simple type, derived from base type
TestTC-SB ::= TEXTUAL-CONVENTION
DISPLAY-HINT "d-2"
STATUS current
DESCRIPTION "Test TC 2"
SYNTAX TestTypeUnsigned32
SYNTAX TestTypeInteger

-- textual convention for textual convention, derived from base type
TestTC-TB ::= TEXTUAL-CONVENTION
Expand Down Expand Up @@ -431,6 +431,50 @@ class TypeDeclarationInheritanceTestCase(unittest.TestCase):
DESCRIPTION "Test TC 10"
SYNTAX TestTC-TC (SIZE (20..23))

--
-- test objects (without constraints only)
--

testObjectB OBJECT-TYPE
SYNTAX TestTC-B
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 123456 }
::= { 1 4 1 }

testObjectSB OBJECT-TYPE
SYNTAX TestTC-SB
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 123456 }
::= { 1 4 2 }

testObjectTB OBJECT-TYPE
SYNTAX TestTC-TB
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 123456 }
::= { 1 4 3 }

testObjectTSB OBJECT-TYPE
SYNTAX TestTC-TSB
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 123456 }
::= { 1 4 4 }

testObjectTTB OBJECT-TYPE
SYNTAX TestTC-TTB
MAX-ACCESS read-only
STATUS current
DESCRIPTION "Test object"
DEFVAL { 123456 }
::= { 1 4 5 }

END
"""

Expand Down Expand Up @@ -551,6 +595,31 @@ def testTextualConventionDisplayHintTTC(self):
"bad DISPLAY-HINT",
)

def testObjectTypePrettyValueB(self):
self.assertEqual(
self.ctx["testObjectB"].getSyntax().prettyPrint(), "12345.6", "bad DEFVAL"
)

def testObjectTypePrettyValueSB(self):
self.assertEqual(
self.ctx["testObjectSB"].getSyntax().prettyPrint(), "1234.56", "bad DEFVAL"
)

def testObjectTypePrettyValueTB(self):
self.assertEqual(
self.ctx["testObjectTB"].getSyntax().prettyPrint(), "123.456", "bad DEFVAL"
)

def testObjectTypePrettyValueTSB(self):
self.assertEqual(
self.ctx["testObjectTSB"].getSyntax().prettyPrint(), "12.3456", "bad DEFVAL"
)

def testObjectTypePrettyValueTTB(self):
self.assertEqual(
self.ctx["testObjectTTB"].getSyntax().prettyPrint(), "1.23456", "bad DEFVAL"
)


class TypeDeclarationBitsTextualConventionSyntaxTestCase(unittest.TestCase):
"""
Expand Down
Loading