Mini Shell
#
# 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
try:
import json
except ImportError:
import simplejson as json
try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict
from pysmi.mibinfo import MibInfo
from pysmi.codegen.base import AbstractCodeGen
from pysmi import error
from pysmi import debug
if sys.version_info[0] > 2:
# noinspection PyShadowingBuiltins
unicode = str
# noinspection PyShadowingBuiltins
long = int
class JsonCodeGen(AbstractCodeGen):
"""Builds JSON document 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*.
"""
constImports = {
'SNMPv2-SMI': ('iso',
'NOTIFICATION-TYPE', # bug in some MIBs (e.g. A3COM-HUAWEI-DHCPSNOOP-MIB)
'MODULE-IDENTITY', 'OBJECT-TYPE', 'OBJECT-IDENTITY'),
'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') + AbstractCodeGen.baseMibs
baseTypes = ['Integer', 'Integer32', 'Bits', 'ObjectIdentifier', 'OctetString']
typeClasses = {
'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']
indent = ' ' * 4
fakeidx = 1000 # starting index for fake symbols
def __init__(self):
self._rows = set()
self._cols = {} # k, v = name, datatype
self._seenSyms = set()
self._importMap = {}
self._out = {} # k, v = name, generated code
self._moduleIdentityOid = None
self._moduleRevision = None
self._enterpriseOid = None
self._oids = set()
self._complianceOids = []
self.moduleName = ['DUMMY']
self.genRules = {'text': True}
self.symbolTable = {}
@staticmethod
def transOpers(symbol):
return symbol.replace('-', '_')
def prepData(self, pdata):
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:]))
)
return data
def genImports(self, imports):
# convertion 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]
outDict = OrderedDict()
outDict['class'] = 'imports'
for module in sorted(imports):
symbols = []
for symbol in set(imports[module]):
symbols.append(symbol)
if symbols:
self._seenSyms.update(
[self.transOpers(s) for s in symbols]
)
self._importMap.update(
[(self.transOpers(s), module) for s in symbols]
)
if module not in outDict:
outDict[module] = []
outDict[module].extend(symbols)
return OrderedDict(imports=outDict), tuple(sorted(imports))
# noinspection PyMethodMayBeStatic
def genLabel(self, symbol):
return '-' in symbol and symbol or ''
def addToExports(self, symbol, moduleIdentity=0):
self._seenSyms.add(symbol)
# noinspection PyUnusedLocal
def regSym(self, symbol, outDict, parentOid=None, moduleIdentity=False, moduleCompliance=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] = outDict
if 'oid' in outDict:
self._oids.add(outDict['oid'])
if not self._enterpriseOid and outDict['oid'].startswith('1.3.6.1.4.1.'):
self._enterpriseOid = '.'.join(outDict['oid'].split('.')[:7])
if moduleIdentity:
if self._moduleIdentityOid:
raise error.PySmiSemanticError('Duplicate module identity')
self._moduleIdentityOid = outDict['oid']
if moduleCompliance:
self._complianceOids.append(outDict['oid'])
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):
name, productRelease, status, description, reference, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'agentcapabilities'
if productRelease:
outDict['productrelease'] = productRelease
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genModuleIdentity(self, data):
name, lastUpdated, organization, contactInfo, description, revisions, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'moduleidentity'
if revisions:
outDict['revisions'] = revisions
self._moduleRevision = revisions[0]['revision']
if self.genRules['text']:
if lastUpdated:
outDict['lastupdated'] = lastUpdated
if organization:
outDict['organization'] = organization
if contactInfo:
outDict['contactinfo'] = contactInfo
if description:
outDict['description'] = description
self.regSym(name, outDict, parentOid, moduleIdentity=True)
return outDict
# noinspection PyUnusedLocal
def genModuleCompliance(self, data):
name, status, description, reference, compliances, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'modulecompliance'
if compliances:
outDict['modulecompliance'] = compliances
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid, moduleCompliance=True)
return outDict
# noinspection PyUnusedLocal
def genNotificationGroup(self, data):
name, objects, status, description, reference, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'notificationgroup'
if objects:
outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genNotificationType(self, data):
name, objects, status, description, reference, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'notificationtype'
if objects:
outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genObjectGroup(self, data):
name, objects, status, description, reference, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict({'name': name,
'oid': oidStr,
'class': 'objectgroup'})
if objects:
outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genObjectIdentity(self, data):
name, status, description, reference, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'objectidentity'
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genObjectType(self, data):
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 ('', '', [])
defval = self.genDefVal(defval, objname=name)
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
if syntax[0]:
nodetype = syntax[0] == 'Bits' and 'scalar' or syntax[0] # Bits hack
nodetype = name in self.symbolTable[self.moduleName[0]]['_symtable_cols'] and 'column' or nodetype
outDict['nodetype'] = nodetype
outDict['class'] = 'objecttype'
if syntax[1]:
outDict['syntax'] = syntax[1]
if defval:
outDict['default'] = defval
if units:
outDict['units'] = units
if maxaccess:
outDict['maxaccess'] = maxaccess
if indexStr:
outDict['indices'] = indexStr
if self.genRules['text'] and reference:
outDict['reference'] = reference
if augmention:
augmention = self.transOpers(augmention)
outDict['augmention'] = OrderedDict()
outDict['augmention']['name'] = name
outDict['augmention']['module'] = self.moduleName[0]
outDict['augmention']['object'] = augmention
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
self.regSym(name, outDict, parentOid)
# TODO
# if fakeSyms: # fake symbols for INDEX to support SMIv1
# for i in range(len(fakeSyms)):
# fakeOutStr = fakeStrlist[i] % oidStr
# self.regSym(fakeSyms[i], fakeOutStr, name)
return outDict
# noinspection PyUnusedLocal
def genTrapType(self, data):
name, enterprise, variables, description, reference, value = data
label = self.genLabel(name)
name = self.transOpers(name)
enterpriseStr, parentOid = enterprise
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = enterpriseStr + '0.' + str(value)
outDict['class'] = 'notificationtype'
if variables:
outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in variables]
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
self.regSym(name, outDict, parentOid)
return outDict
# noinspection PyUnusedLocal
def genTypeDeclaration(self, data):
name, declaration = data
outDict = OrderedDict()
outDict['name'] = name
outDict['class'] = 'type'
if declaration:
parentType, attrs = declaration
if parentType: # skipping SEQUENCE case
name = self.transOpers(name)
outDict.update(attrs)
self.regSym(name, outDict)
return outDict
# noinspection PyUnusedLocal
def genValueDeclaration(self, data):
name, oid = data
label = self.genLabel(name)
name = self.transOpers(name)
oidStr, parentOid = oid
outDict = OrderedDict()
outDict['name'] = name
outDict['oid'] = oidStr
outDict['class'] = 'objectidentity'
self.regSym(name, outDict, parentOid)
return outDict
# Subparts generation functions
# noinspection PyMethodMayBeStatic,PyUnusedLocal
def genBitNames(self, data):
names = data[0]
return names
def genBits(self, data):
bits = data[0]
outDict = OrderedDict()
outDict['type'] = 'Bits'
outDict['class'] = 'type'
outDict['bits'] = OrderedDict()
for name, bit in sorted(bits, key=lambda x: x[1]):
outDict['bits'][name] = bit
return 'scalar', outDict
# noinspection PyUnusedLocal
def genCompliances(self, data):
compliances = []
for complianceModule in data[0]:
name = complianceModule[0] or self.moduleName[0]
compliances += [{'object': self.transOpers(compl), 'module': name} for compl in complianceModule[1]]
return compliances
# noinspection PyUnusedLocal
def genConceptualTable(self, data):
row = data[0]
if row[1] and row[1][-2:] == '()':
row = row[1][:-2]
self._rows.add(row)
return 'table', ''
# noinspection PyMethodMayBeStatic,PyUnusedLocal
def genContactInfo(self, data):
text = data[0]
return self.textFilter('contact-info', text)
# noinspection PyUnusedLocal
def genDisplayHint(self, data):
return data[0]
# noinspection PyUnusedLocal
def genDefVal(self, data, objname=None):
if not data:
return {}
if not objname:
return data
outDict = OrderedDict()
defval = data[0]
defvalType = self.getBaseType(objname, self.moduleName[0])
if isinstance(defval, (int, long)): # number
outDict.update(value=defval, format='decimal')
elif self.isHex(defval): # hex
if defvalType[0][0] in ('Integer32', 'Integer'): # common bug in MIBs
outDict.update(value=str(int(len(defval) > 3 and defval[1:-2] or '0', 16)), format='hex')
else:
outDict.update(value=defval[1:-2], format='hex')
elif self.isBinary(defval): # binary
binval = defval[1:-2]
if defvalType[0][0] in ('Integer32', 'Integer'): # common bug in MIBs
outDict.update(value=str(int(binval or '0', 2)), format='bin')
else:
hexval = binval and hex(int(binval, 2))[2:] or ''
outDict.update(value=hexval, format='hex')
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 {} # we will set no default value
outDict.update(value=defval[1:-1], format='string')
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']))
outDict.update(value=val, format='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])]
if defval:
outDict.update(value=defval[0], format='enum')
elif defval in dict(defvalType[1]): # good MIB: DEFVAL { ... }
outDict.update(value=defval, format='enum')
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))
outDict.update(value=self.genBits([defvalBits])[1], format='bits')
return outDict
else:
raise error.PySmiSemanticError(
'unknown type "%s" for defval "%s" of symbol "%s"' % (defvalType, defval, objname))
return {'default': outDict}
# noinspection PyMethodMayBeStatic
def genDescription(self, data):
return self.textFilter('description', data[0])
# noinspection PyMethodMayBeStatic
def genReference(self, data):
return self.textFilter('reference', data[0])
# noinspection PyMethodMayBeStatic
def genStatus(self, data):
return data[0]
def genProductRelease(self, data):
return data[0]
def genEnumSpec(self, data):
items = data[0]
return {'enumeration': dict(items)}
# noinspection PyUnusedLocal
def genTableIndex(self, data):
def genFakeSyms(fakeidx, idxType):
objType = self.typeClasses.get(idxType, idxType)
objType = self.transOpers(objType)
return {'module': self.moduleName[0],
object: objType}
indexes = data[0]
idxStrlist, fakeSyms, fakeStrlist = [], [], []
for idx in indexes:
isImplied = idx[0]
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
index = OrderedDict()
index['module'] = self._importMap.get(idxName, self.moduleName[0])
index['object'] = idxName
index['implied'] = isImplied
idxStrlist.append(index)
return idxStrlist, fakeStrlist, fakeSyms
def genIntegerSubType(self, data):
ranges = []
for rng in data[0]:
vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng
vmin, vmax = self.str2int(vmin), self.str2int(vmax)
ran = OrderedDict()
ran['min'] = vmin
ran['max'] = vmax
ranges.append(ran)
return {'range': ranges}
# noinspection PyMethodMayBeStatic,PyUnusedLocal
def genMaxAccess(self, data):
return data[0]
def genOctetStringSubType(self, data):
sizes = []
for rng in data[0]:
vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng
vmin, vmax = self.str2int(vmin), self.str2int(vmax)
size = OrderedDict()
size['min'] = vmin
size['max'] = vmax
sizes.append(size)
return {'size': sizes}
# noinspection PyUnusedLocal
def genOid(self, data):
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 '.'.join([str(x) for x in self.genNumericOid(out)]), parent
# noinspection PyUnusedLocal
def genObjects(self, data):
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):
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):
return data[0]
# noinspection PyMethodMayBeStatic,PyUnusedLocal
def genOrganization(self, data):
return self.textFilter('organization', data[0])
# noinspection PyUnusedLocal
def genRevisions(self, data):
revisions = []
for x in data[0]:
revision = OrderedDict()
revision['revision'] = self.genTime([x[0]])[0]
revision['description'] = self.textFilter('description', x[1][1])
revisions.append(revision)
return revisions
def genRow(self, data):
row = data[0]
row = self.transOpers(row)
return row in self.symbolTable[self.moduleName[0]]['_symtable_rows'] and (
'row', '') or self.genSimpleSyntax(data)
# noinspection PyUnusedLocal
def genSequence(self, data):
cols = data[0]
self._cols.update(cols)
return '', ''
def genSimpleSyntax(self, data):
objType = data[0]
objType = self.typeClasses.get(objType, objType)
objType = self.transOpers(objType)
subtype = len(data) == 2 and data[1] or {}
outDict = OrderedDict()
outDict['type'] = objType
outDict['class'] = 'type'
if subtype:
outDict['constraints'] = subtype
return 'scalar', outDict
# noinspection PyUnusedLocal
def genTypeDeclarationRHS(self, data):
if len(data) == 1:
parentType, attrs = data[0]
outDict = OrderedDict()
if not attrs:
return outDict
# just syntax
outDict['type'] = attrs
else:
# Textual convention
display, status, description, reference, syntax = data
parentType, attrs = syntax
outDict = OrderedDict()
outDict['type'] = attrs
outDict['class'] = 'textualconvention'
if display:
outDict['displayhint'] = display
if status:
outDict['status'] = status
if self.genRules['text'] and description:
outDict['description'] = description
if self.genRules['text'] and reference:
outDict['reference'] = reference
return parentType, outDict
# noinspection PyMethodMayBeStatic,PyUnusedLocal
def genUnits(self, data):
text = data[0]
return 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,
'PRODUCT-RELEASE': genProductRelease,
'ApplicationSyntax': genSimpleSyntax,
'BitNames': genBitNames,
'BITS': genBits,
'ComplianceModules': genCompliances,
'conceptualTable': genConceptualTable,
'CONTACT-INFO': genContactInfo,
'DISPLAY-HINT': genDisplayHint,
'DEFVAL': genDefVal,
'DESCRIPTION': genDescription,
'REFERENCE': genReference,
'Status': genStatus,
'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._seenSyms.clear()
self._importMap.clear()
self._out.clear()
self._moduleIdentityOid = None
self._enterpriseOid = None
self._oids = set()
self._complianceOids = []
self.moduleName[0], moduleOid, imports, declarations = ast
outDict, importedModules = self.genImports(imports and imports or {})
for declr in declarations or []:
if declr:
self.handlersTable[declr[0]](self, self.prepData(declr[1:]))
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)
outDict[sym] = self._out[sym]
if 'comments' in kwargs:
outDict['meta'] = OrderedDict()
outDict['meta']['comments'] = kwargs['comments']
outDict['meta']['module'] = self.moduleName[0]
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(outDict)))
return MibInfo(oid=moduleOid,
identity=self._moduleIdentityOid,
name=self.moduleName[0],
revision=self._moduleRevision,
oids=self._oids,
enterprise=self._enterpriseOid,
compliance=self._complianceOids,
imported=tuple([x for x in importedModules if x not in self.fakeMibs])), json.dumps(outDict, indent=2)
def genIndex(self, processed, **kwargs):
outDict = {
'meta': {},
'identity': {},
'enterprise': {},
'compliance': {},
'oids': {},
}
if kwargs.get('old_index_data'):
try:
outDict.update(
json.loads(kwargs['old_index_data'])
)
except Exception:
raise error.PySmiCodegenError('Index load error: %s' % sys.exc_info()[1])
def order(top):
if isinstance(top, dict):
new_top = OrderedDict()
try:
# first try to sort keys as OIDs
for k in sorted(top, key=lambda x: [int(y) for y in x.split('.')]):
new_top[k] = order(top[k])
except ValueError:
for k in sorted(top):
new_top[k] = order(top[k])
return new_top
elif isinstance(top, list):
new_top = []
for e in sorted(set(top)):
new_top.append(order(e))
return new_top
return top
for module, status in processed.items():
modData = outDict['identity']
identity_oid = getattr(status, 'identity', None)
if identity_oid:
if identity_oid not in modData:
modData[identity_oid] = []
modData[identity_oid].append(module)
modData = outDict['enterprise']
enterprise_oid = getattr(status, 'enterprise', None)
if enterprise_oid:
if enterprise_oid not in modData:
modData[enterprise_oid] = []
modData[enterprise_oid].append(module)
modData = outDict['compliance']
compliance_oids = getattr(status, 'compliance', ())
for compliance_oid in compliance_oids:
if compliance_oid not in modData:
modData[compliance_oid] = []
modData[compliance_oid].append(module)
modData = outDict['oids']
objects_oids = getattr(status, 'oids', ())
for object_oid in objects_oids:
if object_oid not in modData:
modData[object_oid] = []
modData[object_oid].append(module)
if modData:
unique_prefixes = {}
for oid in sorted(modData, key=lambda x: x.count('.')):
for oid_prefix, modules in unique_prefixes.items():
if oid.startswith(oid_prefix) and set(modules).issuperset(modData[oid]):
break
else:
unique_prefixes[oid] = modData[oid]
outDict['oids'] = unique_prefixes
if 'comments' in kwargs:
outDict['meta']['comments'] = kwargs['comments']
debug.logger & debug.flagCodegen and debug.logger(
'OID->MIB index built, %s entries' % len(processed))
return json.dumps(order(outDict), indent=2)
Zerion Mini Shell 1.0