You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1217 lines
43 KiB
1217 lines
43 KiB
#
|
|
# This file is part of pysmi software.
|
|
#
|
|
# Copyright (c) 2015-2019, Ilya Etingof <etingof@gmail.com>
|
|
# License: http://snmplabs.com/pysmi/license.html
|
|
#
|
|
import sys
|
|
import re
|
|
from time import strptime, strftime
|
|
from keyword import iskeyword
|
|
from pysmi.mibinfo import MibInfo
|
|
from pysmi.codegen.base import AbstractCodeGen, dorepr
|
|
from pysmi import error
|
|
from pysmi import debug
|
|
|
|
|
|
if sys.version_info[0] > 2:
|
|
# noinspection PyShadowingBuiltins
|
|
unicode = str
|
|
# noinspection PyShadowingBuiltins
|
|
long = int
|
|
|
|
|
|
class PySnmpCodeGen(AbstractCodeGen):
|
|
"""Builds PySNMP-specific Python code representing MIB module supplied
|
|
in form of an Abstract Syntax Tree on input.
|
|
|
|
Instance of this class is supposed to be passed to *MibCompiler*,
|
|
the rest is internal to *MibCompiler*.
|
|
"""
|
|
defaultMibPackages = ('pysnmp.smi.mibs', 'pysnmp_mibs')
|
|
|
|
symsTable = {
|
|
'MODULE-IDENTITY': ('ModuleIdentity',),
|
|
'OBJECT-TYPE': ('MibScalar', 'MibTable', 'MibTableRow', 'MibTableColumn'),
|
|
'NOTIFICATION-TYPE': ('NotificationType',),
|
|
'TEXTUAL-CONVENTION': ('TextualConvention',),
|
|
'MODULE-COMPLIANCE': ('ModuleCompliance',),
|
|
'OBJECT-GROUP': ('ObjectGroup',),
|
|
'NOTIFICATION-GROUP': ('NotificationGroup',),
|
|
'AGENT-CAPABILITIES': ('AgentCapabilities',),
|
|
'OBJECT-IDENTITY': ('ObjectIdentity',),
|
|
'TRAP-TYPE': ('NotificationType',), # smidump always uses NotificationType
|
|
'BITS': ('Bits',),
|
|
}
|
|
|
|
constImports = {
|
|
'ASN1': ('Integer', 'OctetString', 'ObjectIdentifier'),
|
|
'ASN1-ENUMERATION': ('NamedValues',),
|
|
'ASN1-REFINEMENT': ('ConstraintsUnion', 'ConstraintsIntersection', 'SingleValueConstraint',
|
|
'ValueRangeConstraint', 'ValueSizeConstraint'),
|
|
'SNMPv2-SMI': ('iso',
|
|
'Bits', # XXX
|
|
'Integer32', # XXX
|
|
'TimeTicks', # bug in some IETF MIBs
|
|
'Counter32', # bug in some IETF MIBs (e.g. DSA-MIB)
|
|
'Counter64', # bug in some MIBs (e.g.A3COM-HUAWEI-LswINF-MIB)
|
|
'NOTIFICATION-TYPE', # bug in some MIBs (e.g. A3COM-HUAWEI-DHCPSNOOP-MIB)
|
|
'Gauge32', # bug in some IETF MIBs (e.g. DSA-MIB)
|
|
'MODULE-IDENTITY', 'OBJECT-TYPE', 'OBJECT-IDENTITY', 'Unsigned32', 'IpAddress', # XXX
|
|
'MibIdentifier'), # OBJECT IDENTIFIER
|
|
'SNMPv2-TC': ('DisplayString', 'TEXTUAL-CONVENTION',), # XXX
|
|
'SNMPv2-CONF': ('MODULE-COMPLIANCE', 'NOTIFICATION-GROUP',), # XXX
|
|
}
|
|
|
|
# never compile these, they either:
|
|
# - define MACROs (implementation supplies them)
|
|
# - or carry conflicting OIDs (so that all IMPORT's of them will be rewritten)
|
|
# - or have manual fixes
|
|
# - or import base ASN.1 types from implementation-specific MIBs
|
|
fakeMibs = ('ASN1',
|
|
'ASN1-ENUMERATION',
|
|
'ASN1-REFINEMENT')
|
|
baseMibs = ('PYSNMP-USM-MIB',
|
|
'SNMP-FRAMEWORK-MIB',
|
|
'SNMP-TARGET-MIB',
|
|
'TRANSPORT-ADDRESS-MIB',
|
|
'INET-ADDRESS-MIB') + AbstractCodeGen.baseMibs
|
|
|
|
baseTypes = ['Integer', 'Integer32', 'Bits', 'ObjectIdentifier', 'OctetString']
|
|
|
|
typeClasses = {
|
|
'COUNTER32': 'Counter32',
|
|
'COUNTER64': 'Counter64',
|
|
'GAUGE32': 'Gauge32',
|
|
'INTEGER': 'Integer32', # XXX
|
|
'INTEGER32': 'Integer32',
|
|
'IPADDRESS': 'IpAddress',
|
|
'NETWORKADDRESS': 'IpAddress',
|
|
'OBJECT IDENTIFIER': 'ObjectIdentifier',
|
|
'OCTET STRING': 'OctetString',
|
|
'OPAQUE': 'Opaque',
|
|
'TIMETICKS': 'TimeTicks',
|
|
'UNSIGNED32': 'Unsigned32',
|
|
'Counter': 'Counter32',
|
|
'Gauge': 'Gauge32',
|
|
'NetworkAddress': 'IpAddress', # RFC1065-SMI, RFC1155-SMI -> SNMPv2-SMI
|
|
'nullSpecific': 'zeroDotZero', # RFC1158-MIB -> SNMPv2-SMI
|
|
'ipRoutingTable': 'ipRouteTable', # RFC1158-MIB -> RFC1213-MIB
|
|
'snmpEnableAuthTraps': 'snmpEnableAuthenTraps' # RFC1158-MIB -> SNMPv2-MIB
|
|
}
|
|
|
|
smiv1IdxTypes = ['INTEGER', 'OCTET STRING', 'IPADDRESS', 'NETWORKADDRESS']
|
|
|
|
ifTextStr = 'if mibBuilder.loadTexts: '
|
|
indent = ' ' * 4
|
|
fakeidx = 1000 # starting index for fake symbols
|
|
|
|
def __init__(self):
|
|
self._snmpTypes = set(self.typeClasses.values())
|
|
self._snmpTypes.add('Bits')
|
|
self._rows = set()
|
|
self._cols = {} # k, v = name, datatype
|
|
self._exports = set()
|
|
self._seenSyms = set()
|
|
self._importMap = {}
|
|
self._out = {} # k, v = name, generated code
|
|
self._moduleIdentityOid = None
|
|
self._moduleRevision = None
|
|
self.moduleName = ['DUMMY']
|
|
self.genRules = {'text': True}
|
|
self.symbolTable = {}
|
|
|
|
def symTrans(self, symbol):
|
|
if symbol in self.symsTable:
|
|
return self.symsTable[symbol]
|
|
|
|
return symbol,
|
|
|
|
@staticmethod
|
|
def transOpers(symbol):
|
|
if iskeyword(symbol):
|
|
symbol = 'pysmi_' + symbol
|
|
|
|
return symbol.replace('-', '_')
|
|
|
|
def prepData(self, pdata, classmode=False):
|
|
data = []
|
|
|
|
for el in pdata:
|
|
if not isinstance(el, tuple):
|
|
data.append(el)
|
|
|
|
elif len(el) == 1:
|
|
data.append(el[0])
|
|
|
|
else:
|
|
data.append(
|
|
self.handlersTable[el[0]](self, self.prepData(el[1:], classmode=classmode), classmode=classmode)
|
|
)
|
|
|
|
return data
|
|
|
|
def genImports(self, imports):
|
|
outStr = ''
|
|
|
|
# conversion to SNMPv2
|
|
toDel = []
|
|
for module in list(imports):
|
|
|
|
if module in self.convertImportv2:
|
|
|
|
for symbol in imports[module]:
|
|
|
|
if symbol in self.convertImportv2[module]:
|
|
toDel.append((module, symbol))
|
|
|
|
for newImport in self.convertImportv2[module][symbol]:
|
|
newModule, newSymbol = newImport
|
|
|
|
if newModule in imports:
|
|
imports[newModule].append(newSymbol)
|
|
else:
|
|
imports[newModule] = [newSymbol]
|
|
|
|
# removing converted symbols
|
|
for d in toDel:
|
|
imports[d[0]].remove(d[1])
|
|
|
|
# merging mib and constant imports
|
|
for module in self.constImports:
|
|
if module in imports:
|
|
imports[module] += self.constImports[module]
|
|
else:
|
|
imports[module] = self.constImports[module]
|
|
|
|
for module in sorted(imports):
|
|
symbols = ()
|
|
|
|
for symbol in set(imports[module]):
|
|
symbols += self.symTrans(symbol)
|
|
|
|
if symbols:
|
|
self._seenSyms.update([self.transOpers(s) for s in symbols])
|
|
self._importMap.update([(self.transOpers(s), module) for s in symbols])
|
|
|
|
outStr += ', '.join([self.transOpers(s) for s in symbols])
|
|
if len(symbols) < 2:
|
|
outStr += ','
|
|
outStr += ' = mibBuilder.importSymbols("%s")\n' % ('", "'.join((module,) + symbols))
|
|
|
|
return outStr, tuple(sorted(imports))
|
|
|
|
def genExports(self, ):
|
|
exports = list(self._exports)
|
|
if not exports:
|
|
return ''
|
|
|
|
numFuncCalls = len(exports) // 254 + 1
|
|
|
|
outStr = ''
|
|
|
|
for idx in range(numFuncCalls):
|
|
outStr += 'mibBuilder.exportSymbols("' + self.moduleName[0] + '", '
|
|
outStr += ', '.join(exports[254 * idx:254 * (idx + 1)]) + ')\n'
|
|
|
|
return outStr
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
def genLabel(self, symbol, classmode=False):
|
|
if '-' in symbol or iskeyword(symbol):
|
|
return classmode and 'label = "' + symbol + '"\n' or '.setLabel("' + symbol + '")'
|
|
|
|
return ''
|
|
|
|
def addToExports(self, symbol, moduleIdentity=0):
|
|
if moduleIdentity:
|
|
self._exports.add('PYSNMP_MODULE_ID=%s' % symbol)
|
|
|
|
self._exports.add('%s=%s' % (symbol, symbol))
|
|
self._seenSyms.add(symbol)
|
|
|
|
# noinspection PyUnusedLocal
|
|
def regSym(self, symbol, outStr, oidStr=None, moduleIdentity=False):
|
|
if symbol in self._seenSyms and symbol not in self._importMap:
|
|
raise error.PySmiSemanticError('Duplicate symbol found: %s' % symbol)
|
|
|
|
self.addToExports(symbol, moduleIdentity)
|
|
self._out[symbol] = outStr
|
|
|
|
if moduleIdentity:
|
|
if self._moduleIdentityOid:
|
|
raise error.PySmiSemanticError('Duplicate module identity')
|
|
# TODO: turning literal tuple into a string - hackerish
|
|
self._moduleIdentityOid = '.'.join(oidStr.split(', '))[1:-1]
|
|
|
|
def genNumericOid(self, oid):
|
|
numericOid = ()
|
|
|
|
for part in oid:
|
|
if isinstance(part, tuple):
|
|
parent, module = part
|
|
|
|
if parent == 'iso':
|
|
numericOid += (1,)
|
|
continue
|
|
|
|
if module not in self.symbolTable:
|
|
# XXX do getname for possible future borrowed mibs
|
|
raise error.PySmiSemanticError('no module "%s" in symbolTable' % module)
|
|
|
|
if parent not in self.symbolTable[module]:
|
|
raise error.PySmiSemanticError('no symbol "%s" in module "%s"' % (parent, module))
|
|
|
|
numericOid += self.genNumericOid(self.symbolTable[module][parent]['oid'])
|
|
|
|
else:
|
|
numericOid += (part,)
|
|
|
|
return numericOid
|
|
|
|
def getBaseType(self, symName, module):
|
|
if module not in self.symbolTable:
|
|
raise error.PySmiSemanticError('no module "%s" in symbolTable' % module)
|
|
|
|
if symName not in self.symbolTable[module]:
|
|
raise error.PySmiSemanticError('no symbol "%s" in module "%s"' % (symName, module))
|
|
|
|
symType, symSubtype = self.symbolTable[module][symName].get('syntax', (('', ''), ''))
|
|
|
|
if not symType[0]:
|
|
raise error.PySmiSemanticError('unknown type for symbol "%s"' % symName)
|
|
|
|
if symType[0] in self.baseTypes:
|
|
return symType, symSubtype
|
|
|
|
else:
|
|
baseSymType, baseSymSubtype = self.getBaseType(*symType)
|
|
|
|
if isinstance(baseSymSubtype, list):
|
|
if isinstance(symSubtype, list):
|
|
symSubtype += baseSymSubtype
|
|
else:
|
|
symSubtype = baseSymSubtype
|
|
|
|
return baseSymType, symSubtype
|
|
|
|
# Clause generation functions
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genAgentCapabilities(self, data, classmode=False):
|
|
name, productRelease, status, description, reference, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
outStr = name + ' = AgentCapabilities(' + oidStr + ')' + label + '\n'
|
|
|
|
if productRelease:
|
|
outStr += """\
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(name)s = %(name)s%(productRelease)s
|
|
""" % dict(name=name, productRelease=productRelease)
|
|
|
|
if status:
|
|
outStr += """\
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(name)s = %(name)s%(status)s
|
|
""" % dict(name=name, status=status)
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genModuleIdentity(self, data, classmode=False):
|
|
name, lastUpdated, organization, contactInfo, description, revisionsAndDescrs, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
|
|
outStr = name + ' = ModuleIdentity(' + oidStr + ')' + label + '\n'
|
|
|
|
if revisionsAndDescrs:
|
|
last_revision, revisions, descriptions = revisionsAndDescrs
|
|
|
|
self._moduleRevision = last_revision
|
|
|
|
if revisions:
|
|
outStr += name + revisions + '\n'
|
|
|
|
if self.genRules['text'] and descriptions:
|
|
outStr += """
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(ifTextStr)s%(name)s%(descriptions)s
|
|
""" % dict(ifTextStr=self.ifTextStr, name=name, descriptions=descriptions)
|
|
|
|
if lastUpdated:
|
|
outStr += self.ifTextStr + name + lastUpdated + '\n'
|
|
|
|
if organization:
|
|
outStr += self.ifTextStr + name + organization + '\n'
|
|
|
|
if self.genRules['text'] and contactInfo:
|
|
outStr += self.ifTextStr + name + contactInfo + '\n'
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr, moduleIdentity=True)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genModuleCompliance(self, data, classmode=False):
|
|
name, status, description, reference, compliances, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
outStr = name + ' = ModuleCompliance(' + oidStr + ')' + label
|
|
outStr += compliances + '\n'
|
|
|
|
if status:
|
|
outStr += """\
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(name)s = %(name)s%(status)s
|
|
""" % dict(name=name, status=status)
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genNotificationGroup(self, data, classmode=False):
|
|
name, objects, status, description, reference, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
|
|
outStr = name + ' = NotificationGroup(' + oidStr + ')' + label
|
|
|
|
if objects:
|
|
objects = ['("' + self._importMap.get(obj, self.moduleName[0]) + '", "' + self.transOpers(obj) + '")'
|
|
for obj in objects]
|
|
|
|
numFuncCalls = len(objects) // 255 + 1
|
|
|
|
if numFuncCalls > 1:
|
|
objStrParts = []
|
|
|
|
for idx in range(numFuncCalls):
|
|
objStrParts.append('[' + ', '.join(objects[255 * idx:255 * (idx + 1)]) + ']')
|
|
|
|
outStr += """
|
|
for _%(name)s_obj in [%(objects)s]:
|
|
if getattr(mibBuilder, 'version', 0) < (4, 4, 2):
|
|
# WARNING: leading objects get lost here! Upgrade your pysnmp version!
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj)
|
|
else:
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj, **dict(append=True))\
|
|
""" % dict(name=name, objects=', '.join(objStrParts))
|
|
|
|
else:
|
|
outStr += '.setObjects(' + ', '.join(objects) + ')'
|
|
|
|
outStr += '\n'
|
|
|
|
if status:
|
|
outStr += """\
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(name)s = %(name)s%(status)s
|
|
""" % dict(name=name, status=status)
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genNotificationType(self, data, classmode=False):
|
|
name, objects, status, description, reference, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
|
|
outStr = name + ' = NotificationType(' + oidStr + ')' + label
|
|
|
|
if objects:
|
|
objects = ['("' + self._importMap.get(obj, self.moduleName[0]) + '", "' + self.transOpers(obj) + '")'
|
|
for obj in objects]
|
|
|
|
numFuncCalls = len(objects) // 255 + 1
|
|
|
|
if numFuncCalls > 1:
|
|
objStrParts = []
|
|
|
|
for idx in range(numFuncCalls):
|
|
objStrParts.append('[' + ', '.join(objects[255 * idx:255 * (idx + 1)]) + ']')
|
|
|
|
outStr += """
|
|
for _%(name)s_obj in [%(objects)s]:
|
|
if getattr(mibBuilder, 'version', 0) < (4, 4, 2):
|
|
# WARNING: leading objects get lost here! Upgrade your pysnmp version!
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj)
|
|
else:
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj, **dict(append=True))\
|
|
""" % dict(name=name, objects=', '.join(objStrParts))
|
|
|
|
else:
|
|
outStr += '.setObjects(' + ', '.join(objects) + ')'
|
|
|
|
outStr += '\n'
|
|
|
|
if status:
|
|
outStr += self.ifTextStr + name + status + '\n'
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genObjectGroup(self, data, classmode=False):
|
|
name, objects, status, description, reference, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
|
|
outStr = name + ' = ObjectGroup(' + oidStr + ')' + label
|
|
|
|
if objects:
|
|
objects = ['("' + self._importMap.get(obj, self.moduleName[0]) + '", "' + self.transOpers(obj) + '")'
|
|
for obj in objects]
|
|
|
|
numFuncCalls = len(objects) // 255 + 1
|
|
|
|
if numFuncCalls > 1:
|
|
objStrParts = []
|
|
|
|
for idx in range(numFuncCalls):
|
|
objStrParts.append('[' + ', '.join(objects[255 * idx:255 * (idx + 1)]) + ']')
|
|
|
|
outStr += """
|
|
for _%(name)s_obj in [%(objects)s]:
|
|
if getattr(mibBuilder, 'version', 0) < (4, 4, 2):
|
|
# WARNING: leading objects get lost here!
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj)
|
|
else:
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj, **dict(append=True))\
|
|
""" % dict(name=name, objects=', '.join(objStrParts))
|
|
|
|
else:
|
|
outStr += '.setObjects(' + ', '.join(objects) + ')'
|
|
|
|
outStr += '\n'
|
|
|
|
if status:
|
|
outStr += """\
|
|
if getattr(mibBuilder, 'version', (0, 0, 0)) > (4, 4, 0):
|
|
%(name)s = %(name)s%(status)s
|
|
""" % dict(name=name, status=status)
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genObjectIdentity(self, data, classmode=False):
|
|
name, status, description, reference, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
outStr = name + ' = ObjectIdentity(' + oidStr + ')' + label + '\n'
|
|
|
|
if status:
|
|
outStr += self.ifTextStr + name + status + '\n'
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genObjectType(self, data, classmode=False):
|
|
name, syntax, units, maxaccess, status, description, reference, augmention, index, defval, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
|
|
indexStr, fakeStrlist, fakeSyms = index or ('', '', [])
|
|
subtype = syntax[0] == 'Bits' and 'Bits()' + syntax[1] or syntax[1] # Bits hack #1
|
|
|
|
classtype = self.typeClasses.get(syntax[0], syntax[0])
|
|
classtype = self.transOpers(classtype)
|
|
classtype = syntax[0] == 'Bits' and 'MibScalar' or classtype # Bits hack #2
|
|
classtype = name in self.symbolTable[self.moduleName[0]]['_symtable_cols'] and 'MibTableColumn' or classtype
|
|
|
|
defval = self.genDefVal(defval, objname=name)
|
|
|
|
outStr = name + ' = ' + classtype + '(' + oidStr + ', ' + subtype + (defval or '') + ')' + label
|
|
outStr += units or ''
|
|
outStr += maxaccess or ''
|
|
outStr += indexStr or ''
|
|
outStr += '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
if augmention:
|
|
augmention = self.transOpers(augmention)
|
|
outStr += augmention + '.registerAugmentions(("' + self._importMap.get(name, self.moduleName[0]) + '", "' + name + '"))\n'
|
|
outStr += name + '.setIndexNames(*' + augmention + '.getIndexNames())\n'
|
|
|
|
if status:
|
|
outStr += self.ifTextStr + name + status + '\n'
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
self.regSym(name, outStr, parentOid)
|
|
|
|
if fakeSyms: # fake symbols for INDEX to support SMIv1
|
|
for idx, fakeSym in enumerate(fakeSyms):
|
|
fakeOutStr = fakeStrlist[idx] % oidStr
|
|
self.regSym(fakeSym, fakeOutStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genTrapType(self, data, classmode=False):
|
|
name, enterprise, objects, description, reference, value = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
enterpriseStr, parentOid = enterprise
|
|
|
|
outStr = name + ' = NotificationType(' + enterpriseStr + ' + (0,' + str(value) + '))' + label
|
|
|
|
if objects:
|
|
objects = ['("' + self._importMap.get(obj, self.moduleName[0]) + '", "' + self.transOpers(obj) + '")'
|
|
for obj in objects]
|
|
|
|
numFuncCalls = len(objects) // 255 + 1
|
|
|
|
if numFuncCalls > 1:
|
|
objStrParts = []
|
|
|
|
for idx in range(numFuncCalls):
|
|
objStrParts.append('[' + ', '.join(objects[255 * idx:255 * (idx + 1)]) + ']')
|
|
|
|
outStr += """
|
|
for _%(name)s_obj in [%(objects)s]:
|
|
if getattr(mibBuilder, 'version', 0) < (4, 4, 2):
|
|
# WARNING: leading objects get lost here! Upgrade your pysnmp version!
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj)
|
|
else:
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj, **dict(append=True))\
|
|
""" % dict(name=name, objects=', '.join(objStrParts))
|
|
|
|
else:
|
|
outStr += '.setObjects(' + ', '.join(objects) + ')'
|
|
|
|
outStr += '\n'
|
|
|
|
if self.genRules['text'] and description:
|
|
outStr += self.ifTextStr + name + description + '\n'
|
|
|
|
if self.genRules['text'] and reference:
|
|
outStr += self.ifTextStr + name + reference + '\n'
|
|
|
|
self.regSym(name, outStr, enterpriseStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genTypeDeclaration(self, data, classmode=False):
|
|
outStr = ''
|
|
|
|
name, declaration = data
|
|
|
|
if declaration:
|
|
parentType, attrs = declaration
|
|
if parentType: # skipping SEQUENCE case
|
|
name = self.transOpers(name)
|
|
outStr = 'class ' + name + '(' + parentType + '):\n' + attrs + '\n'
|
|
self.regSym(name, outStr)
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genValueDeclaration(self, data, classmode=False):
|
|
name, oid = data
|
|
|
|
label = self.genLabel(name)
|
|
name = self.transOpers(name)
|
|
|
|
oidStr, parentOid = oid
|
|
outStr = name + ' = MibIdentifier(' + oidStr + ')' + label + '\n'
|
|
|
|
self.regSym(name, outStr, oidStr)
|
|
|
|
return outStr
|
|
|
|
# Subparts generation functions
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def ftNames(self, data, classmode=False):
|
|
names = data[0]
|
|
return names
|
|
|
|
def genBitNames(self, data, classmode=False):
|
|
names = data[0]
|
|
return names
|
|
|
|
def genBits(self, data, classmode=False):
|
|
bits = data[0]
|
|
|
|
namedval = ['("' + bit[0] + '", ' + str(bit[1]) + ')' for bit in bits]
|
|
|
|
numFuncCalls = len(namedval) // 255 + 1
|
|
|
|
funcCalls = ''
|
|
for idx in range(numFuncCalls):
|
|
funcCalls += 'NamedValues(' + ', '.join(namedval[255 * idx:255 * (idx + 1)]) + ') + '
|
|
|
|
funcCalls = funcCalls[:-3]
|
|
|
|
outStr = classmode and self.indent + 'namedValues = ' + funcCalls + '\n' or '.clone(namedValues=' + funcCalls + ')'
|
|
|
|
return 'Bits', outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genCompliances(self, data, classmode=False):
|
|
if not data[0]:
|
|
return ''
|
|
|
|
objects = []
|
|
|
|
for complianceModule in data[0]:
|
|
name = complianceModule[0] or self.moduleName[0]
|
|
objects += ['("' + name + '", "' + self.transOpers(compl) + '")' for compl in complianceModule[1]]
|
|
|
|
outStr = ''
|
|
|
|
numFuncCalls = len(objects) // 255 + 1
|
|
|
|
if numFuncCalls > 1:
|
|
objStrParts = []
|
|
|
|
for idx in range(numFuncCalls):
|
|
objStrParts.append('[' + ', '.join(objects[255 * idx:255 * (idx + 1)]) + ']')
|
|
|
|
outStr += """
|
|
for _%(name)s_obj in [%(objects)s]:
|
|
if getattr(mibBuilder, 'version', 0) < (4, 4, 2):
|
|
# WARNING: leading objects get lost here! Upgrade your pysnmp version!
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj)
|
|
else:
|
|
%(name)s = %(name)s.setObjects(*_%(name)s_obj, **dict(append=True))
|
|
|
|
""" % dict(name=name, objects=', '.join(objStrParts))
|
|
|
|
else:
|
|
outStr += '.setObjects(' + ', '.join(objects) + ')\n'
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genConceptualTable(self, data, classmode=False):
|
|
row = data[0]
|
|
if row[1] and row[1][-2:] == '()':
|
|
row = row[1][:-2]
|
|
self._rows.add(row)
|
|
|
|
return 'MibTable', ''
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genContactInfo(self, data, classmode=False):
|
|
text = self.textFilter('contact-info', data[0])
|
|
return '.setContactInfo(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genDisplayHint(self, data, classmode=False):
|
|
return self.indent + 'displayHint = ' + dorepr(data[0]) + '\n'
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genDefVal(self, data, classmode=False, objname=None):
|
|
if not data:
|
|
return ''
|
|
|
|
if not objname:
|
|
return data
|
|
|
|
defval = data[0]
|
|
defvalType = self.getBaseType(objname, self.moduleName[0])
|
|
|
|
if isinstance(defval, (int, long)): # number
|
|
val = str(defval)
|
|
|
|
elif self.isHex(defval): # hex
|
|
if defvalType[0][0] in ('Integer32', 'Integer'): # common bug in MIBs
|
|
val = str(int(defval[1:-2], 16))
|
|
else:
|
|
val = 'hexValue="' + defval[1:-2] + '"'
|
|
|
|
elif self.isBinary(defval): # binary
|
|
binval = defval[1:-2]
|
|
if defvalType[0][0] in ('Integer32', 'Integer'): # common bug in MIBs
|
|
val = str(int(binval or '0', 2))
|
|
else:
|
|
hexval = binval and hex(int(binval, 2))[2:] or ''
|
|
val = 'hexValue="' + hexval + '"'
|
|
|
|
elif defval[0] == defval[-1] and defval[0] == '"': # quoted string
|
|
if defval[1:-1] == '' and defvalType != 'OctetString': # common bug
|
|
# a warning should be here
|
|
return False # we will set no default value
|
|
|
|
val = dorepr(defval[1:-1])
|
|
|
|
else: # symbol (oid as defval) or name for enumeration member
|
|
if (defvalType[0][0] == 'ObjectIdentifier' and
|
|
(defval in self.symbolTable[self.moduleName[0]] or defval in self._importMap)): # oid
|
|
module = self._importMap.get(defval, self.moduleName[0])
|
|
|
|
try:
|
|
val = str(self.genNumericOid(self.symbolTable[module][defval]['oid']))
|
|
except:
|
|
# or no module if it will be borrowed later
|
|
raise error.PySmiSemanticError('no symbol "%s" in module "%s"' % (defval, module))
|
|
|
|
# enumeration
|
|
elif defvalType[0][0] in ('Integer32', 'Integer') and isinstance(defvalType[1], list):
|
|
if isinstance(defval, list): # buggy MIB: DEFVAL { { ... } }
|
|
defval = [dv for dv in defval if dv in dict(defvalType[1])]
|
|
val = defval and dorepr(defval[0]) or ''
|
|
elif defval in dict(defvalType[1]): # good MIB: DEFVAL { ... }
|
|
val = dorepr(defval)
|
|
else:
|
|
val = ''
|
|
|
|
elif defvalType[0][0] == 'Bits':
|
|
defvalBits = []
|
|
bits = dict(defvalType[1])
|
|
|
|
for bit in defval:
|
|
bitValue = bits.get(bit, None)
|
|
if bitValue is not None:
|
|
defvalBits.append((bit, bitValue))
|
|
else:
|
|
raise error.PySmiSemanticError('no such bit as "%s" for symbol "%s"' % (bit, objname))
|
|
|
|
return self.genBits([defvalBits])[1]
|
|
|
|
else:
|
|
raise error.PySmiSemanticError(
|
|
'unknown type "%s" for defval "%s" of symbol "%s"' % (defvalType, defval, objname))
|
|
|
|
return '.clone(' + val + ')'
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genDescription(self, data, classmode=False):
|
|
text = self.textFilter('description', data[0])
|
|
return classmode and self.indent + 'description = ' + dorepr(text) + '\n' or '.setDescription(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
def genReference(self, data, classmode=False):
|
|
text = self.textFilter('reference', data[0])
|
|
return classmode and self.indent + 'reference = ' + dorepr(text) + '\n' or '.setReference(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
def genStatus(self, data, classmode=False):
|
|
text = data[0]
|
|
return classmode and self.indent + 'status = ' + dorepr(text) + '\n' or '.setStatus(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyMethodMayBeStatic
|
|
def genProductRelease(self, data, classmode=False):
|
|
text = data[0]
|
|
return classmode and self.indent + 'productRelease = ' + dorepr(text) + '\n' or '.setProductRelease(' + dorepr(text) + ')'
|
|
|
|
def genEnumSpec(self, data, classmode=False):
|
|
items = data[0]
|
|
singleval = [str(item[1]) for item in items]
|
|
outStr = classmode and self.indent + 'subtypeSpec = %s.subtypeSpec + ' or '.subtype(subtypeSpec='
|
|
numFuncCalls = len(singleval) / 255 + 1
|
|
singleCall = numFuncCalls == 1
|
|
funcCalls = ''
|
|
|
|
outStr += not singleCall and 'ConstraintsUnion(' or ''
|
|
|
|
for idx in range(int(numFuncCalls)):
|
|
if funcCalls:
|
|
funcCalls += ', '
|
|
funcCalls += 'SingleValueConstraint(' + ', '.join(singleval[255 * idx:255 * (idx + 1)]) + ')'
|
|
|
|
outStr += funcCalls
|
|
outStr += not singleCall and (classmode and ')\n' or '))') or (not classmode and ')' or '\n')
|
|
outStr += self.genBits(data, classmode=classmode)[1]
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genTableIndex(self, data, classmode=False):
|
|
def genFakeSyms(fakeidx, idxType):
|
|
fakeSymName = 'pysmiFakeCol%s' % fakeidx
|
|
|
|
objType = self.typeClasses.get(idxType, idxType)
|
|
objType = self.transOpers(objType)
|
|
|
|
return (fakeSymName + ' = MibTableColumn(%s + (' + str(fakeidx) +
|
|
', ), ' + objType + '())\n', # stub for parentOid
|
|
fakeSymName)
|
|
|
|
indexes = data[0]
|
|
idxStrlist, fakeSyms, fakeStrlist = [], [], []
|
|
for idx in indexes:
|
|
idxName = idx[1]
|
|
if idxName in self.smiv1IdxTypes: # SMIv1 support
|
|
idxType = idxName
|
|
|
|
fakeSymStr, idxName = genFakeSyms(self.fakeidx, idxType)
|
|
fakeStrlist.append(fakeSymStr)
|
|
fakeSyms.append(idxName)
|
|
self.fakeidx += 1
|
|
|
|
idxStrlist.append('(' + str(idx[0]) + ', "' +
|
|
self._importMap.get(idxName, self.moduleName[0]) +
|
|
'", "' + idxName + '")')
|
|
|
|
return '.setIndexNames(' + ', '.join(idxStrlist) + ')', fakeStrlist, fakeSyms
|
|
|
|
def genIntegerSubType(self, data, classmode=False):
|
|
singleRange = len(data[0]) == 1
|
|
|
|
outStr = classmode and self.indent + 'subtypeSpec = %s.subtypeSpec + ' or '.subtype(subtypeSpec='
|
|
outStr += not singleRange and 'ConstraintsUnion(' or ''
|
|
|
|
for rng in data[0]:
|
|
vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng
|
|
vmin, vmax = str(self.str2int(vmin)), str(self.str2int(vmax))
|
|
outStr += 'ValueRangeConstraint(' + vmin + ', ' + vmax + ')' + (not singleRange and ', ' or '')
|
|
|
|
outStr += not singleRange and (classmode and ')' or '))') or (not classmode and ')' or '\n')
|
|
|
|
return outStr
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genMaxAccess(self, data, classmode=False):
|
|
access = data[0].replace('-', '')
|
|
return access != 'notaccessible' and '.setMaxAccess("' + access + '")' or ''
|
|
|
|
def genOctetStringSubType(self, data, classmode=False):
|
|
singleRange = len(data[0]) == 1
|
|
|
|
outStr = classmode and self.indent + 'subtypeSpec = %s.subtypeSpec + ' or '.subtype(subtypeSpec='
|
|
outStr += not singleRange and 'ConstraintsUnion(' or ''
|
|
|
|
for rng in data[0]:
|
|
vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng
|
|
vmin, vmax = str(self.str2int(vmin)), str(self.str2int(vmax))
|
|
outStr += ('ValueSizeConstraint(' + vmin + ', ' + vmax + ')' +
|
|
(not singleRange and ', ' or ''))
|
|
|
|
outStr += not singleRange and (classmode and ')' or '))') or (not classmode and ')' or '\n')
|
|
|
|
if data[0]:
|
|
# noinspection PyUnboundLocalVariable
|
|
outStr += (singleRange
|
|
and vmin == vmax
|
|
and (classmode and self.indent + 'fixedLength = ' + vmin + '\n' or '.setFixedLength(' + vmin + ')') or '')
|
|
|
|
return outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genOid(self, data, classmode=False):
|
|
out = ()
|
|
parent = ''
|
|
for el in data[0]:
|
|
if isinstance(el, (str, unicode)):
|
|
parent = self.transOpers(el)
|
|
out += ((parent, self._importMap.get(parent, self.moduleName[0])),)
|
|
|
|
elif isinstance(el, (int, long)):
|
|
out += (el,)
|
|
|
|
elif isinstance(el, tuple):
|
|
out += (el[1],) # XXX Do we need to create a new object el[0]?
|
|
|
|
else:
|
|
raise error.PySmiSemanticError('unknown datatype for OID: %s' % el)
|
|
|
|
return str(self.genNumericOid(out)), parent
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genObjects(self, data, classmode=False):
|
|
if data[0]:
|
|
return [self.transOpers(obj) for obj in data[0]] # XXX self.transOpers or not??
|
|
return []
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genTime(self, data, classmode=False):
|
|
times = []
|
|
for timeStr in data:
|
|
if len(timeStr) == 11:
|
|
timeStr = '19' + timeStr
|
|
# XXX raise in strict mode
|
|
# elif lenTimeStr != 13:
|
|
# raise error.PySmiSemanticError("Invalid date %s" % t)
|
|
try:
|
|
times.append(strftime('%Y-%m-%d %H:%M', strptime(timeStr, '%Y%m%d%H%MZ')))
|
|
|
|
except ValueError:
|
|
# XXX raise in strict mode
|
|
# raise error.PySmiSemanticError("Invalid date %s: %s" % (t, sys.exc_info()[1]))
|
|
timeStr = '197001010000Z' # dummy date for dates with typos
|
|
times.append(strftime('%Y-%m-%d %H:%M', strptime(timeStr, '%Y%m%d%H%MZ')))
|
|
|
|
return times
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genLastUpdated(self, data, classmode=False):
|
|
text = data[0]
|
|
return '.setLastUpdated(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genOrganization(self, data, classmode=False):
|
|
text = self.textFilter('organization', data[0])
|
|
return '.setOrganization(' + dorepr(text) + ')'
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genRevisions(self, data, classmode=False):
|
|
times = self.genTime([x[0] for x in data[0]])
|
|
times = [dorepr(x) for x in times]
|
|
|
|
revisions = '.setRevisions((%s,))' % ', '.join(times)
|
|
|
|
descriptions = '.setRevisionsDescriptions((%s,))' % ', '.join(
|
|
[dorepr(self.textFilter('description', x[1][1])) for x in data[0]]
|
|
)
|
|
|
|
lastRevision = data[0][0][0]
|
|
|
|
return lastRevision, revisions, descriptions
|
|
|
|
def genRow(self, data, classmode=False):
|
|
row = data[0]
|
|
row = self.transOpers(row)
|
|
return row in self.symbolTable[self.moduleName[0]]['_symtable_rows'] and (
|
|
'MibTableRow', '') or self.genSimpleSyntax(data, classmode=classmode)
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genSequence(self, data, classmode=False):
|
|
cols = data[0]
|
|
self._cols.update(cols)
|
|
return '', ''
|
|
|
|
def genSimpleSyntax(self, data, classmode=False):
|
|
objType = data[0]
|
|
objType = self.typeClasses.get(objType, objType)
|
|
objType = self.transOpers(objType)
|
|
|
|
subtype = len(data) == 2 and data[1] or ''
|
|
|
|
if classmode:
|
|
subtype = '%s' in subtype and subtype % objType or subtype # XXX hack?
|
|
return objType, subtype
|
|
|
|
outStr = objType + '()' + subtype
|
|
|
|
return 'MibScalar', outStr
|
|
|
|
# noinspection PyUnusedLocal
|
|
def genTypeDeclarationRHS(self, data, classmode=False):
|
|
if len(data) == 1:
|
|
parentType, attrs = data[0] # just syntax
|
|
|
|
else:
|
|
# Textual convention
|
|
display, status, description, reference, syntax = data
|
|
parentType, attrs = syntax
|
|
|
|
if parentType in self._snmpTypes:
|
|
parentType = 'TextualConvention, ' + parentType
|
|
|
|
if display:
|
|
attrs = display + attrs
|
|
|
|
if status:
|
|
attrs = status + attrs
|
|
|
|
if self.genRules['text'] and description:
|
|
attrs = description + attrs
|
|
|
|
if reference:
|
|
attrs = reference + attrs
|
|
|
|
attrs = attrs or self.indent + 'pass\n'
|
|
|
|
return parentType, attrs
|
|
|
|
# noinspection PyMethodMayBeStatic,PyUnusedLocal
|
|
def genUnits(self, data, classmode=False):
|
|
text = data[0]
|
|
return '.setUnits(' + dorepr(self.textFilter('units', text)) + ')'
|
|
|
|
handlersTable = {
|
|
'agentCapabilitiesClause': genAgentCapabilities,
|
|
'moduleIdentityClause': genModuleIdentity,
|
|
'moduleComplianceClause': genModuleCompliance,
|
|
'notificationGroupClause': genNotificationGroup,
|
|
'notificationTypeClause': genNotificationType,
|
|
'objectGroupClause': genObjectGroup,
|
|
'objectIdentityClause': genObjectIdentity,
|
|
'objectTypeClause': genObjectType,
|
|
'trapTypeClause': genTrapType,
|
|
'typeDeclaration': genTypeDeclaration,
|
|
'valueDeclaration': genValueDeclaration,
|
|
|
|
'ApplicationSyntax': genSimpleSyntax,
|
|
'BitNames': genBitNames,
|
|
'BITS': genBits,
|
|
'ComplianceModules': genCompliances,
|
|
'conceptualTable': genConceptualTable,
|
|
'CONTACT-INFO': genContactInfo,
|
|
'DISPLAY-HINT': genDisplayHint,
|
|
'DEFVAL': genDefVal,
|
|
'DESCRIPTION': genDescription,
|
|
'REFERENCE': genReference,
|
|
'Status': genStatus,
|
|
'PRODUCT-RELEASE': genProductRelease,
|
|
'enumSpec': genEnumSpec,
|
|
'INDEX': genTableIndex,
|
|
'integerSubType': genIntegerSubType,
|
|
'MaxAccessPart': genMaxAccess,
|
|
'Notifications': genObjects,
|
|
'octetStringSubType': genOctetStringSubType,
|
|
'objectIdentifier': genOid,
|
|
'Objects': genObjects,
|
|
'LAST-UPDATED': genLastUpdated,
|
|
'ORGANIZATION': genOrganization,
|
|
'Revisions': genRevisions,
|
|
'row': genRow,
|
|
'SEQUENCE': genSequence,
|
|
'SimpleSyntax': genSimpleSyntax,
|
|
'typeDeclarationRHS': genTypeDeclarationRHS,
|
|
'UNITS': genUnits,
|
|
'VarTypes': genObjects,
|
|
# 'a': lambda x: genXXX(x, 'CONSTRAINT')
|
|
}
|
|
|
|
def genCode(self, ast, symbolTable, **kwargs):
|
|
self.genRules['text'] = kwargs.get('genTexts', False)
|
|
self.textFilter = kwargs.get('textFilter') or (lambda symbol, text: re.sub('\s+', ' ', text))
|
|
self.symbolTable = symbolTable
|
|
self._rows.clear()
|
|
self._cols.clear()
|
|
self._exports.clear()
|
|
self._seenSyms.clear()
|
|
self._importMap.clear()
|
|
self._out.clear()
|
|
self._moduleIdentityOid = None
|
|
self.moduleName[0], moduleOid, imports, declarations = ast
|
|
|
|
out, importedModules = self.genImports(imports or {})
|
|
|
|
for declr in declarations or []:
|
|
if declr:
|
|
clausetype = declr[0]
|
|
classmode = clausetype == 'typeDeclaration'
|
|
self.handlersTable[declr[0]](self, self.prepData(declr[1:], classmode), classmode)
|
|
|
|
for sym in self.symbolTable[self.moduleName[0]]['_symtable_order']:
|
|
if sym not in self._out:
|
|
raise error.PySmiCodegenError('No generated code for symbol %s' % sym)
|
|
out += self._out[sym]
|
|
|
|
out += self.genExports()
|
|
|
|
if 'comments' in kwargs:
|
|
out = ''.join(['# %s\n' % x for x in kwargs['comments']]) + '#\n' + out
|
|
out = '#\n# PySNMP MIB module %s (http://snmplabs.com/pysmi)\n' % self.moduleName[0] + out
|
|
|
|
debug.logger & debug.flagCodegen and debug.logger(
|
|
'canonical MIB name %s (%s), imported MIB(s) %s, Python code size %s bytes' % (
|
|
self.moduleName[0], moduleOid, ','.join(importedModules) or '<none>', len(out)))
|
|
|
|
return MibInfo(oid=moduleOid,
|
|
identity=self._moduleIdentityOid,
|
|
name=self.moduleName[0],
|
|
revision=self._moduleRevision,
|
|
oids=[],
|
|
enterprise=None,
|
|
compliance=[],
|
|
imported=tuple([x for x in importedModules if x not in self.fakeMibs])), out
|
|
|
|
def genIndex(self, processed, **kwargs):
|
|
out = '\nfrom pysnmp.proto.rfc1902 import ObjectName\n\noidToMibMap = {\n'
|
|
count = 0
|
|
for module, status in processed.items():
|
|
value = getattr(status, 'oid', None)
|
|
if value:
|
|
out += 'ObjectName("%s"): "%s",\n' % (value, module)
|
|
count += 1
|
|
out += '}\n'
|
|
|
|
if 'comments' in kwargs:
|
|
out = ''.join(['# %s\n' % x for x in kwargs['comments']]) + '#\n' + out
|
|
out = '#\n# PySNMP MIB indices (http://snmplabs.com/pysmi)\n' + out
|
|
|
|
debug.logger & debug.flagCodegen and debug.logger(
|
|
'OID->MIB index built, %s entries, %s bytes' % (count, len(out)))
|
|
|
|
return out
|
|
|
|
# backward compatibility
|
|
baseMibs = PySnmpCodeGen.baseMibs
|
|
fakeMibs = PySnmpCodeGen.fakeMibs
|