[
  {
    "path": ".bandit.yml",
    "content": "skips:\n- B603  # Ignore warnings about calling subprocess.Popen without shell=True\n- B607  # Ignore warnings about calling subprocess.Popen without a full path to executable\n"
  },
  {
    "path": ".flake8.ini",
    "content": "[flake8]\nshow-source = True\n# E123, E125 seem invalid\nignore = E123,E125,D104,D100,D101,D102,D103,D106,D107,D412,W504\n#enable-extensions=H106,H203,H204,H205,H210,H904\nbuiltins = _\nexclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "custom: http://snmplabs.com/sponsorship.html\n"
  },
  {
    "path": ".gitignore",
    "content": "# Python stuff\n*.pyc\n__pycache__\n\n# vim swapfiles\n*.sw?\n\n# python packaging\nMANIFEST\ndist/\nbuild/\n*.egg-info/\n\n# PyCharm stuff\n.idea/\n\n# Sphinx template\ndocs/source/.templates/layout.html\n\n# Eclipse stuff\n.project\n.pydevproject\n\n# Virtual envs\nvenv*\n\n.coverage\n.tox/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: python\ncache: pip\nmatrix:\n  include:\n  - os: linux\n    dist: trusty\n    python: '2.6'\n  - os: linux\n    dist: trusty\n    python: '2.7'\n  # Jinja seems to be broken on py3.2\n#  - os: linux\n#    dist: trusty\n#    python: '3.2'\n  - os: linux\n    dist: trusty\n    python: '3.3'\n  - os: linux\n    dist: trusty\n    python: '3.4'\n  - os: linux\n    dist: trusty\n    python: '3.5'\n  - os: linux\n    dist: trusty\n    python: '3.6'\n  - os: linux\n    dist: xenial\n    python: '3.7'\n  - os: linux\n    dist: trusty\n    python: 'nightly'\n  - os: linux\n    dist: trusty\n    python: 'pypy'\n  - os: linux\n    dist: trusty\n    python: 'pypy3'\ninstall:\n  - pip install codecov\n  - pip install -r requirements.txt -r devel-requirements.txt\n  - pip install -e .\nscript:\n  - PYTHONPATH=.:$PYTHONPATH python tests/__main__.py\nafter_success:\n  - PYTHONPATH=.:$PYTHONPATH coverage run --omit=*test* tests/__main__.py\n  - codecov\n"
  },
  {
    "path": "CHANGES.rst",
    "content": "Revision 0.4.0, XX-03-2020\n--------------------------\n\n- Introduced Jinja2 templates for code generation.\n\n  This change significantly refactors the way how code generation\n  works. Previously, pysmi code generator has been responsible for\n  producing a well-formed text document (e.g. JSON or pysnmp).\n\n  With this change, all code generations should be done through\n  Jinja2 templates by rendering them in the context of the parsed MIB\n  taking shape of the intermediate MIB representation which other parts\n  of pysmi provide.\n\n- By way of moving pysnmp code generation to Jinja2 template, the\n  Python code layout of pysnmp modules improved dramatically - it\n  is just one little step from being PEP8-compliant.\n\n- The template-based pysnmp code generator drops some backward\n  compatibility aids that keep Python MIB modules compatible with\n  older pysnmp versions. Perhaps in the followup patch we should\n  make the Python MIB module failing early and clearly on import\n  when it's old pysnmp importing it.\n\n- Jinja does not seem to work well with Python < 2.6 and Python == 3.2.\n  Despite pysmi is trying to support those Python versions, it may\n  start to fail on them due to Jinja failures.\n\n- Introduced SNMP agent code hooks generation template allowing\n  building a functional skeleton of the Python module from a\n  given ASN.1 MIB. The tapping points include SMI Managed Object\n  read/readnext/write/create and destroy work flows.\n\nRevision 0.3.5, XX-03-2020\n--------------------------\n\n- Added tox runner with a handful of basic jobs\n- Copyright notice extended to the year 2020\n- Fixed MIB file load by URI on Windows\n\nRevision 0.3.4, 14-04-2019\n--------------------------\n\n- Added `implied` key to JSON SNMP table index structure\n- Rebased MIB importing code onto `importlib` because `imp` is long\n  deprecated\n- Fixed Py file borrower to become functional\n\nRevision 0.3.3, 29-12-2018\n--------------------------\n\n- Added mibcopy.py documentation\n- Copyright notice bumped up to year 2019\n\nRevision 0.3.2, 22-10-2018\n--------------------------\n\n- Bumped upper Python version to 3.7 and enabled pip cache\n- Exit code indication of the command-line tools aligned with\n  sysexits.h to report more useful termination status\n\nRevision 0.3.1, 10-06-2018\n--------------------------\n\n- Fixed pysnmp lower version in test-requirements.txt\n- Fixed compiler crash when building comments at a platform which\n  has broken users/groups databases\n\nRevision 0.3.0, 29-04-2018\n--------------------------\n\n- The `mibcopy` tool implemented to copy MIB modules from files with\n  potentially messed up names into a directory under canonical MIB\n  names picking up the latest MIB revision along the way.\n- ZIP archive reader implemented to pull ASN.1 MIB files from .zip\n  archives pretty much in the same way as from plain directories\n- HTTP/S proxy support added (through respecting `http_proxy` environment\n  variable) by switching from `httplib` to `urllib2` internally\n- Copyright notice bumped up to year 2018\n- Project site in the docs changes from SourceForge to snmplabs.com\n- PRODUCT-RELEASE generation added to the JSON code generator\n- Added special handling of BITS-like DEFVAL syntax for Integers\n  that occurs in buggy MIBs\n- Fixed missing REVISIONS generations in MODULE-IDENTITY\n\nRevision 0.2.2, 13-11-2017\n--------------------------\n\n- Library documentation refactored and updated\n- Fixed malformed Python code being produced by pysnmp code generator\n\nRevision 0.2.1, 11-11-2017\n--------------------------\n\n- Added MIB *status*, *product release* and *revision description* set\n  calls at pysnmp code generator\n- Changed REVISION field format in JSON representation - it is now\n  a list of dicts each with *revision* timestamp and *description* text\n- MIB REFERENCE fields are only exported if --with-mib-text is on\n- Sphinx documentation theme changed to Alabaster\n- Multiple fixes to pysnmp codegen not to produce function calls\n  with more than 255 parameters\n\nRevision 0.1.4, 14-10-2017\n--------------------------\n\n- Fix to SMI lexer to treat tokens starting from a digit as belonging\n  to a lower-cased class. This fixes sub-OID parsing bug (specifically,\n  802dot3(10006))\n- Fix to the mibdump.py local MIB path automatic injection in front\n  of existing --mib-sources\n\nRevision 0.1.3, 19-05-2017\n--------------------------\n\n* INET-ADDRESS-MIB configured as pre-built at pysnmp codegen\n* JSON codegen produces \"nodetype\" element for OBJECT-TYPE\n* Fix to mibdump.py --destination-directory option\n* Fix to pysnmp and JSON code generators to properly refer to MIB module\n  defining particular MIB object\n\nRevision 0.1.2, 12-04-2017\n--------------------------\n\n* The @mib@ magic in reader's URL template made optional. If it is not present,\n  MIB module name is just appended to URL template\n* Send User-Agent containing pysmi and Python versions as well as platform name.\n* Fixed missing STATUS/DISPLAY-HINT/REFERENCE/etc fields generation at pysnmp\n  backend when running in the non-full-text mode\n* Fixed broken `ordereddict` dependency on Python 2.6-\n\nRevision 0.1.1, 30-03-2017\n--------------------------\n\n* Generate REFERENCE and STATUS fields at various SMI objects\n* Generate DESCRIPTION field followed REVISION field at MODULE-IDENTITY objects\n* Generate PRODUCT-RELEASE field at AGENT-CAPABILITIES objects\n* Generated Python source aligned with PEP8\n* MIB texts cleaned up by default, --keep-texts-layout preserves original formatting\n* Fix to the `ordereddict` conditional dependency\n* Missing test module recovered\n* Failing tests fixed\n\nRevision 0.1.0, 25-03-2017\n--------------------------\n\n* JSON code generating backend implemented\n* Experimental JSON OID->MIB indices generation implemented\n* Package structure flattened for easier use\n* Minor refactoring to the test suite\n* Source code statically analyzed, hardened and PEP8-ized\n* Files closed explicitly to mute ResourceWarnings\n* Fixed to Python 2.4 (and aged ply) compatibility\n* Added a workaround to avoid generating pysnmp TextualConvention classes\n  inheriting from TextualConvention (when MIB defines a TEXTUAL-CONVENTION\n  based on another TEXTUAL-CONVENTION as SYNTAX)\n* Author's e-mail changed, copyright extended to year 2017\n\nRevision 0.0.7, 12-02-2016\n--------------------------\n\n* Crash on existing .py file handling fixed.\n* Fix to __doc__ use in setup.py to make -O0 installation mode working.\n* Fix to PyPackageSearcher not to fail on broken Python packages.\n* Source code pep8'ed\n* Copyright added to source files.\n\nRevision 0.0.6, 01-10-2015\n--------------------------\n\n* Several typos fixed, source code linted again.\n* Some dead code cleaned up.\n\nRevision 0.0.5, 28-09-2015\n--------------------------\n\n* Wheel distribution format now supported.\n* Handle the case of MIB symbols conflict with Python reserved words.\n* Handle binary DEFVAL initializer for INTEGER's.\n* Generate LAST-UPDATED at pysnmp code generator.\n\nRevision 0.0.4, 01-07-2015\n--------------------------\n\n* Fix to MRO compliance for mixin classes generation at pysnmp backend\n* Fix to repeated imports in generated code at pysnmp backend\n* Fix to mibdump tool to properly handle the --generate-mib-texts option.\n* Fix to Python compile() - optimize flag is valid only past Python 3.1\n* Fix to SMIv1 INDEX clause code generation for pysnmp backend.\n* Tighten file creation security at pysmi.writer.pyfile\n\nRevision 0.0.3, 28-06-2015\n--------------------------\n\n* Two-pass compiler design allows for much accurate code generation.\n* Sphinx-based documentation first introduced\n\nRevision 0.0.0, 11-04-2015\n--------------------------\n\n* First public release, not fully operational yet\n"
  },
  {
    "path": "LICENSE.rst",
    "content": "Copyright (c) 2015-2020 Ilya Etingof <etingof@gmail.com>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, \n    this list of conditions and the following disclaimer.\n\n  * Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE \nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE \nARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\nLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\nSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\nINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\nCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE. \n"
  },
  {
    "path": "MANIFEST.in",
    "content": "include *.txt *.rst *.md\nrecursive-include tests *.py\nrecursive-include examples *.py\nrecursive-include docs *.txt *.rst *.svg *.py Makefile\n"
  },
  {
    "path": "README.md",
    "content": "\nSNMP MIB parser\n---------------\n[![Python Versions](https://img.shields.io/pypi/pyversions/pysmi.svg)](https://pypi.org/project/pysmi/)\n[![Build status](https://travis-ci.org/etingof/pysmi.svg?branch=master)](https://secure.travis-ci.org/etingof/pysmi)\n[![Coverage Status](https://img.shields.io/codecov/c/github/etingof/pysmi.svg)](https://codecov.io/github/etingof/pysmi)\n[![GitHub license](https://img.shields.io/badge/license-BSD-blue.svg)](https://raw.githubusercontent.com/etingof/pysmi/master/LICENSE.rst)\n\nPySMI is a pure-Python implementation of\n[SNMP SMI](https://en.wikipedia.org/wiki/Management_information_base) MIB parser.\nThis tool is designed to turn ASN.1 MIBs into various formats. As of this moment,\nJSON and [pysnmp](https://github.com/etingof/pysnmp) modules can be generated\nfrom ASN.1 MIBs.\n\nFeatures\n--------\n\n* Understands SMIv1, SMIv2 and de-facto SMI dialects\n* Turns MIBs into pysnmp classes and JSON documents\n* Maintains an index of MIB objects over many MIB modules\n* Automatically pulls ASN.1 MIBs from local directories, ZIP archives,\n  HTTP and FTP servers\n* 100% Python, works with Python 2.4 up to Python 3.7\n\nRendered PySMI documentation can be found at [pysmi site](http://snmplabs.com/pysmi).\n\nHow to use PySMI\n----------------\n\nIf you are using pysnmp, you might never notice pysmi presence - pysnmp\ncalls pysmi for MIB download and compilation behind the scenes (you can\nstill can do that manually by invoking *mibdump.py* tool).\n\nTo turn ASN.1 MIB into a JSON document, call *mibdump.py* tool like this:\n\n```\n$ mibdump.py --generate-mib-texts  --destination-format json IF-MIB\nSource MIB repositories: file:///usr/share/snmp/mibs, http://mibs.snmplabs.com/asn1/@mib@\nBorrow missing/failed MIBs from: http://mibs.snmplabs.com/json/fulltexts/@mib@\nExisting/compiled MIB locations: \nCompiled MIBs destination directory: .\nMIBs excluded from code generation: RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI,\nRFC1158-MIB, RFC1213-MIB, SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC, SNMPv2-TM\nMIBs to compile: IF-MIB\nDestination format: json\nParser grammar cache directory: not used\nAlso compile all relevant MIBs: yes\nRebuild MIBs regardless of age: yes\nDo not create/update MIBs: no\nByte-compile Python modules: no (optimization level no)\nIgnore compilation errors: no\nGenerate OID->MIB index: no\nGenerate texts in MIBs: yes\nKeep original texts layout: no\nTry various filenames while searching for MIB module: yes\nCreated/updated MIBs: IANAifType-MIB, IF-MIB, SNMPv2-MIB\nPre-compiled MIBs borrowed: \nUp to date MIBs: SNMPv2-CONF, SNMPv2-SMI, SNMPv2-TC\nMissing source MIBs: \nIgnored MIBs: \nFailed MIBs: \n```\n\nJSON document build from\n[IF-MIB module](http://mibs.snmplabs.com/asn1/IF-MIB)\nwould hold information such as:\n\n```\n   {\n      \"ifMIB\": {\n          \"name\": \"ifMIB\",\n          \"oid\": \"1.3.6.1.2.1.31\",\n          \"class\": \"moduleidentity\",\n          \"revisions\": [\n            \"2007-02-15 00:00\",\n            \"1996-02-28 21:55\",\n            \"1993-11-08 21:55\"\n          ]\n        },\n      ...\n      \"ifTestTable\": {\n        \"name\": \"ifTestTable\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3\",\n        \"nodetype\": \"table\",\n        \"class\": \"objecttype\",\n        \"maxaccess\": \"not-accessible\"\n      },\n      \"ifTestEntry\": {\n        \"name\": \"ifTestEntry\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3.1\",\n        \"nodetype\": \"row\",\n        \"class\": \"objecttype\",\n        \"maxaccess\": \"not-accessible\",\n        \"augmention\": {\n          \"name\": \"ifTestEntry\",\n          \"module\": \"IF-MIB\",\n          \"object\": \"ifEntry\"\n        }\n      },\n      \"ifTestId\": {\n        \"name\": \"ifTestId\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3.1.1\",\n        \"nodetype\": \"column\",\n        \"class\": \"objecttype\",\n        \"syntax\": {\n          \"type\": \"TestAndIncr\",\n          \"class\": \"type\"\n        },\n        \"maxaccess\": \"read-write\"\n      },\n      ...\n   }\n```\n\nIn general, converted MIBs capture all aspects of original (ASN.1) MIB contents\nand layout. The snippet above is just a partial example, but here is the\ncomplete [IF-MIB.json](http://mibs.snmplabs.com/json/fulltexts/IF-MIB.json)\nfile.\n\nBesides one-to-one MIB conversion, PySMI library can produce JSON index to\nfacilitate fast MIB information lookup across large collection of MIB files.\nFor example, JSON index for\n[IP-MIB.json](http://mibs.snmplabs.com/json/asn1/IP-MIB),\n[TCP-MIB.json](http://mibs.snmplabs.com/json/asn1/TCP-MIB) and\n[UDP-MIB.json](http://mibs.snmplabs.com/json/asn1/UDP-MIB)\nmodules would keep information like this:\n\n```\n   {\n      \"compliance\": {\n         \"1.3.6.1.2.1.48.2.1.1\": [\n           \"IP-MIB\"\n         ],\n         \"1.3.6.1.2.1.49.2.1.1\": [\n           \"TCP-MIB\"\n         ],\n         \"1.3.6.1.2.1.50.2.1.1\": [\n           \"UDP-MIB\"\n         ]\n      },\n      \"identity\": {\n          \"1.3.6.1.2.1.48\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.49\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.50\": [\n            \"UDP-MIB\"\n          ]\n      },\n      \"oids\": {\n          \"1.3.6.1.2.1.4\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.5\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.6\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.7\": [\n            \"UDP-MIB\"\n          ],\n          \"1.3.6.1.2.1.49\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.50\": [\n            \"UDP-MIB\"\n          ]\n      }\n   }\n```\n\nWith this example, *compliance* and *identity* keys point to\n*MODULE-COMPLIANCE* and *MODULE-IDENTITY* MIB objects, *oids*\nlist top-level OIDs branches defined in MIB modules. Full index\nbuild over thousands of MIBs could be seen\n[here](http://mibs.snmplabs.com/json/index.json).\n\nThe PySMI library can automatically fetch required MIBs from HTTP, FTP sites\nor local directories. You could configure any MIB source available to you (including\n[http://mibs.snmplabs.com/asn1/](http://mibs.snmplabs.com/asn1/)) for that purpose.\n\nHow to get PySMI\n----------------\n\nThe pysmi package is distributed under terms and conditions of 2-clause\nBSD [license](http://snmplabs.com/pysmi/license.html). Source code is freely\navailable as a GitHub [repo](https://github.com/etingof/pysmi).\n\nYou could `pip install pysmi` or download it from [PyPI](https://pypi.org/project/pysmi/).\n\nIf something does not work as expected,\n[open an issue](https://github.com/etingof/pysmi/issues) at GitHub or\npost your question [on Stack Overflow](http://stackoverflow.com/questions/ask).\n\nCopyright (c) 2015-2020, [Ilya Etingof](mailto:etingof@gmail.com).\nAll rights reserved.\n"
  },
  {
    "path": "THANKS.txt",
    "content": "Lars Michelsen\nTanya Tereschenko\n"
  },
  {
    "path": "TODO.txt",
    "content": "* add more tests on edge cases\n* generate reverse OID -> MIB index\n* handle SMIv1 MAX clause in range constraint\n* support MAX clause mapping it into type-specific value\n* possibly split symbol table code generator onto imported modules and symbol\n  table code generators.\n* support more common broken SMI constructs \n* DEFVAL and AUGMENTS should not depend on the order of symbols in MIB\n* make a collection of fixed MIBs (e.g. Huawei has lots of bad/broken MIBs)\n* some MIBs use hex as DEFVAL for types other than OCTET STRING (additional AST processing phase will help)\n* handle the case when the symbol and the enumaration value (which can be in DEFVAL) have the same name - llc2 in NETLINK-SPECIFIC-MIB (additional AST processing phase will help)\n* check imports and try to add necessary ones if missed (like OBJECT-TYPE, MODULE-IDENTITY, etc)\n* generate TextualConvention first or add additional AST processing phase\n* implement a cache of available files at abstract reader path\n* create a command-line tool for splitting MIBs stored in a single file\n* create a MIB querying tool: get MIB module's OIDs, enterprise IDs,\n  canonical name(s); search MIB objects by regexp; build source .index\n* implement xml/html/yaml codegeneration backend\n* write a tool to fetch canonical MIB name from MIB file, rename MIB file, split merged MIBs onto individual files\n* write a tool to turn IANA assigned numbers into JSON\n* introduce cached MIBs invalidation feature -- may be useful when we screw up and produce bad MIBs\n* json codegen:\n  - make schema configurable\n  - further simplify/review codegen code\n  - rebuild the docs\n  - conditionally require simplejson and ordereddict\n  - add tests\n  - is it a good idea to make writers also reading data?\n  - review symtable for unused pieces\n  - write a tool to split json index onto separate documents\n  - index NOTIFICATION-TYPE's\n  - add example script on index build\n"
  },
  {
    "path": "devel-requirements.txt",
    "content": "Sphinx <= 1.6; python_version < '2.7'\nSphinx > 1.6; python_version >= '2.7'\npysnmp < 5.0.0\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nPAPER         =\nBUILDDIR      = build\n\n# User-friendly check for sphinx-build\nifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)\n$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)\nendif\n\n# Internal variables.\nPAPEROPT_a4     = -D latex_paper_size=a4\nPAPEROPT_letter = -D latex_paper_size=letter\nALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n# the i18n builder cannot share the environment and doctrees with the others\nI18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source\n\n.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext\n\nhelp:\n\t@echo \"Please use \\`make <target>' where <target> is one of\"\n\t@echo \"  html       to make standalone HTML files\"\n\t@echo \"  dirhtml    to make HTML files named index.html in directories\"\n\t@echo \"  singlehtml to make a single large HTML file\"\n\t@echo \"  pickle     to make pickle files\"\n\t@echo \"  json       to make JSON files\"\n\t@echo \"  htmlhelp   to make HTML files and a HTML help project\"\n\t@echo \"  qthelp     to make HTML files and a qthelp project\"\n\t@echo \"  applehelp  to make an Apple Help Book\"\n\t@echo \"  devhelp    to make HTML files and a Devhelp project\"\n\t@echo \"  epub       to make an epub\"\n\t@echo \"  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter\"\n\t@echo \"  latexpdf   to make LaTeX files and run them through pdflatex\"\n\t@echo \"  latexpdfja to make LaTeX files and run them through platex/dvipdfmx\"\n\t@echo \"  text       to make text files\"\n\t@echo \"  man        to make manual pages\"\n\t@echo \"  texinfo    to make Texinfo files\"\n\t@echo \"  info       to make Texinfo files and run them through makeinfo\"\n\t@echo \"  gettext    to make PO message catalogs\"\n\t@echo \"  changes    to make an overview of all changed/added/deprecated items\"\n\t@echo \"  xml        to make Docutils-native XML files\"\n\t@echo \"  pseudoxml  to make pseudoxml-XML files for display purposes\"\n\t@echo \"  linkcheck  to check all external links for integrity\"\n\t@echo \"  doctest    to run all doctests embedded in the documentation (if enabled)\"\n\t@echo \"  coverage   to run coverage check of the documentation (if enabled)\"\n\nclean:\n\trm -rf $(BUILDDIR)/*\n\nhtml:\n\t$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/html.\"\n\ndirhtml:\n\t$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml\n\t@echo\n\t@echo \"Build finished. The HTML pages are in $(BUILDDIR)/dirhtml.\"\n\nsinglehtml:\n\t$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml\n\t@echo\n\t@echo \"Build finished. The HTML page is in $(BUILDDIR)/singlehtml.\"\n\npickle:\n\t$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle\n\t@echo\n\t@echo \"Build finished; now you can process the pickle files.\"\n\njson:\n\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json\n\t@echo\n\t@echo \"Build finished; now you can process the JSON files.\"\n\nhtmlhelp:\n\t$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp\n\t@echo\n\t@echo \"Build finished; now you can run HTML Help Workshop with the\" \\\n\t      \".hhp project file in $(BUILDDIR)/htmlhelp.\"\n\nqthelp:\n\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp\n\t@echo\n\t@echo \"Build finished; now you can run \"qcollectiongenerator\" with the\" \\\n\t      \".qhcp project file in $(BUILDDIR)/qthelp, like this:\"\n\t@echo \"# qcollectiongenerator $(BUILDDIR)/qthelp/PySMI.qhcp\"\n\t@echo \"To view the help file:\"\n\t@echo \"# assistant -collectionFile $(BUILDDIR)/qthelp/PySMI.qhc\"\n\napplehelp:\n\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp\n\t@echo\n\t@echo \"Build finished. The help book is in $(BUILDDIR)/applehelp.\"\n\t@echo \"N.B. You won't be able to view it unless you put it in\" \\\n\t      \"~/Library/Documentation/Help or install it in your application\" \\\n\t      \"bundle.\"\n\ndevhelp:\n\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp\n\t@echo\n\t@echo \"Build finished.\"\n\t@echo \"To view the help file:\"\n\t@echo \"# mkdir -p $$HOME/.local/share/devhelp/PySMI\"\n\t@echo \"# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PySMI\"\n\t@echo \"# devhelp\"\n\nepub:\n\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub\n\t@echo\n\t@echo \"Build finished. The epub file is in $(BUILDDIR)/epub.\"\n\nlatex:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo\n\t@echo \"Build finished; the LaTeX files are in $(BUILDDIR)/latex.\"\n\t@echo \"Run \\`make' in that directory to run these through (pdf)latex\" \\\n\t      \"(use \\`make latexpdf' here to do that automatically).\"\n\nlatexpdf:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through pdflatex...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\nlatexpdfja:\n\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex\n\t@echo \"Running LaTeX files through platex and dvipdfmx...\"\n\t$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja\n\t@echo \"pdflatex finished; the PDF files are in $(BUILDDIR)/latex.\"\n\ntext:\n\t$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text\n\t@echo\n\t@echo \"Build finished. The text files are in $(BUILDDIR)/text.\"\n\nman:\n\t$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man\n\t@echo\n\t@echo \"Build finished. The manual pages are in $(BUILDDIR)/man.\"\n\ntexinfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo\n\t@echo \"Build finished. The Texinfo files are in $(BUILDDIR)/texinfo.\"\n\t@echo \"Run \\`make' in that directory to run these through makeinfo\" \\\n\t      \"(use \\`make info' here to do that automatically).\"\n\ninfo:\n\t$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo\n\t@echo \"Running Texinfo files through makeinfo...\"\n\tmake -C $(BUILDDIR)/texinfo info\n\t@echo \"makeinfo finished; the Info files are in $(BUILDDIR)/texinfo.\"\n\ngettext:\n\t$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale\n\t@echo\n\t@echo \"Build finished. The message catalogs are in $(BUILDDIR)/locale.\"\n\nchanges:\n\t$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes\n\t@echo\n\t@echo \"The overview file is in $(BUILDDIR)/changes.\"\n\nlinkcheck:\n\t$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck\n\t@echo\n\t@echo \"Link check complete; look for any errors in the above output \" \\\n\t      \"or in $(BUILDDIR)/linkcheck/output.txt.\"\n\ndoctest:\n\t$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest\n\t@echo \"Testing of doctests in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/doctest/output.txt.\"\n\ncoverage:\n\t$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage\n\t@echo \"Testing of coverage in the sources finished, look at the \" \\\n\t      \"results in $(BUILDDIR)/coverage/python.txt.\"\n\nxml:\n\t$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml\n\t@echo\n\t@echo \"Build finished. The XML files are in $(BUILDDIR)/xml.\"\n\npseudoxml:\n\t$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml\n\t@echo\n\t@echo \"Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml.\"\n"
  },
  {
    "path": "docs/README.txt",
    "content": "You need Sphinx too build this documentation. Or you can read it in ASCII. ;)\n\nBetter run:\n\n# pip sphinx\n\nand once Sphinx is installed on your system, run:\n\n$ make html\n\nTo build a copy of HTML'ed PySMI documentation.\n"
  },
  {
    "path": "docs/source/.static/css/rtdimproved.css",
    "content": "@import url(\"../pygments.css\");\n@import url(\"theme.css\");\n\n/* fix horizontal padding to accomodate adsense banners */\n.wy-nav-content {\n    padding: 1.618em 2.236em;\n    height: 100%;\n    /* max-width: 800px; */\n    margin: auto;\n}\n"
  },
  {
    "path": "docs/source/changelog.rst",
    "content": "\nChangelog\n=========\n\n.. include:: ../../CHANGES.rst\n"
  },
  {
    "path": "docs/source/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# PySMI documentation build configuration file, created by\n# sphinx-quickstart on Sat Jun 27 23:15:54 2015.\n#\n# This file is execfile()d with the current directory set to its\n# containing dir.\n#\n# Note that not all possible configuration values are present in this\n# autogenerated file.\n#\n# All configuration values have a default; values that are commented out\n# serve to show the default.\n\nimport sys\nimport os\nimport shlex\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#sys.path.insert(0, os.path.abspath('.'))\n\n# -- General configuration ------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'sphinx.ext.napoleon',\n    'sphinx.ext.doctest',\n    'sphinx.ext.intersphinx',\n    'sphinx.ext.todo'\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['.templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n# source_suffix = ['.rst', '.md']\nsource_suffix = '.rst'\n\n# The encoding of source files.\n#source_encoding = 'utf-8-sig'\n\n# The master toctree document.\nmaster_doc = 'contents'\n\n# General information about the project.\nproject = u'SNMP SMI compiler'\ncopyright = u'2015-2020, Ilya Etingof <etingof@gmail.com>'\nauthor = u'Ilya Etingof <etingof@gmail.com>'\n\n# The version info for the project you're documenting, acts as replacement for\n# |version| and |release|, also used in various other places throughout the\n# built documents.\n#\n# The short X.Y version.\nversion = '0.1'\n# The full version, including alpha/beta/rc tags.\nrelease = '0.1'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# There are two options for replacing |today|: either, you set today to some\n# non-false value, then it is used:\n#today = ''\n# Else, today_fmt is used as the format for a strftime call.\n#today_fmt = '%B %d, %Y'\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\nexclude_patterns = []\n\n# The reST default role (used for this markup: `text`) to use for all\n# documents.\n#default_role = None\n\n# If true, '()' will be appended to :func: etc. cross-reference text.\n#add_function_parentheses = True\n\n# If true, the current module name will be prepended to all description\n# unit titles (such as .. function::).\n#add_module_names = True\n\n# If true, sectionauthor and moduleauthor directives will be shown in the\n# output. They are ignored by default.\n#show_authors = False\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = 'sphinx'\n\n# A list of ignored prefixes for module index sorting.\n#modindex_common_prefix = []\n\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\n#keep_warnings = False\n\n# If true, `todo` and `todoList` produce output, else they produce nothing.\ntodo_include_todos = True\n\n\n# -- Options for HTML output ----------------------------------------------\n\n# The theme to use for HTML and HTML Help pages.  See the documentation for\n# a list of builtin themes.\nhtml_theme = 'alabaster'\n\n# Theme options are theme-specific and customize the look and feel of a theme\n# further.  For a list of options available for each theme, see the\n# documentation.\n#html_theme_options = { 'collapse_navigation': False }\nhtml_theme_options = {\n    'logo': 'logo.svg',\n    'description': '<p align=left><i><b>Brewing free software for the greater good</i></b></p>',\n    'show_powered_by': False,\n    'github_user': 'etingof',\n    'github_repo': 'pysmi',\n    'fixed_sidebar': True,\n}\n\nhtml_sidebars = {\n    '**': [\n        'about.html',\n        'navigation.html',\n        'relations.html',\n        'searchbox.html',\n        'donate.html',\n    ]\n}\n\n# The name for this set of Sphinx documents.  If None, it defaults to\n# \"<project> v<release> documentation\".\n#html_title = None\n\n# A shorter title for the navigation bar.  Default is the same as html_title.\n#html_short_title = None\n\n# The name of an image file (relative to this directory) to place at the top\n# of the sidebar.\n#html_logo = None\n\n# The name of an image file (within the static path) to use as favicon of the\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\n# pixels large.\nhtml_favicon = '.static/favicon.ico'\n\n# Add any paths that contain custom static files (such as style sheets) here,\n# relative to this directory. They are copied after the builtin static files,\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\nhtml_static_path = ['.static']\n\n# Custom CSS theme\n#html_style = 'css/rtdimproved.css'\n\n# Add any extra paths that contain custom files (such as robots.txt or\n# .htaccess) here, relative to this directory. These files are copied\n# directly to the root of the documentation.\n#html_extra_path = []\n\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\n# using the given strftime format.\n#html_last_updated_fmt = '%b %d, %Y'\n\n# If true, SmartyPants will be used to convert quotes and dashes to\n# typographically correct entities.\n#html_use_smartypants = True\n\n# Custom sidebar templates, maps document names to template names.\n#html_sidebars = {}\n\n# Additional templates that should be rendered to pages, maps page names to\n# template names.\n#html_additional_pages = {}\n\n# If false, no module index is generated.\nhtml_domain_indices = False\n\n# If false, no index is generated.\nhtml_use_index = False\n\n# If true, the index is split into individual pages for each letter.\n#html_split_index = False\n\n# If true, links to the reST sources are added to the pages.\nhtml_show_sourcelink = False\n\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\nhtml_show_sphinx = False\n\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\n#html_show_copyright = True\n\n# If true, an OpenSearch description file will be output, and all pages will\n# contain a <link> tag referring to it.  The value of this option must be the\n# base URL from which the finished HTML is served.\n#html_use_opensearch = ''\n\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\n#html_file_suffix = None\n\n# Language to be used for generating the HTML full-text search index.\n# Sphinx supports the following languages:\n#   'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'\n#   'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'\n#html_search_language = 'en'\n\n# A dictionary with options for the search language support, empty by default.\n# Now only 'ja' uses this config value\n#html_search_options = {'type': 'default'}\n\n# The name of a javascript file (relative to the configuration directory) that\n# implements a search results scorer. If empty, the default will be used.\n#html_search_scorer = 'scorer.js'\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'PySMIdoc'\n\n# -- Options for LaTeX output ---------------------------------------------\n\nlatex_elements = {\n# The paper size ('letterpaper' or 'a4paper').\n#'papersize': 'letterpaper',\n\n# The font size ('10pt', '11pt' or '12pt').\n#'pointsize': '10pt',\n\n# Additional stuff for the LaTeX preamble.\n#'preamble': '',\n\n# Latex figure (float) alignment\n#'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n  (master_doc, 'PySMI.tex', u'SNMP SMI compiler',\n   u'Ilya Etingof \\\\textless{}etingof@gmail.com\\\\textgreater{}', 'manual'),\n]\n\n# The name of an image file (relative to this directory) to place at the top of\n# the title page.\n#latex_logo = None\n\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\n# not chapters.\n#latex_use_parts = False\n\n# If true, show page references after internal links.\n#latex_show_pagerefs = False\n\n# If true, show URL addresses after external links.\n#latex_show_urls = False\n\n# Documents to append as an appendix to all manuals.\n#latex_appendices = []\n\n# If false, no module index is generated.\n#latex_domain_indices = True\n\n\n# -- Options for manual page output ---------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'pysmi', u'SNMP SMI compiler',\n     [author], 1)\n]\n\n# If true, show URL addresses after external links.\n#man_show_urls = False\n\n\n# -- Options for Texinfo output -------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n  (master_doc, 'PySMI', u'SNMP SMI compiler',\n   author, 'PySMI', 'One line description of project.',\n   'Miscellaneous'),\n]\n\n# Documents to append as an appendix to all manuals.\n#texinfo_appendices = []\n\n# If false, no module index is generated.\n#texinfo_domain_indices = True\n\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\n#texinfo_show_urls = 'footnote'\n\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\n#texinfo_no_detailmenu = False\n\n\n# Example configuration for intersphinx: refer to the Python standard library.\nintersphinx_mapping = {'https://docs.python.org/': None}\n\n# this merges constructor docstring with class docstring\nautoclass_content = 'both'\n\n# Napoleon settings\nnapoleon_google_docstring = True\nnapoleon_numpy_docstring = False\nnapoleon_include_private_with_doc = False\nnapoleon_include_special_with_doc = True\nnapoleon_use_admonition_for_examples = False\nnapoleon_use_admonition_for_notes = False\nnapoleon_use_admonition_for_references = False\nnapoleon_use_ivar = False\nnapoleon_use_param = False\nnapoleon_use_rtype = False\n"
  },
  {
    "path": "docs/source/contents.rst",
    "content": "\nSNMP SMI compiler\n=================\n\n.. toctree::\n   :maxdepth: 2\n\nThe PySMI library and tools are designed to parse, verify and transform\n`SNMP SMI <https://en.wikipedia.org/wiki/Management_information_base>`_ MIB\nmodules from their original ASN.1 form into JSON or `pysnmp <http://snmplabs.com/pysnmp/>`_\nrepresentation.\n\nDocumentation\n-------------\n\n.. toctree::\n   :maxdepth: 2\n\n   /documentation\n\nSource code & Changelog\n-----------------------\n\nProject source code is hosted at `GitHub <https://github.com/etingof/pysmi>`_.\nEveryone is welcome to fork and contribute back!\n\nWe maintain the detailed :doc:`log of changes </changelog>` to our software.\n\nDownload & Install\n------------------\n\n.. toctree::\n   :maxdepth: 2\n\n   /download\n\nChanges\n-------\n\n.. toctree::\n   :maxdepth: 1\n\n   /changelog\n\nLicense\n-------\n\nThe SNMP SMI library software is distributed under 2-clause BSD License.\n\n.. toctree::\n   :maxdepth: 2\n\n   /license\n\nMIB files archive\n-----------------\n\nThe PySMI project maintains a `collection <http://mibs.snmplabs.com/asn1/>`_\nof publicly available ASN.1 MIB files collected on the Internet. You are\nwelcome to use this MIBs archive however we can't guarantee any degree\nof consistency or reliability when it comes to these MIB modules.\n\nThe *mibdump.py* tool as well as many other utilities based on PySMI\nare programmed to use this MIB repository for automatic download and\ndependency resolution.\n\nYou can always reconfigure PySMI to use some other remote MIB repository\ninstead or in addition to this one.\n\nContact\n-------\n\nIn case of questions or troubles using SNMP SMI library, please open up an\n`issue <https://github.com/etingof/pysmi/issues>`_ at GitHub or ask at\n`Stack Overflow <http://stackoverflow.com/questions/tagged/pysmi>`_ .\n"
  },
  {
    "path": "docs/source/documentation.rst",
    "content": "\nPySMI documentation\n===================\n\nPySMI library is highly modular. The top-level component is called\n*compiler* and it acts as main user-facing object. Most of other\ncomponents are plugged into the *compiler* object prior to its use.\n\nNormally, user asks *compiler* to perform certain transformation of\nnamed MIB module. Compiler will:\n\n* Search its data sources for given MIB module (identified by name)\n  noting their last modification times.\n* Search compiler-managed repositories of already converted MIB modules\n  for modules that are more recent than corresponding source MIB module.\n* If freshly transformed MIB module is found, processing stops here.\n* Otherwise compiler passes ASN.1 MIB module content to the *lexer*\n  component.\n* Lexer returns a sequence of tokenized ASN.1 MIB contents. Compiler\n  then passes that sequence of tokens to the *parser* component.\n* Parser runs LR algorithm on tokenized MIB thus transforming MIB\n  contents into Abstract Syntax Tree (AST) and also noting what other\n  MIB modules are referred to from the MIB being parsed.\n* In case of parser failure, what is usually an indication of broken\n  ASN.1 MIB syntax, compiler may attempt to fetch pre-transformed MIB\n  contents from configured source. This process is called *borrowing*\n  in PySMI.\n* In case of successful parser completion, compiler will pass produced\n  AST to *code generator* component.\n* Code generator walks its input AST and performs actual data\n  transformation.\n* The above steps may be repeated for each of the MIB modules referred\n  to as parser figures out. Once no more unresolved dependencies remain,\n  compiler will call its *writer* component to store all transformed MIB\n  modules.\n\nThe location of ASN.1 MIB modules and flavor of their syntax, as well as\ndesired transformation format, is determined by respective components\nchosen and configured to compiler.\n\n.. toctree::\n   :maxdepth: 2\n\n   /mibdump\n   /mibcopy\n   /library-reference\n"
  },
  {
    "path": "docs/source/download.rst",
    "content": "\nDownload & Install\n==================\n\nThe best way to obtain SNMP SMI library is by running `pip`:\n\n.. code-block:: bash\n\n   $ virtualenv venv\n   $ source venv/bin/activate\n   $ pip install pysmi\n\nAlternatively, you can download the latest release from\n`GitHub <https://github.com/etingof/pysmi/releases>`_\nor `PyPI <https://pypi.org/project/pysmi/>`_.\n"
  },
  {
    "path": "docs/source/examples/always-borrow-precompiled-pysnmp-files.rst",
    "content": "\n.. include:: /../../examples/always-borrow-precompiled-pysnmp-files.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/always-borrow-precompiled-pysnmp-files.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/always-borrow-precompiled-pysnmp-files.py>` script.\n\n"
  },
  {
    "path": "docs/source/examples/borrow-precompiled-pysnmp-files-on-failure.rst",
    "content": "\n.. include:: /../../examples/borrow-precompiled-pysnmp-files-on-failure.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/borrow-precompiled-pysnmp-files-on-failure.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/borrow-precompiled-pysnmp-files-on-failure.py>` script.\n\n"
  },
  {
    "path": "docs/source/examples/compile-smistar-mibs-into-pysnmp-files-if-needed.rst",
    "content": "\n.. include:: /../../examples/compile-smistar-mibs-into-pysnmp-files-if-needed.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/compile-smistar-mibs-into-pysnmp-files-if-needed.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/compile-smistar-mibs-into-pysnmp-files-if-needed.py>` script.\n\n"
  },
  {
    "path": "docs/source/examples/compile-smiv2-mibs-from-text-into-pysnmp-code.rst",
    "content": "\n.. include:: /../../examples/compile-smiv2-mibs-from-text-into-pysnmp-code.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/compile-smiv2-mibs-from-text-into-pysnmp-code.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/compile-smiv2-mibs-from-text-into-pysnmp-code.py>` script.\n\n"
  },
  {
    "path": "docs/source/examples/download-and-compile-smistar-mibs-into-json.rst",
    "content": "\n.. include:: /../../examples/download-and-compile-smistar-mibs-into-json.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/download-and-compile-smistar-mibs-into-json.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/download-and-compile-smistar-mibs-into-json.py>` script.\n\n"
  },
  {
    "path": "docs/source/examples/download-and-compile-smistar-mibs-into-pysnmp-files.rst",
    "content": "\n.. include:: /../../examples/download-and-compile-smistar-mibs-into-pysnmp-files.py\n   :start-after: \"\"\"\n   :end-before: \"\"\"#\n\n.. literalinclude:: /../../examples/download-and-compile-smistar-mibs-into-pysnmp-files.py\n   :start-after: \"\"\"#\n   :language: python\n\n:download:`Download</../../examples/download-and-compile-smistar-mibs-into-pysnmp-files.py>` script.\n\n"
  },
  {
    "path": "docs/source/library-reference.rst",
    "content": "\nPySMI library\n=============\n\nThe *MibCompiler* object is the top-most interface to PySMI library features.\nIt holds together the otherwise isolated pieces of the compiler infrastructure\nand manages the workflow of ASN.1 MIB transformation.\n\nThis example showcases some of its features:\n\n.. code-block:: python\n\n   from pysmi.reader import HttpReader\n   from pysmi.searcher import StubSearcher\n   from pysmi.writer import CallbackWriter\n   from pysmi.parser import SmiStarParser\n   from pysmi.codegen import JsonCodeGen\n   from pysmi.compiler import MibCompiler\n\n   inputMibs = ['IF-MIB', 'IP-MIB']\n\n   httpSources = [('mibs.snmplabs.com', 80, '/asn1/@mib@')]\n\n   # store compiled MIBs by calling this function\n   def store_mibs(mibName, jsonDoc, cbCtx):\n       print('# MIB module %s' % mibName)\n       print(jsonDoc)\n\n   mibCompiler = MibCompiler(\n       SmiStarParser(), JsonCodeGen(), CallbackWriter(store_mibs)\n   )\n\n   # pull ASN.1 MIBs over HTTP\n   mibCompiler.addSources(*[HttpReader(*x) for x in httpSources])\n\n   # never recompile MIBs with ASN.1 MACROs\n   mibCompiler.addSearchers(StubSearcher(*JsonCodeGen.baseMibs))\n\n   status = mibCompiler.compile(*inputMibs)\n\n   print(status)\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/compiler/mibcompiler\n   /pysmi/compiler/mibstatus\n\nMIB sources\n-----------\n\nPySMI offers a handful of distinct transport mechanisms for fetching MIBs by\nname from specific locations. In all cases MIB module name to file name match\nmay not be exact -- some name fuzzying can be performed to mitigate\npossible changes to MIB file name.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/reader/localfile/filereader\n   /pysmi/reader/zipreader/zipreader\n   /pysmi/reader/httpclient/httpreader\n   /pysmi/reader/ftpclient/ftpreader\n   /pysmi/reader/callback/callbackreader\n\nConditional compilation\n-----------------------\n\nThere are cases when MIB transformation may or must not be performed.\nSuch cases include:\n\n* foundation MIBs containing manually implemented pieces or ASN.1 MACRO's\n* obsolete MIBs fully reimplemented within modern MIBs\n* already transformed MIBs\n\n:ref:`MibCompiler <compiler.MibCompiler>` expects user to supply a\n*searcher* object that would allow or skip MIB transformation for particular\nname based on whatever reason it is aware of.\n\nIn general, *searcher* logic is specific to target format. At the time being,\nonly `pysnmp <http://snmplabs.com/pysnmp>`_ code generation backend requires\nsuch filtering.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/searcher/pyfile/pyfilesearcher\n   /pysmi/searcher/pypackage/pypackagesearcher\n   /pysmi/searcher/stub/stubsearcher\n\nParser configuration\n--------------------\n\nMIBs may be written in one of the two major SMI language versions (v1 and v2).\nSome MIBs may contain typical errors.\n\nPySMI offers a way to customize the parser to consume either of the major SMI\ngrammars as well as to recover from well-known errors in MIB files.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/parser/smi/parserfactory\n   /pysmi/parser/smi/dialect\n\nCode generators\n---------------\n\nOnce ASN.1 MIB is parsed up, AST is passed to a code generator which turns\nAST into desired representation of the MIB.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/codegen/jsondoc/jsoncodegen\n   /pysmi/codegen/pysnmp/pysnmpcodegen\n   /pysmi/codegen/null/nullcodegen\n\nBorrow pre-compiled MIBs\n------------------------\n\nSome MIBs in circulation appear broken beyond automatic repair. To\nhandle such cases PySMI introduces the *MIB borrowing*\nfunctionality. When :ref:`MibCompiler <compiler.MibCompiler>`\ngives up compiling a MIB, it can try to go out and take a copy of\nalready transformed MIB to complete the request successfully.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/borrower/anyfile/anyfileborrower\n   /pysmi/borrower/pyfile/pyfileborrower\n\nWrite compiled MIBs\n-------------------\n\nSuccessfully transformed MIB modules' contents will be passed to *writer*\nobject given to :ref:`MibCompiler <compiler.MibCompiler>` on instantiation.\n\n.. toctree::\n   :maxdepth: 2\n\n   /pysmi/writer/localfile/filewriter\n   /pysmi/writer/pyfile/pyfilewriter\n   /pysmi/writer/callback/callbackwriter\n\nExamples\n--------\n\nThe following examples focus on various feature of the PySMI library.\n\n.. toctree::\n   :maxdepth: 2\n\n   /examples/download-and-compile-smistar-mibs-into-json.rst\n   /examples/download-and-compile-smistar-mibs-into-pysnmp-files.rst\n   /examples/compile-smistar-mibs-into-pysnmp-files-if-needed.rst\n   /examples/compile-smiv2-mibs-from-text-into-pysnmp-code.rst\n   /examples/borrow-precompiled-pysnmp-files-on-failure.rst\n   /examples/always-borrow-precompiled-pysnmp-files.rst\n\nIn case of any troubles or confusion, try enabling PySMI debugging\nand watch the output:\n\n.. code-block:: python\n\n   from pysmi import debug\n\n   debug.setLogger(debug.Debug('all'))\n\n"
  },
  {
    "path": "docs/source/license.rst",
    "content": "\nLicense\n=======\n\n.. include:: ../../LICENSE.rst\n"
  },
  {
    "path": "docs/source/mibcopy.rst",
    "content": "\nThe *mibcopy* tool\n==================\n\n.. toctree::\n   :maxdepth: 2\n\nThe *mibcopy.py* tool attempts to normalize the file name of the MIB file.\n\nIt turned out that sometimes vendors name their MIBs in any possible way,\nnot necessarily after the canonical MIB name. This causes problems to the\nMIB consumers as they may not be able to locate the MIB they need on the\nfile system.\n\nThe way how *mibcopy.py* works is that it tries to read the MIB from\nthe given file (or all files from a given directory or archive), parse\nMIB's canonical name from the contents of the file. Based on that, the\ntool tries to rename MIB file into the name which is the same as canonical\nMIB name. If *mibcopy.py* encounters the same named file already present\non the file system, it reads it up to see its revision date. Then the\ntool compares the revision dates of the colliding MIB files and either\noverrides the offending file or drops the file being copied as outdated.\n\nThe ultimate goal is to end up with the latest versions of the MIB files\nall named after their canonical names.\n\n.. code-block:: bash\n\n    $ mibcopy.py --help\n    Synopsis:\n      SNMP SMI/MIB files copying tool. When given MIB file(s) or\n      directory(ies) on input and a destination directory, the tool\n      parses MIBs to figure out their canonical MIB module name and\n      the latest revision date, then copies MIB module on input\n      into the destination directory under its MIB module name\n      *if* there is no such file already or its revision date is\n      older.\n\n    Documentation:\n      http://snmplabs.com/pysmi\n    Usage: mibcopy.py [--help]\n          [--version]\n          [--verbose]\n          [--quiet]\n          [--debug=<all|borrower|codegen|compiler|grammar|lexer|\n                    parser|reader|searcher|writer>]\n          [--mib-source=<URI>]\n          [--cache-directory=<DIRECTORY>]\n          [--ignore-errors]\n          [--dry-run]\n          <SOURCE [SOURCE...]> <DESTINATION>\n    Where:\n        URI      - file, zip, http, https, ftp, sftp schemes are\n                   supported. Use @mib@ placeholder token in URI to\n                   refer directly to the required MIB module when\n                   source does not support directory listing\n                   (e.g. HTTP).\n\nSpecifying MIB source\n---------------------\n\nThe --mib-source option can be given multiple times. Each instance of\n--mib-source must specify a URL where ASN.1 MIB modules should be\nlooked up and downloaded from. At this moment three MIB sourcing\nmethods are supported:\n\n* Local files. This could be a top-level directory where MIB files are\n  located. Subdirectories will be automatically traversed as well. \n  Example: file:///usr/share/snmp\n* ZIP archives containing MIB files. Subdirectories and embedded ZIP\n  archives will be automatically traversed.\n  Example: zip://mymibs.zip\n* HTTP/HTTPS. A fully specified URL where MIB module name is specified by\n  a @mib@ placeholder. When specific MIB is looked up, PySMI will replace\n  that placeholder with MIB module name it is looking for. \n  Example: `http://mibs.snmplabs.com/asn1/@mib@ <http://mibs.snmplabs.com/asn1/>`_\n* SFTP/FTP. A fully specified URL including FTP username and password. \n  MIB module name is specified by a @mib@ placeholder. When specific MIB\n  is looked up, PySMI will replace that placeholder with MIB module name\n  it is looking for. \n  Example: `http://mibs.snmplabs.com/asn1/@mib@ <http://mibs.snmplabs.com/asn1/>`_\n\nWhen trying to fetch a MIB module, the *mibcopy.py* tool will try each of\nconfigured --mib-source transports in order of specification till \nfirst successful hit.\n\nBy default *mibcopy.py* will search:\n\n* file:///usr/share/snmp\n* http://mibs.snmplabs.com/asn1/@mib@\n\nOnce another --mib-source option is given, those defaults will not be used\nand should be manually given to *mibcopy.py* if needed.\n\nSetting destination directory\n-----------------------------\n\nThe *mibcopy.py* writes MIBs into the *<DESTINATION>* directory.\n\nIgnoring transformation errors\n------------------------------\n\nBy default PySMI will stop on first fatal error occurred during\ntransformations of a series of MIBs. If you wish PySMI to ignore\nfatal errors and therefore skipping failed MIB, use the --ignore-errors\noption.\n\nKeep in mind that skipping transformation of MIBs that are imported\nby other MIBs might make dependant MIBs inconsistent for use.\n\nMinor speedups\n--------------\n\nThe --cache-directory option may be used to point to a temporary\nwritable directory where PySMI parser (e.g. Ply) would store its \nlookup tables. That should improve PySMI performance a tad bit.\n"
  },
  {
    "path": "docs/source/mibdump.rst",
    "content": "\nThe *mibdump* tool\n==================\n\n.. toctree::\n   :maxdepth: 2\n\nThe *mibdump.py* tool is a command-line frontend to the PySMI library. This\ntool can be used for automatic downloading and transforming SNMP MIB modules\ninto various formats.\n\n.. code-block:: bash\n\n   $ mibdump.py --help\n   Synopsis:\n     SNMP SMI/MIB files conversion tool\n   Documentation:\n     http://snmplabs.com/pysmi\n   Usage: mibdump.py [--help]\n         [--version]\n         [--quiet]\n         [--debug=<all|borrower|codegen|compiler|grammar|lexer|parser|reader|searcher|writer>]\n         [--mib-source=<URI>]\n         [--mib-searcher=<PATH|PACKAGE>]\n         [--mib-stub=<MIB-NAME>]\n         [--mib-borrower=<PATH>]\n         [--destination-format=<FORMAT>]\n         [--destination-directory=<DIRECTORY>]\n         [--cache-directory=<DIRECTORY>]\n         [--disable-fuzzy-source]\n         [--no-dependencies]\n         [--no-python-compile]\n         [--python-optimization-level]\n         [--ignore-errors]\n         [--build-index]\n         [--rebuild]\n         [--dry-run]\n         [--no-mib-writes]\n         [--generate-mib-texts]\n         [--keep-texts-layout]\n         <MIB-NAME> [MIB-NAME [...]]]\n   Where:\n       URI      - file, zip, http, https, ftp, sftp schemes are supported.\n                  Use @mib@ placeholder token in URI to refer directly to\n                  the required MIB module when source does not support\n                  directory listing (e.g. HTTP).\n       FORMAT   - pysnmp, json, null\n\n\nWhen JSON destination format is requested, for each MIB module *mibdump.py*\nwill produce a JSON document containing all MIB objects. For example,\n`IF-MIB <http://mibs.snmplabs.com/asn1/IF-MIB>`_ module in JSON form\nwould look like:\n\n.. code-block:: python\n\n   {\n      \"ifMIB\": {\n          \"name\": \"ifMIB\",\n          \"oid\": \"1.3.6.1.2.1.31\",\n          \"class\": \"moduleidentity\",\n          \"revisions\": [\n            \"2007-02-15 00:00\",\n            \"1996-02-28 21:55\",\n            \"1993-11-08 21:55\"\n          ]\n        },\n\n      ...\n      \"ifTestTable\": {\n        \"name\": \"ifTestTable\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3\",\n        \"class\": \"objecttype\",\n        \"maxaccess\": \"not-accessible\"\n      },\n      \"ifTestEntry\": {\n        \"name\": \"ifTestEntry\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3.1\",\n        \"class\": \"objecttype\",\n        \"maxaccess\": \"not-accessible\",\n        \"augmention\": {\n          \"name\": \"ifTestEntry\",\n          \"module\": \"IF-MIB\",\n          \"object\": \"ifEntry\"\n        }\n      },\n      \"ifTestId\": {\n        \"name\": \"ifTestId\",\n        \"oid\": \"1.3.6.1.2.1.31.1.3.1.1\",\n        \"class\": \"objecttype\",\n        \"syntax\": {\n          \"type\": \"TestAndIncr\",\n          \"class\": \"type\"\n        },\n        \"maxaccess\": \"read-write\"\n      },\n      ...\n   }\n\nIn general, JSON MIB captures all aspects of original (ASN.1) MIB contents\nand layout. The snippet above is just an example, here is the complete\n`IF-MIB.json <http://mibs.snmplabs.com/json/fulltext/IF-MIB.json>`_\nfile.\n\nSpecifying MIB source\n---------------------\n\nThe --mib-source option can be given multiple times. Each instance of\n--mib-source must specify a URL where ASN.1 MIB modules should be\nlooked up and downloaded from. At this moment three MIB sourcing\nmethods are supported:\n\n* Local files. This could be a top-level directory where MIB files are\n  located. Subdirectories will be automatically traversed as well. \n  Example: file:///usr/share/snmp\n* ZIP archives containing MIB files. Subdirectories and embedded ZIP\n  archives will be automatically traversed.\n  Example: zip://mymibs.zip\n* HTTP/HTTPS. A fully specified URL where MIB module name is specified by\n  a @mib@ placeholder. When specific MIB is looked up, PySMI will replace\n  that placeholder with MIB module name it is looking for. \n  Example: `http://mibs.snmplabs.com/asn1/@mib@ <http://mibs.snmplabs.com/asn1/>`_\n* SFTP/FTP. A fully specified URL including FTP username and password. \n  MIB module name is specified by a @mib@ placeholder. When specific MIB\n  is looked up, PySMI will replace that placeholder with MIB module name\n  it is looking for. \n  Example: `http://mibs.snmplabs.com/asn1/@mib@ <http://mibs.snmplabs.com/asn1/>`_\n\nWhen trying to fetch a MIB module, the *mibdump.py* tool will try each of\nconfigured --mib-source transports in order of specification till \nfirst successful hit.\n\nBy default *mibdump.py* will search:\n\n* file:///usr/share/snmp\n* http://mibs.snmplabs.com/asn1/@mib@\n\nOnce another --mib-source option is given, those defaults will not be used\nand should be manually given to *mibdump.py* if needed.\n\nFuzzying MIB module names\n-------------------------\n\nThere is no single convention on how MIB module files should be named. By\ndefault *mibdump.py* will try a handful of guesses when trying to find a file\ncontaining specific MIB module. It will try upper and lower cases, a file \nnamed after MIB module, try adding different extensions to a file (.mib,\n.my etc), try adding/cutting the '-MIB' part of the file name.\nIf nothing matches, *mibdump.py* will consider that probed --mib-source\ndoes not contain MIB module it is looking for.\n\nThere is a small chance, though, that fuzzy natching may result in getting\na wrong MIB. If that happens, you can disable the above fuzzyness by\ngiving *mibdump.py* the --disable-fuzzy-source flag.\n\nAvoiding excessive transformation\n---------------------------------\n\nIt well may happen that many MIB modules refer to a common single MIB\nmodule. In that case *mibdump.py* may transform it many times unless you\ntell *mibdump.py* where to search for already transformed MIBs. That place\ncould of course be a directory where *mibdump.py* writes its transforms into\nand/or some other local locations.\n\nThe --mib-searcher option specifies either local directory or importable\nPython package (applicable to pysnmp transformation) containing transformed\nMIB modules. Multiple --mib-searcher options could be given, *mibdump.py*\nwill use each of them in order of specification till first hit.\n\nIf no transformed MIB module is found, *mibdump.py* will go on running its full\ntransformation cycle.\n\nBy default *mibdump.py* will use:\n\n* --mib-searcher=$HOME/.pysnmp/mibs\n* --mib-searcher=pysnmp_mibs\n\nOnce another --mib-searcher option is given, those defaults will not be used\nand should be manually given to *mibdump.py* if needed.\n\nBlacklisting MIBs\n-----------------\n\nSome MIBs may not be automatically transformed into another form and \ntherefore must be explicitly excluded from processing. Such MIBs are\nnormally manually implemented for each target MIB format. Examples\ninclude MIBs containing base SMI types or ASN.1 MACRO definitions\n(SNMPv2-SMI, SNMPV2-TC), initially compiled but later manually modified \nMIBs and others.\n\nDefault list of blacklisted MIBs for pysnmp transformation target \nis: RFC-1212, RFC-1215, RFC1065-SMI, RFC1155-SMI, RFC1158-MIB, \nRFC1213-MIB, SNMP-FRAMEWORK-MIB, SNMP-TARGET-MIB, SNMPv2-CONF, SNMPv2-SMI,\nSNMPv2-TC, SNMPv2-TM, TRANSPORT-ADDRESS-MIB.\n\nIf you need to modify this list use the --mib-stub option.\n\nDealing with broken MIBs\n------------------------\n\nCuriously enough, some MIBs coming from quite prominent vendors \nappear syntactically incorrect. That leads to MIB compilers fail on\nsuch MIBs. While many MIB compiler implementations (PySMI included)\nintroduce workarounds and grammar relaxations allowing slightly\nbroken MIBs to compile, however severely broken MIBs can't be\nreliably compiled. \n\nAs another workaround PySMI offers the *borrow* feature. It allows\nPySMI to fetch already transformed MIBs even if corresponding\nASN.1 MIB can't be found or parsed.\n\nDefault source of pre-compiled MIBs for pysnmp target is:\n\n* http://mibs.snmplabs.com/pysnmp/fulltexts/@mib@\n* http://mibs.snmplabs.com/pysnmp/notexts/@mib@\n\nIf you wish to modify this default list use one or more\n--mib-borrower options.\n\nChoosing target transformation\n------------------------------\n\nPySMI design allows many transformation formats to be\nsupported in form of specialized code generation components.\nAt the moment PySMI can produce MIBs in form of pysnmp classes\nand JSON documents.\n\nJSON document schema is chosen to preserve as much of MIB\ninformation as possible. There's no established JSON schema\nknown to the authors.\n\nSetting destination directory\n-----------------------------\n\nBy default *mibdump.py* writes pysnmp MIBs into:\n\n* $HOME/.pysnmp/mibs  (on UNIX)\n* @HOME@\\PySNMP Configuration\\MIBs\\  (on Windows)\n\nand JSON files in current working directory.\n\nUse --destination-directory option to change default output\ndirectory.\n\nPerforming unconditional transformation\n---------------------------------------\n\nBy default PySMI will avoid creating new transformations if fresh\nenough versions already exist. By using --rebuild option you could\ntrick PySMI doing requested transformation for all given MIB modules.\n\nIgnoring transformation errors\n------------------------------\n\nBy default PySMI will stop on first fatal error occurred during\ntransformations of a series of MIBs. If you wish PySMI to ignore\nfatal errors and therefore skipping failed MIB, use the --ignore-errors\noption.\n\nKeep in mind that skipping transformation of MIBs that are imported\nby other MIBs might make dependant MIBs inconsistent for use.\n\nSkipping dependencies\n---------------------\n\nMost MIBs rely on other MIBs for their operations. This is indicated\nby the IMPORT statement in ASN.1 language. PySMI attempts to transform\nall MIBs IMPORT'ed by MIB being transformed. That is done in recursive\nmanner.\n\nBy using --no-dependencies flag you can tell PySMI not to transform any\nMIBs other than those explicitly requested to be transformed.\n\nKeep in mind that skipping dependencies may make the whole set of\ntransformed MIBs inconsistent.\n\nGenerating MIB texts\n--------------------\n\nMost MIBs are very verbose. They contain many human-oriented descriptions\nand clarifications written in plain English. Those texts may be useful \nfor MIB browser applications (to display those texts to human operator)\nbut might not make any sense in other applications.\n\nTo save space and CPU time, PySMI does not by default include those texts \ninto transformed MIBs. However this can be reverted by adding\n--generate-mib-texts option.\n\nWhen MIB texts are generated, whitespaces and new lines are stripped by\ndefault. Sometimes that breaks down ASCII art should it occur in MIB texts.\nTo preserve original text formatting, --keep-texts-layout option may\nbe used.\n\nBuilding MIB indices\n--------------------\n\nIf --build-index option is given, depending on the destination format chosen,\nthe *mibdump.py* tool may create new (or update existing) document containing\nMIB information in a form that is convenient for querying cornerstone\nproperties of MIB files.\n\nFor example, building JSON index for\n`IP-MIB.json <http://mibs.snmplabs.com/json/asn1/IP-MIB>`_,\n`TCP-MIB.json <http://mibs.snmplabs.com/json/asn1/TCP-MIB>`_ and\n`UDP-MIB.json <http://mibs.snmplabs.com/json/asn1/UDP-MIB>`_\nMIB modules would emit something like this:\n\n.. code-block:: json\n\n   {\n      \"compliance\": {\n         \"1.3.6.1.2.1.48.2.1.1\": [\n           \"IP-MIB\"\n         ],\n         \"1.3.6.1.2.1.49.2.1.1\": [\n           \"TCP-MIB\"\n         ],\n         \"1.3.6.1.2.1.50.2.1.1\": [\n           \"UDP-MIB\"\n         ]\n      },\n      \"identity\": {\n          \"1.3.6.1.2.1.48\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.49\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.50\": [\n            \"UDP-MIB\"\n          ]\n      },\n      \"oids\": {\n          \"1.3.6.1.2.1.4\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.5\": [\n            \"IP-MIB\"\n          ],\n          \"1.3.6.1.2.1.6\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.7\": [\n            \"UDP-MIB\"\n          ],\n          \"1.3.6.1.2.1.49\": [\n            \"TCP-MIB\"\n          ],\n          \"1.3.6.1.2.1.50\": [\n            \"UDP-MIB\"\n          ]\n      }\n   }\n\nWith this example, *compliance* and *identity* keys point to\n*MODULE-COMPLIANCE* and *MODULE-IDENTITY* MIB objects, *oids*\nlist top-level OIDs branches defined in MIB modules. Full index\nbuild over thousands of MIBs could be seen\n`here <http://mibs.snmplabs.com/json/index.json>`_.\n\nMinor speedups\n--------------\n\nThere are a few options that may improve PySMI performance.\n\nThe --cache-directory option may be used to point to a temporary\nwritable directory where PySMI parser (e.g. Ply) would store its \nlookup tables.\n\nBy default PySMI performing transformation into pysnmp format will \nalso pre-compile Python source into interpreter bytecode. That takes\nsome time and space. If you wish not to cache Python bytecode\nor to do that later, use the --no-python-compile option.\n\n"
  },
  {
    "path": "docs/source/pysmi/borrower/anyfile/anyfileborrower.rst",
    "content": "\n.. _borrower.anyfile.AnyFileBorrower:\n\nAny file borrower\n-----------------\n\n.. autoclass:: pysmi.borrower.anyfile.AnyFileBorrower\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/borrower/pyfile/pyfileborrower.rst",
    "content": "\n.. _borrower.pyfile.PyFileBorrower:\n\nPython file borrower\n--------------------\n\n.. autoclass:: pysmi.borrower.pyfile.PyFileBorrower\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/codegen/jsondoc/jsoncodegen.rst",
    "content": "\n.. _codegen.jsondoc.JsonCodeGen:\n\nJSON document generator\n-----------------------\n\n.. autoclass:: pysmi.codegen.jsondoc.JsonCodeGen\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/codegen/null/nullcodegen.rst",
    "content": "\n.. _codegen.null.NullCodeGen:\n\nCode generation stub\n--------------------\n\n.. autoclass:: pysmi.codegen.null.NullCodeGen\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/codegen/pysnmp/pysnmpcodegen.rst",
    "content": "\n.. _codegen.pysnmp.PySnmpCodeGen:\n\nPySNMP MIB generator\n--------------------\n\n.. autoclass:: pysmi.codegen.pysnmp.PySnmpCodeGen\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/compiler/mibcompiler.rst",
    "content": "\n.. _compiler.MibCompiler:\n\nMIB compiler\n------------\n\n.. autoclass:: pysmi.compiler.MibCompiler\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/compiler/mibstatus.rst",
    "content": "\n.. _reader.compiler.MibStatus:\n\nCompilation status\n------------------\n\n*MibStatus* class instance is used by :func:`MibCompiler.compiler` to\nindicate the outcome of MIB transformation operation.\n\n.. autoclass:: pysmi.compiler.MibStatus\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/parser/smi/dialect.rst",
    "content": "\n.. _parser.smi.dialect:\n\nSMI language dialects\n---------------------\n\nPySMI offers a pre-built collection of parser grammar relaxation options\nto simplify its use:\n\n* *pysmi.parser.dialect.smiV2* - canonical SMIv2 grammar\n* *pysmi.parser.dialect.smiV1* - canonical SMIv1 grammar\n* *pysmi.parser.dialect.smiV1Relaxed* - relaxed SMIv1 grammar allowing some deviations\n\nThe grammar object should be passed to the :ref:`parserFactory <parser.smi.parserFactory>` function.\n\n.. code-block:: python\n\n  from pysmi.parser.dialect import smiV1\n  from pysmi.parser.smi import parserFactory\n\n  SmiV1Parser = parserFactory(**smiV1)\n\nApparently, many production MIBs were shipped in syntactically broken\ncondition. PySMI attempts to work around such issues by allowing some\nextra SMI grammar relaxations. You can enable all those relaxations at\nonce to maximize the number of MIBs, found in the wild, successfully\ncompiled.\n\n.. code-block:: python\n\n  from pysmi.parser.dialect import smiV1Relaxed\n  from pysmi.parser.smi import parserFactory\n\n  RelaxedSmiV1Parser = parserFactory(**smiV1Relaxed)\n"
  },
  {
    "path": "docs/source/pysmi/parser/smi/parserfactory.rst",
    "content": "\n.. _parser.smi.parserFactory:\n\nSMI parser\n----------\n\nSNMP MIBs are written in two kinds of special language - SMIv1 and SMIv2.\nThe first SMI version is obsolete, most MIBs by now are written in SMIv2\ngrammar. There are also efforts aimed at improving SMIv2, but those MIBs\nare in great minority at the time of this writing.\n\nPySMI is designed to handle both SMIv1 and SMIv2. The way it is done is\nthat SMIv2 is considered the most basic and complete, whereas SMIv1 is a\nspecialization of SMIv2 syntax.\n\nFor a user to acquire SMIv2 parser the *parserFactory* function should\nbe called with the :ref:`SMI dialect object <parser.smi.dialect>`.\n\nThe parser object should be passed to the :ref:`MibCompiler <compiler.MibCompiler>` object.\n\n.. autofunction:: pysmi.parser.smi.parserFactory\n\n.. note::\n\n   Please, note that *parserFactory* function returns a class, not\n   class instance. Make sure to instantiate it when passing to\n   :ref:`MibCompiler <compiler.MibCompiler>` class constructor.\n"
  },
  {
    "path": "docs/source/pysmi/reader/callback/callbackreader.rst",
    "content": "\n.. _reader.callback.CallbackReader:\n\nCallback reader\n---------------\n\n*CallbackReader* class instance tries to fetch MIB files by calling user object.\n\n.. autoclass:: pysmi.reader.callback.CallbackReader\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/reader/ftpclient/ftpreader.rst",
    "content": "\n.. _reader.ftpclient.FtpReader:\n\nFTP reader\n----------\n\n*FtpReader* class instance tries to download MIB files from configured FTP server.\n\n.. autoclass:: pysmi.reader.ftpclient.FtpReader\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/reader/httpclient/httpreader.rst",
    "content": "\n.. _reader.httpclient.HttpReader:\n\nHTTP reader\n-----------\n\n*HttpReader* class instance tries to download MIB files using configured URL.\n\n.. autoclass:: pysmi.reader.httpclient.HttpReader\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/reader/localfile/filereader.rst",
    "content": "\n.. _reader.localfile.FileReader:\n\nLocal file reader\n-----------------\n\n*FileReader* class instance looks up MIB files in given directories on\nthe host running PySMI.\n\n.. autoclass:: pysmi.reader.localfile.FileReader\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/reader/zipreader/zipreader.rst",
    "content": "\n.. _reader.zipreader.ZipReader:\n\nZIP archive reader\n------------------\n\n*ZipReader* class instance looks up MIB files in local ZIP archive.\nZIP subdirectories and embedded ZIP archives would be traversed.\n\n.. autoclass:: pysmi.reader.zipreader.ZipReader\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/searcher/pyfile/pyfilesearcher.rst",
    "content": "\n.. _searcher.pyfile.PyFileSearcher:\n\nPython files searcher\n---------------------\n\nTransformed MIBs that were saved in form of Python files can be checked\nwith *PyFileSearcher* class instances.\n\n.. autoclass:: pysmi.searcher.pyfile.PyFileSearcher\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/searcher/pypackage/pypackagesearcher.rst",
    "content": "\n.. _searcher.pypackage.PyPackageSearcher:\n\nSearch Python packages\n----------------------\n\nSome MIBs, most frequently the base ones, can be stored at a Python package.\nThere existence can be checked with the *PyPackageSearcher* class instances.\n\n.. autoclass:: pysmi.searcher.pypackage.PyPackageSearcher\n   :members:\n"
  },
  {
    "path": "docs/source/pysmi/searcher/stub/stubsearcher.rst",
    "content": "\n.. _searcher.stub.StubSearcher:\n\nUnconditionally ignore MIBs\n---------------------------\n\nFoundation or obsolete MIBs that should never be transformed can be\nblindly excluded by listing their names at the *StubSearcher* class\ninstance.\n\n.. autoclass:: pysmi.searcher.stub.StubSearcher\n   :members:\n\n   .. note::\n\n      A pysnmp-specific list of MIB names to be permanently excluded from\n      transformation can be found at :py:const:`pysmi.codegen.pysnmp.baseMibs`.\n"
  },
  {
    "path": "docs/source/pysmi/writer/callback/callbackwriter.rst",
    "content": "\n.. _writer.callback.CallbackReader:\n\nCallback writer\n---------------\n\n*CallbackWriter* class instance passes the contents of the compiled MIB files to a user object.\n\n.. autoclass:: pysmi.writer.callback.CallbackWriter\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/writer/localfile/filewriter.rst",
    "content": "\n.. _writer.localfile.FileWriter:\n\nFile writer\n-----------\n\n.. autoclass:: pysmi.writer.localfile.FileWriter\n  :members:\n"
  },
  {
    "path": "docs/source/pysmi/writer/pyfile/pyfilewriter.rst",
    "content": "\n.. _writer.pyfile.PyFileWriter:\n\nPython file writer\n------------------\n\n.. autoclass:: pysmi.writer.pyfile.PyFileWriter\n  :members:\n"
  },
  {
    "path": "examples/always-borrow-precompiled-pysnmp-files.py",
    "content": "\"\"\"\nAlways borrow pysnmp MIBs\n+++++++++++++++++++++++++\n\nTry to borrow precompiled pysnmp MIB file(s) from a web-site.\n\nIn this example no attempt is made to find and compile ASN.1\nMIB source.\n\nFetched pysnmp MIB(s) are stored in a local directory.\n\"\"\"#\nfrom pysmi.reader import HttpReader\nfrom pysmi.searcher import PyFileSearcher\nfrom pysmi.borrower import PyFileBorrower\nfrom pysmi.writer import PyFileWriter\nfrom pysmi.parser import NullParser\nfrom pysmi.codegen import NullCodeGen\nfrom pysmi.compiler import MibCompiler\n\ninputMibs = ['BORROWED-MIB']\n\nhttpBorrowers = [\n    ('mibs.snmplabs.com', 80, '/pysnmp/notexts/@mib@')\n]\ndstDirectory = '.pysnmp-mibs'\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    NullParser(), NullCodeGen(), PyFileWriter(dstDirectory)\n)\n\n# check compiled/borrowed MIBs in our own productions\nmibCompiler.addSearchers(PyFileSearcher(dstDirectory))\n\n# search for precompiled MIBs at Web sites\nmibCompiler.addBorrowers(\n    *[PyFileBorrower(HttpReader(*x)) for x in httpBorrowers]\n)\n\n# run MIB compilation\nresults = mibCompiler.compile(*inputMibs)\n\nprint('Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "examples/borrow-precompiled-pysnmp-files-on-failure.py",
    "content": "\"\"\"\nBorrow pysnmp MIBs on failure\n+++++++++++++++++++++++++++++\n\nLook up specific ASN.1 MIBs at configured Web/FTP sites.\nIf no required MIB is found or its compilation fails for\nsome reason, attempt to download precompiled version of\nfailed MIB and store it locally as if we had compiled it.\n\"\"\"#\nfrom pysmi.reader import HttpReader\nfrom pysmi.searcher import PyFileSearcher\nfrom pysmi.searcher import StubSearcher\nfrom pysmi.borrower import PyFileBorrower\nfrom pysmi.writer import PyFileWriter\nfrom pysmi.parser import SmiStarParser\nfrom pysmi.codegen import PySnmpCodeGen\nfrom pysmi.compiler import MibCompiler\n# from pysmi import debug\n\n# debug.setLogger(debug.Debug('borrower', 'reader', 'searcher'))\n\ninputMibs = ['BORROWED-MIB']\nhttpSources = [ \n    ('mibs.snmplabs.com', 80, '/asn1/@mib@')\n]\nhttpBorrowers = [\n    ('mibs.snmplabs.com', 80, '/pysnmp/notexts/@mib@')\n]\ndstDirectory = '.pysnmp-mibs'\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    SmiStarParser(), PySnmpCodeGen(), PyFileWriter(dstDirectory)\n)\n\n# search for source MIBs at Web sites\nmibCompiler.addSources(*[HttpReader(*x) for x in httpSources])\n\n# never recompile MIBs with MACROs\nmibCompiler.addSearchers(StubSearcher(*PySnmpCodeGen.baseMibs))\n\n# check compiled/borrowed MIBs in our own productions\nmibCompiler.addSearchers(PyFileSearcher(dstDirectory))\n\n# search for compiled MIBs at Web sites if source is not available or broken\nmibCompiler.addBorrowers(*[PyFileBorrower(HttpReader(*x)).setOptions(genTexts=False) for x in httpBorrowers])\n\n# run non-recursive MIB compilation\nresults = mibCompiler.compile(*inputMibs)\n\nprint('Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "examples/compile-smistar-mibs-into-pysnmp-files-if-needed.py",
    "content": "\"\"\"\nCompile SMIv1/v2 MIBs\n+++++++++++++++++++++\n\nLook up specific ASN.1 MIBs at configured local directories,\ncompile them into pysnmp form if not done yet and save Python\nmodules as plain-text files in a local directory.\n\nTry to support both SMIv1 and SMIv2 flavors of SMI as well as\npopular deviations from official syntax found in the wild.\n\nWhen figuring out if compilation is needed, check all known\nplaces where pysnmp MIBs could possibly be found.\n\nYou can force MIB re-compilation by passing rebuild flag to\nMIB compiler (see below).\n\nDefault invocation of MIB compiler does not generate [potentially\nlarge] comments and texts found in MIBs. If you need them in pysnmp\nMIB modules, just pass genTexts flag to MIB compiler.\n\"\"\"#\nfrom pysmi.reader import FileReader\nfrom pysmi.searcher import PyFileSearcher, PyPackageSearcher, StubSearcher\nfrom pysmi.writer import PyFileWriter\nfrom pysmi.parser import SmiStarParser\nfrom pysmi.codegen import PySnmpCodeGen\nfrom pysmi.compiler import MibCompiler\n\ninputMibs = ['IF-MIB', 'IP-MIB']\nsrcDirectories = ['/usr/share/snmp/mibs']\ndstDirectory = '.pysnmp-mibs'\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(SmiStarParser(),\n                          PySnmpCodeGen(),\n                          PyFileWriter(dstDirectory))\n\n# search for source MIBs here\nmibCompiler.addSources(*[FileReader(x) for x in srcDirectories])\n\n# check compiled MIBs in our own productions\nmibCompiler.addSearchers(PyFileSearcher(dstDirectory))\n# ...and at default PySNMP MIBs packages\nmibCompiler.addSearchers(*[PyPackageSearcher(x) for x in PySnmpCodeGen.defaultMibPackages])\n\n# never recompile MIBs with MACROs\nmibCompiler.addSearchers(StubSearcher(*PySnmpCodeGen.baseMibs))\n\n# run [possibly recursive] MIB compilation\nresults = mibCompiler.compile(*inputMibs)  #, rebuild=True, genTexts=True)\n\nprint('Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "examples/compile-smiv2-mibs-from-text-into-pysnmp-code.py",
    "content": "\"\"\"\nCompile SMIv2 MIBs\n++++++++++++++++++\n\nInvoke user callback function to provide MIB text,\ncompile given text string into pysnmp MIB form and pass\nresults to another user callback function for storing.\n\nHere we expect to deal only with SMIv2-valid MIBs.\n\nWe use noDeps flag to prevent MIB compiler from attemping\nto compile IMPORT'ed MIBs as well.\n\"\"\"#\nimport sys\nfrom pysmi.reader import CallbackReader\nfrom pysmi.searcher import StubSearcher\nfrom pysmi.writer import CallbackWriter\nfrom pysmi.parser import SmiV2Parser\nfrom pysmi.codegen import PySnmpCodeGen\nfrom pysmi.compiler import MibCompiler\n\ninputMibs = ['IF-MIB', 'IP-MIB']\nsrcDir = '/usr/share/snmp/mibs/'  # we will read MIBs from here\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    SmiV2Parser(),\n    PySnmpCodeGen(),\n    # out own callback function stores results in its own way\n    CallbackWriter(lambda m, d, c: sys.stdout.write(d))\n)\n\n# our own callback function serves as a MIB source here\nmibCompiler.addSources(\n  CallbackReader(lambda m, c: open(srcDir+m+'.txt').read())\n)\n\n# never recompile MIBs with MACROs\nmibCompiler.addSearchers(StubSearcher(*PySnmpCodeGen.baseMibs))\n\n# run non-recursive MIB compilation\nresults = mibCompiler.compile(*inputMibs, **dict(noDeps=True))\n\nprint('Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "examples/download-and-compile-smistar-mibs-into-json.py",
    "content": "\"\"\"\nCompile MIBs into JSON\n++++++++++++++++++++++\n\nLook up specific ASN.1 MIBs at configured Web and FTP sites,\ncompile them into JSON documents and print them out to stdout.\n\nTry to support both SMIv1 and SMIv2 flavors of SMI as well as\npopular deviations from official syntax found in the wild.\n\"\"\"#\nfrom pysmi.reader import FileReader, HttpReader\nfrom pysmi.searcher import StubSearcher\nfrom pysmi.writer import CallbackWriter\nfrom pysmi.parser import SmiStarParser\nfrom pysmi.codegen import JsonCodeGen\nfrom pysmi.compiler import MibCompiler\n# from pysmi import debug\n\n# debug.setLogger(debug.Debug('reader', 'compiler'))\n\ninputMibs = ['IF-MIB', 'IP-MIB']\nsrcDirectories = ['/usr/share/snmp/mibs']\nhttpSources = [\n    ('mibs.snmplabs.com', 80, '/asn1/@mib@')\n]\n\n\ndef printOut(mibName, jsonDoc, cbCtx):\n    print('\\n\\n# MIB module %s' % mibName)\n    print(jsonDoc)\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    SmiStarParser(), JsonCodeGen(), CallbackWriter(printOut)\n)\n\n# search for source MIBs here\nmibCompiler.addSources(*[FileReader(x) for x in srcDirectories])\n\n# search for source MIBs at Web sites\nmibCompiler.addSources(*[HttpReader(*x) for x in httpSources])\n\n# never recompile MIBs with MACROs\nmibCompiler.addSearchers(StubSearcher(*JsonCodeGen.baseMibs))\n\n# run recursive MIB compilation\nresults = mibCompiler.compile(*inputMibs)\n\nprint('\\n# Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "examples/download-and-compile-smistar-mibs-into-pysnmp-files.py",
    "content": "\"\"\"\nCompile MIBs from web\n+++++++++++++++++++++\n\nLook up specific ASN.1 MIBs at configured Web and FTP sites,\ncompile them into pysnmp form and save Python modules as plain-text\nfiles in a local directory.\n\nTry to support both SMIv1 and SMIv2 flavors of SMI as well as\npopular deviations from official syntax found in the wild.\n\nIn this example we disable automatic dependency checking on MIB\ncompilation using noDeps flag.\n\nAlso, we do not check if target file already exists thus MIB\ncompilation occurs on every invocation.\n\"\"\"#\nfrom pysmi.reader import HttpReader\nfrom pysmi.reader import FtpReader\nfrom pysmi.searcher import StubSearcher\nfrom pysmi.writer import PyFileWriter\nfrom pysmi.parser import SmiStarParser\nfrom pysmi.codegen import PySnmpCodeGen\nfrom pysmi.compiler import MibCompiler\n\ninputMibs = ['IF-MIB', 'IP-MIB']\nhttpSources = [\n    ('mibs.snmplabs.com', 80, '/asn1/@mib@')\n]\nftpSources = [\n    ('ftp.cisco.com', '/pub/mibs/v2/@mib@')\n]\ndstDirectory = '.pysnmp-mibs'\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    SmiStarParser(), PySnmpCodeGen(), PyFileWriter(dstDirectory)\n)\n\n# search for source MIBs at Web and FTP sites\nmibCompiler.addSources(*[HttpReader(*x) for x in httpSources])\nmibCompiler.addSources(*[FtpReader(*x) for x in ftpSources])\n\n# never recompile MIBs with MACROs\nmibCompiler.addSearchers(StubSearcher(*PySnmpCodeGen.baseMibs))\n\n# run non-recursive MIB compilation\nresults = mibCompiler.compile(*inputMibs, **dict(noDeps=True))\n\nprint('Results: %s' % ', '.join(['%s:%s' % (x, results[x]) for x in results]))\n"
  },
  {
    "path": "pysmi/__init__.py",
    "content": "# http://www.python.org/dev/peps/pep-0396/\n__version__ = '0.4.0'\n\nimport sys\n\nif sys.version_info[:2] < (2, 4):\n    raise RuntimeError('PySMI requires Python 2.4 or later')\n"
  },
  {
    "path": "pysmi/borrower/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.borrower.pyfile import PyFileBorrower\nfrom pysmi.borrower.anyfile import AnyFileBorrower\n"
  },
  {
    "path": "pysmi/borrower/anyfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.borrower.base import AbstractBorrower\n\n\nclass AnyFileBorrower(AbstractBorrower):\n    \"\"\"Create arbitrary MIB file borrowing object\"\"\"\n"
  },
  {
    "path": "pysmi/borrower/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi import error\nfrom pysmi import debug\n\n\nclass AbstractBorrower(object):\n    genTexts = False\n    exts = ''\n\n    def __init__(self, reader, genTexts=False):\n        \"\"\"Creates an instance of *Borrower* class.\n\n           Args:\n               reader: a *reader* object\n\n           Keyword Args:\n               genText: indicates whether this borrower should be looking\n                        for transformed MIBs that include human-oriented texts\n        \"\"\"\n        if genTexts is not None:\n            self.genTexts = genTexts\n\n        self._reader = reader\n\n    def __str__(self):\n        return '%s{%s, genTexts=%s, exts=%s}' % (self.__class__.__name__,\n                                                 self._reader, self.genTexts,\n                                                 self.exts)\n\n    def setOptions(self, **kwargs):\n        self._reader.setOptions(**kwargs)\n\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n\n        return self\n\n    def getData(self, mibname, **options):\n        if bool(options.get('genTexts')) != self.genTexts:\n            debug.logger & debug.flagBorrower and debug.logger(\n                'skipping incompatible borrower %s for file %s' % (self, mibname))\n            raise error.PySmiFileNotFoundError(mibname=mibname, reader=self._reader)\n\n        debug.logger & debug.flagBorrower and (\n            debug.logger('trying to borrow file %s from %s' % (mibname, self._reader))\n        )\n\n        if 'exts' not in options:\n            options['exts'] = self.exts\n\n        return self._reader.getData(mibname, **options)\n"
  },
  {
    "path": "pysmi/borrower/pyfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\ntry:\n    import importlib\n\n    try:\n        SOURCE_SUFFIXES = importlib.machinery.SOURCE_SUFFIXES\n\n    except Exception:\n        raise ImportError()\n\nexcept ImportError:\n    import imp\n\n    SOURCE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                       if s[2] == imp.PY_SOURCE]\n\nfrom pysmi.borrower.base import AbstractBorrower\n\n\nclass PyFileBorrower(AbstractBorrower):\n    \"\"\"Create PySNMP MIB file borrowing object\"\"\"\n    exts = SOURCE_SUFFIXES\n"
  },
  {
    "path": "pysmi/codegen/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.jsondoc import JsonCodeGen\nfrom pysmi.codegen.null import NullCodeGen\n\n"
  },
  {
    "path": "pysmi/codegen/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nfrom pysmi import error\n\n\nif sys.version_info[0] > 2:\n    # noinspection PyShadowingBuiltins\n    unicode = str\n    # noinspection PyShadowingBuiltins\n    long = int\n\n    def dorepr(s):\n        return repr(s)\nelse:\n    def dorepr(s):\n        return repr(s.encode('utf-8')).decode('utf-8')\n\ndef updateDict(d1, d2):\n    d1.update(d2)\n    return d1\n\n\nclass AbstractCodeGen(object):\n    # never compile these, they either:\n    # - define MACROs (implementation supplies them)\n    # - or carry conflicting OIDs (so that all IMPORT's of them will be rewritten)\n    # - or have manual fixes\n    # - or import base ASN.1 types from implementation-specific MIBs\n    baseMibs = ('RFC1065-SMI',\n                'RFC1155-SMI',\n                'RFC1158-MIB',\n                'RFC-1212',\n                'RFC1213-MIB',\n                'RFC-1215',\n                'SNMPv2-SMI',\n                'SNMPv2-TC',\n                'SNMPv2-TM',\n                'SNMPv2-CONF')\n\n    # Explicit SMIv1 -> SMIv2 mapping for standard MIBs\n    commonSyms = {'RFC1155-SMI/RFC1065-SMI':\n                      {'internet': [('SNMPv2-SMI', 'internet')],\n                       'directory': [('SNMPv2-SMI', 'directory')],\n                       'mgmt': [('SNMPv2-SMI', 'mgmt')],\n                       'experimental': [('SNMPv2-SMI', 'experimental')],\n                       'private': [('SNMPv2-SMI', 'private')],\n                       'enterprises': [('SNMPv2-SMI', 'enterprises')],\n                       'OBJECT-TYPE': [('SNMPv2-SMI', 'OBJECT-TYPE')],\n                       'ObjectName': [('SNMPv2-SMI', 'ObjectName')],\n                       'ObjectSyntax': [('SNMPv2-SMI', 'ObjectSyntax')],\n                       'SimpleSyntax': [('SNMPv2-SMI', 'SimpleSyntax')],\n                       'ApplicationSyntax': [('SNMPv2-SMI', 'ApplicationSyntax')],\n                       'NetworkAddress': [('SNMPv2-SMI', 'IpAddress')],\n                       'IpAddress': [('SNMPv2-SMI', 'IpAddress')],\n                       'Counter': [('SNMPv2-SMI', 'Counter32')],\n                       'Gauge': [('SNMPv2-SMI', 'Gauge32')],\n                       'TimeTicks': [('SNMPv2-SMI', 'TimeTicks')],\n                       'Opaque': [('SNMPv2-SMI', 'Opaque')]},\n                  'RFC1158-MIB/RFC1213-MIB':\n                      {'mib-2': [('SNMPv2-SMI', 'mib-2')],\n                       'DisplayString': [('SNMPv2-TC', 'DisplayString')],\n                       'system': [('SNMPv2-MIB', 'system')],\n                       'interfaces': [('IF-MIB', 'interfaces')],\n                       'ip': [('IP-MIB', 'ip')],\n                       'icmp': [('IP-MIB', 'icmp')],\n                       'tcp': [('TCP-MIB', 'tcp')],\n                       'udp': [('UDP-MIB', 'udp')],\n                       'transmission': [('SNMPv2-SMI', 'transmission')],\n                       'snmp': [('SNMPv2-MIB', 'snmp')],\n                       'sysDescr': [('SNMPv2-MIB', 'sysDescr')],\n                       'sysObjectID': [('SNMPv2-MIB', 'sysObjectID')],\n                       'sysUpTime': [('SNMPv2-MIB', 'sysUpTime')],\n                       'sysContact': [('SNMPv2-MIB', 'sysContact')],\n                       'sysName': [('SNMPv2-MIB', 'sysName')],\n                       'sysLocation': [('SNMPv2-MIB', 'sysLocation')],\n                       'sysServices': [('SNMPv2-MIB', 'sysServices')],\n                       'ifNumber': [('IF-MIB', 'ifNumber')],\n                       'ifTable': [('IF-MIB', 'ifTable')],\n                       'ifEntry': [('IF-MIB', 'ifEntry')],\n                       'ifIndex': [('IF-MIB', 'ifIndex')],\n                       'ifDescr': [('IF-MIB', 'ifDescr')],\n                       'ifType': [('IF-MIB', 'ifType')],\n                       'ifMtu': [('IF-MIB', 'ifMtu')],\n                       'ifSpeed': [('IF-MIB', 'ifSpeed')],\n                       'ifPhysAddress': [('IF-MIB', 'ifPhysAddress')],\n                       'ifAdminStatus': [('IF-MIB', 'ifAdminStatus')],\n                       'ifOperStatus': [('IF-MIB', 'ifOperStatus')],\n                       'ifLastChange': [('IF-MIB', 'ifLastChange')],\n                       'ifInOctets': [('IF-MIB', 'ifInOctets')],\n                       'ifInUcastPkts': [('IF-MIB', 'ifInUcastPkts')],\n                       'ifInNUcastPkts': [('IF-MIB', 'ifInNUcastPkts')],\n                       'ifInDiscards': [('IF-MIB', 'ifInDiscards')],\n                       'ifInErrors': [('IF-MIB', 'ifInErrors')],\n                       'ifInUnknownProtos': [('IF-MIB', 'ifInUnknownProtos')],\n                       'ifOutOctets': [('IF-MIB', 'ifOutOctets')],\n                       'ifOutUcastPkts': [('IF-MIB', 'ifOutUcastPkts')],\n                       'ifOutNUcastPkts': [('IF-MIB', 'ifOutNUcastPkts')],\n                       'ifOutDiscards': [('IF-MIB', 'ifOutDiscards')],\n                       'ifOutErrors': [('IF-MIB', 'ifOutErrors')],\n                       'ifOutQLen': [('IF-MIB', 'ifOutQLen')],\n                       'ifSpecific': [('IF-MIB', 'ifSpecific')],\n                       'ipForwarding': [('IP-MIB', 'ipForwarding')],\n                       'ipDefaultTTL': [('IP-MIB', 'ipDefaultTTL')],\n                       'ipInReceives': [('IP-MIB', 'ipInReceives')],\n                       'ipInHdrErrors': [('IP-MIB', 'ipInHdrErrors')],\n                       'ipInAddrErrors': [('IP-MIB', 'ipInAddrErrors')],\n                       'ipForwDatagrams': [('IP-MIB', 'ipForwDatagrams')],\n                       'ipInUnknownProtos': [('IP-MIB', 'ipInUnknownProtos')],\n                       'ipInDiscards': [('IP-MIB', 'ipInDiscards')],\n                       'ipInDelivers': [('IP-MIB', 'ipInDelivers')],\n                       'ipOutRequests': [('IP-MIB', 'ipOutRequests')],\n                       'ipOutDiscards': [('IP-MIB', 'ipOutDiscards')],\n                       'ipOutNoRoutes': [('IP-MIB', 'ipOutNoRoutes')],\n                       'ipReasmTimeout': [('IP-MIB', 'ipReasmTimeout')],\n                       'ipReasmReqds': [('IP-MIB', 'ipReasmReqds')],\n                       'ipReasmOKs': [('IP-MIB', 'ipReasmOKs')],\n                       'ipReasmFails': [('IP-MIB', 'ipReasmFails')],\n                       'ipFragOKs': [('IP-MIB', 'ipFragOKs')],\n                       'ipFragFails': [('IP-MIB', 'ipFragFails')],\n                       'ipFragCreates': [('IP-MIB', 'ipFragCreates')],\n                       'ipAddrTable': [('IP-MIB', 'ipAddrTable')],\n                       'ipAddrEntry': [('IP-MIB', 'ipAddrEntry')],\n                       'ipAdEntAddr': [('IP-MIB', 'ipAdEntAddr')],\n                       'ipAdEntIfIndex': [('IP-MIB', 'ipAdEntIfIndex')],\n                       'ipAdEntNetMask': [('IP-MIB', 'ipAdEntNetMask')],\n                       'ipAdEntBcastAddr': [('IP-MIB', 'ipAdEntBcastAddr')],\n                       'ipAdEntReasmMaxSize': [('IP-MIB', 'ipAdEntReasmMaxSize')],\n                       'ipNetToMediaTable': [('IP-MIB', 'ipNetToMediaTable')],\n                       'ipNetToMediaEntry': [('IP-MIB', 'ipNetToMediaEntry')],\n                       'ipNetToMediaIfIndex': [('IP-MIB', 'ipNetToMediaIfIndex')],\n                       'ipNetToMediaPhysAddress': [('IP-MIB', 'ipNetToMediaPhysAddress')],\n                       'ipNetToMediaNetAddress': [('IP-MIB', 'ipNetToMediaNetAddress')],\n                       'ipNetToMediaType': [('IP-MIB', 'ipNetToMediaType')],\n                       'icmpInMsgs': [('IP-MIB', 'icmpInMsgs')],\n                       'icmpInErrors': [('IP-MIB', 'icmpInErrors')],\n                       'icmpInDestUnreachs': [('IP-MIB', 'icmpInDestUnreachs')],\n                       'icmpInTimeExcds': [('IP-MIB', 'icmpInTimeExcds')],\n                       'icmpInParmProbs': [('IP-MIB', 'icmpInParmProbs')],\n                       'icmpInSrcQuenchs': [('IP-MIB', 'icmpInSrcQuenchs')],\n                       'icmpInRedirects': [('IP-MIB', 'icmpInRedirects')],\n                       'icmpInEchos': [('IP-MIB', 'icmpInEchos')],\n                       'icmpInEchoReps': [('IP-MIB', 'icmpInEchoReps')],\n                       'icmpInTimestamps': [('IP-MIB', 'icmpInTimestamps')],\n                       'icmpInTimestampReps': [('IP-MIB', 'icmpInTimestampReps')],\n                       'icmpInAddrMasks': [('IP-MIB', 'icmpInAddrMasks')],\n                       'icmpInAddrMaskReps': [('IP-MIB', 'icmpInAddrMaskReps')],\n                       'icmpOutMsgs': [('IP-MIB', 'icmpOutMsgs')],\n                       'icmpOutErrors': [('IP-MIB', 'icmpOutErrors')],\n                       'icmpOutDestUnreachs': [('IP-MIB', 'icmpOutDestUnreachs')],\n                       'icmpOutTimeExcds': [('IP-MIB', 'icmpOutTimeExcds')],\n                       'icmpOutParmProbs': [('IP-MIB', 'icmpOutParmProbs')],\n                       'icmpOutSrcQuenchs': [('IP-MIB', 'icmpOutSrcQuenchs')],\n                       'icmpOutRedirects': [('IP-MIB', 'icmpOutRedirects')],\n                       'icmpOutEchos': [('IP-MIB', 'icmpOutEchos')],\n                       'icmpOutEchoReps': [('IP-MIB', 'icmpOutEchoReps')],\n                       'icmpOutTimestamps': [('IP-MIB', 'icmpOutTimestamps')],\n                       'icmpOutTimestampReps': [('IP-MIB', 'icmpOutTimestampReps')],\n                       'icmpOutAddrMasks': [('IP-MIB', 'icmpOutAddrMasks')],\n                       'icmpOutAddrMaskReps': [('IP-MIB', 'icmpOutAddrMaskReps')],\n                       'tcpRtoAlgorithm': [('TCP-MIB', 'tcpRtoAlgorithm')],\n                       'tcpRtoMin': [('TCP-MIB', 'tcpRtoMin')],\n                       'tcpRtoMax': [('TCP-MIB', 'tcpRtoMax')],\n                       'tcpMaxConn': [('TCP-MIB', 'tcpMaxConn')],\n                       'tcpActiveOpens': [('TCP-MIB', 'tcpActiveOpens')],\n                       'tcpPassiveOpens': [('TCP-MIB', 'tcpPassiveOpens')],\n                       'tcpAttemptFails': [('TCP-MIB', 'tcpAttemptFails')],\n                       'tcpEstabResets': [('TCP-MIB', 'tcpEstabResets')],\n                       'tcpCurrEstab': [('TCP-MIB', 'tcpCurrEstab')],\n                       'tcpInSegs': [('TCP-MIB', 'tcpInSegs')],\n                       'tcpOutSegs': [('TCP-MIB', 'tcpOutSegs')],\n                       'tcpRetransSegs': [('TCP-MIB', 'tcpRetransSegs')],\n                       'tcpConnTable': [('TCP-MIB', 'tcpConnTable')],\n                       'tcpConnEntry': [('TCP-MIB', 'tcpConnEntry')],\n                       'tcpConnState': [('TCP-MIB', 'tcpConnState')],\n                       'tcpConnLocalAddress': [('TCP-MIB', 'tcpConnLocalAddress')],\n                       'tcpConnLocalPort': [('TCP-MIB', 'tcpConnLocalPort')],\n                       'tcpConnRemAddress': [('TCP-MIB', 'tcpConnRemAddress')],\n                       'tcpConnRemPort': [('TCP-MIB', 'tcpConnRemPort')],\n                       'tcpInErrs': [('TCP-MIB', 'tcpInErrs')],\n                       'tcpOutRsts': [('TCP-MIB', 'tcpOutRsts')],\n                       'udpInDatagrams': [('UDP-MIB', 'udpInDatagrams')],\n                       'udpNoPorts': [('UDP-MIB', 'udpNoPorts')],\n                       'udpInErrors': [('UDP-MIB', 'udpInErrors')],\n                       'udpOutDatagrams': [('UDP-MIB', 'udpOutDatagrams')],\n                       'udpTable': [('UDP-MIB', 'udpTable')],\n                       'udpEntry': [('UDP-MIB', 'udpEntry')],\n                       'udpLocalAddress': [('UDP-MIB', 'udpLocalAddress')],\n                       'udpLocalPort': [('UDP-MIB', 'udpLocalPort')],\n                       'snmpInPkts': [('SNMPv2-MIB', 'snmpInPkts')],\n                       'snmpOutPkts': [('SNMPv2-MIB', 'snmpOutPkts')],\n                       'snmpInBadVersions': [('SNMPv2-MIB', 'snmpInBadVersions')],\n                       'snmpInBadCommunityNames': [('SNMPv2-MIB', 'snmpInBadCommunityNames')],\n                       'snmpInBadCommunityUses': [('SNMPv2-MIB', 'snmpInBadCommunityUses')],\n                       'snmpInASNParseErrs': [('SNMPv2-MIB', 'snmpInASNParseErrs')],\n                       'snmpInTooBigs': [('SNMPv2-MIB', 'snmpInTooBigs')],\n                       'snmpInNoSuchNames': [('SNMPv2-MIB', 'snmpInNoSuchNames')],\n                       'snmpInBadValues': [('SNMPv2-MIB', 'snmpInBadValues')],\n                       'snmpInReadOnlys': [('SNMPv2-MIB', 'snmpInReadOnlys')],\n                       'snmpInGenErrs': [('SNMPv2-MIB', 'snmpInGenErrs')],\n                       'snmpInTotalReqVars': [('SNMPv2-MIB', 'snmpInTotalReqVars')],\n                       'snmpInTotalSetVars': [('SNMPv2-MIB', 'snmpInTotalSetVars')],\n                       'snmpInGetRequests': [('SNMPv2-MIB', 'snmpInGetRequests')],\n                       'snmpInGetNexts': [('SNMPv2-MIB', 'snmpInGetNexts')],\n                       'snmpInSetRequests': [('SNMPv2-MIB', 'snmpInSetRequests')],\n                       'snmpInGetResponses': [('SNMPv2-MIB', 'snmpInGetResponses')],\n                       'snmpInTraps': [('SNMPv2-MIB', 'snmpInTraps')],\n                       'snmpOutTooBigs': [('SNMPv2-MIB', 'snmpOutTooBigs')],\n                       'snmpOutNoSuchNames': [('SNMPv2-MIB', 'snmpOutNoSuchNames')],\n                       'snmpOutBadValues': [('SNMPv2-MIB', 'snmpOutBadValues')],\n                       'snmpOutGenErrs': [('SNMPv2-MIB', 'snmpOutGenErrs')],\n                       'snmpOutGetRequests': [('SNMPv2-MIB', 'snmpOutGetRequests')],\n                       'snmpOutGetNexts': [('SNMPv2-MIB', 'snmpOutGetNexts')],\n                       'snmpOutSetRequests': [('SNMPv2-MIB', 'snmpOutSetRequests')],\n                       'snmpOutGetResponses': [('SNMPv2-MIB', 'snmpOutGetResponses')],\n                       'snmpOutTraps': [('SNMPv2-MIB', 'snmpOutTraps')],\n                       'snmpEnableAuthenTraps': [('SNMPv2-MIB', 'snmpEnableAuthenTraps')]}}\n\n    convertImportv2 = {\n        'RFC1065-SMI': commonSyms['RFC1155-SMI/RFC1065-SMI'],\n        'RFC1155-SMI': commonSyms['RFC1155-SMI/RFC1065-SMI'],\n        'RFC1158-MIB': updateDict(\n            dict(commonSyms['RFC1155-SMI/RFC1065-SMI']),\n                 (('nullSpecific', [('SNMPv2-SMI', 'zeroDotZero')]),\n                  ('ipRoutingTable', [('RFC1213-MIB', 'ipRouteTable')]),\n                  ('ipRouteEntry', [('RFC1213-MIB', 'ipRouteEntry')]),\n                  ('ipRouteDest', [('RFC1213-MIB', 'ipRouteDest')]),\n                  ('ipRouteIfIndex', [('RFC1213-MIB', 'ipRouteIfIndex')]),\n                  ('ipRouteMetric1', [('RFC1213-MIB', 'ipRouteMetric1')]),\n                  ('ipRouteMetric2', [('RFC1213-MIB', 'ipRouteMetric2')]),\n                  ('ipRouteMetric3', [('RFC1213-MIB', 'ipRouteMetric3')]),\n                  ('ipRouteMetric4', [('RFC1213-MIB', 'ipRouteMetric4')]),\n                  ('ipRouteNextHop', [('RFC1213-MIB', 'ipRouteNextHop')]),\n                  ('ipRouteType', [('RFC1213-MIB', 'ipRouteType')]),\n                  ('ipRouteProto', [('RFC1213-MIB', 'ipRouteProto')]),\n                  ('ipRouteAge', [('RFC1213-MIB', 'ipRouteAge')]),\n                  ('ipRouteMask', [('RFC1213-MIB', 'ipRouteMask')]),\n                  ('egpInMsgs', [('RFC1213-MIB', 'egpInMsgs')]),\n                  ('egpInErrors', [('RFC1213-MIB', 'egpInErrors')]),\n                  ('egpOutMsgs', [('RFC1213-MIB', 'egpOutMsgs')]),\n                  ('egpOutErrors', [('RFC1213-MIB', 'egpOutErrors')]),\n                  ('egpNeighTable', [('RFC1213-MIB', 'egpNeighTable')]),\n                  ('egpNeighEntry', [('RFC1213-MIB', 'egpNeighEntry')]),\n                  ('egpNeighState', [('RFC1213-MIB', 'egpNeighState')]),\n                  ('egpNeighAddr', [('RFC1213-MIB', 'egpNeighAddr')]),\n                  ('egpNeighAs', [('RFC1213-MIB', 'egpNeighAs')]),\n                  ('egpNeighInMsgs', [('RFC1213-MIB', 'egpNeighInMsgs')]),\n                  ('egpNeighInErrs', [('RFC1213-MIB', 'egpNeighInErrs')]),\n                  ('egpNeighOutMsgs', [('RFC1213-MIB', 'egpNeighOutMsgs')]),\n                  ('egpNeighOutErrs', [('RFC1213-MIB', 'egpNeighOutErrs')]),\n                  ('egpNeighInErrMsgs', [('RFC1213-MIB', 'egpNeighInErrMsgs')]),\n                  ('egpNeighOutErrMsgs', [('RFC1213-MIB', 'egpNeighOutErrMsgs')]),\n                  ('egpNeighStateUps', [('RFC1213-MIB', 'egpNeighStateUps')]),\n                  ('egpNeighStateDowns', [('RFC1213-MIB', 'egpNeighStateDowns')]),\n                  ('egpNeighIntervalHello', [('RFC1213-MIB', 'egpNeighIntervalHello')]),\n                  ('egpNeighIntervalPoll', [('RFC1213-MIB', 'egpNeighIntervalPoll')]),\n                  ('egpNeighMode', [('RFC1213-MIB', 'egpNeighMode')]),\n                  ('egpNeighEventTrigger', [('RFC1213-MIB', 'egpNeighEventTrigger')]),\n                  ('egpAs', [('RFC1213-MIB', 'egpAs')]),\n                  ('snmpEnableAuthTraps', [('SNMPv2-MIB', 'snmpEnableAuthenTraps')]))\n        ),\n        'RFC-1212': {'OBJECT-TYPE': [('SNMPv2-SMI', 'OBJECT-TYPE')]},\n        # XXX 'IndexSyntax': ???\n        'RFC1213-MIB': updateDict(dict(commonSyms['RFC1158-MIB/RFC1213-MIB']),\n                                  (('PhysAddress', [('SNMPv2-TC', 'PhysAddress')]),)),\n        'RFC-1215': {'TRAP-TYPE': [('SNMPv2-SMI', 'TRAP-TYPE')]}\n    }\n\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        raise NotImplementedError()\n\n    def genIndex(self, mibsMap, **kwargs):\n        raise NotImplementedError()\n\n    @staticmethod\n    def isBinary(s):\n        return (isinstance(s, (str, unicode)) and\n                s[0] == '\\'' and s[-2:] in ('\\'b', '\\'B'))\n\n    @staticmethod\n    def isHex(s):\n        return (isinstance(s, (str, unicode)) and s[0] == '\\''\n                and s[-2:] in ('\\'h', '\\'H'))\n\n    def str2int(self, s):\n        if self.isBinary(s):\n            if s[1:-2]:\n                return int(s[1:-2], 2)\n            else:\n                raise error.PySmiSemanticError('empty binary string to int conversion')\n\n        elif self.isHex(s):\n            if s[1:-2]:\n                return int(s[1:-2], 16)\n            else:\n                raise error.PySmiSemanticError('empty hex string to int conversion')\n        else:\n            return int(s)\n"
  },
  {
    "path": "pysmi/codegen/intermediate.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2019, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport re\nfrom time import strptime, strftime\ntry:\n    from collections import OrderedDict\nexcept ImportError:\n    from ordereddict import OrderedDict\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.codegen.base import AbstractCodeGen\nfrom pysmi import error\nfrom pysmi import debug\n\nif sys.version_info[0] > 2:\n    unicode = str\n    long = int\n\n\nclass IntermediateCodeGen(AbstractCodeGen):\n    \"\"\"Turns MIB AST into an intermediate representation.\n\n    This intermediate representation is based on built-in Python types\n    and structures that could easily be used from within the template\n    engines.\n    \"\"\"\n    constImports = {\n        'SNMPv2-SMI': ('iso',\n                       'NOTIFICATION-TYPE',  # bug in some MIBs (e.g. A3COM-HUAWEI-DHCPSNOOP-MIB)\n                       'MODULE-IDENTITY', 'OBJECT-TYPE', 'OBJECT-IDENTITY'),\n        'SNMPv2-TC': ('DisplayString', 'TEXTUAL-CONVENTION',),  # XXX\n        'SNMPv2-CONF': ('MODULE-COMPLIANCE', 'NOTIFICATION-GROUP',),  # XXX\n    }\n\n    # never compile these, they either:\n    # - define MACROs (implementation supplies them)\n    # - or carry conflicting OIDs (so that all IMPORT's of them will be rewritten)\n    # - or have manual fixes\n    # - or import base ASN.1 types from implementation-specific MIBs\n    fakeMibs = ('ASN1',\n                'ASN1-ENUMERATION',\n                'ASN1-REFINEMENT') + AbstractCodeGen.baseMibs\n\n    baseTypes = ['Integer', 'Integer32', 'Bits', 'ObjectIdentifier', 'OctetString']\n\n    SMI_TYPES = {\n        'NetworkAddress': 'IpAddress',  # RFC1065-SMI, RFC1155-SMI -> SNMPv2-SMI\n        'nullSpecific': 'zeroDotZero',  # RFC1158-MIB -> SNMPv2-SMI\n        'ipRoutingTable': 'ipRouteTable',  # RFC1158-MIB -> RFC1213-MIB\n        'snmpEnableAuthTraps': 'snmpEnableAuthenTraps'  # RFC1158-MIB -> SNMPv2-MIB\n    }\n\n    smiv1IdxTypes = ['INTEGER', 'OCTET STRING', 'IPADDRESS', 'NETWORKADDRESS']\n\n    indent = ' ' * 4\n    fakeidx = 1000  # starting index for fake symbols\n\n    def __init__(self):\n        self._rows = set()\n        self._cols = {}  # k, v = name, datatype\n        self._seenSyms = set()\n        self._importMap = {}\n        self._out = {}  # k, v = name, generated code\n        self._moduleIdentityOid = None\n        self._moduleRevision = None\n        self._enterpriseOid = None\n        self._oids = set()\n        self._complianceOids = []\n        self.moduleName = ['DUMMY']\n        self.genRules = {'text': True}\n        self.symbolTable = {}\n\n    @staticmethod\n    def transOpers(symbol):\n        return symbol.replace('-', '_')\n\n    def prepData(self, pdata):\n        data = []\n        for el in pdata:\n            if not isinstance(el, tuple):\n                data.append(el)\n            elif len(el) == 1:\n                data.append(el[0])\n            else:\n                data.append(\n                    self.handlersTable[el[0]](self, self.prepData(el[1:]))\n                )\n        return data\n\n    def genImports(self, imports):\n        # convertion to SNMPv2\n        toDel = []\n        for module in list(imports):\n\n            if module in self.convertImportv2:\n\n                for symbol in imports[module]:\n\n                    if symbol in self.convertImportv2[module]:\n                        toDel.append((module, symbol))\n\n                        for newImport in self.convertImportv2[module][symbol]:\n                            newModule, newSymbol = newImport\n\n                            if newModule in imports:\n                                imports[newModule].append(newSymbol)\n                            else:\n                                imports[newModule] = [newSymbol]\n\n        # removing converted symbols\n        for d in toDel:\n            imports[d[0]].remove(d[1])\n\n        # merging mib and constant imports\n        for module in self.constImports:\n            if module in imports:\n                imports[module] += self.constImports[module]\n            else:\n                imports[module] = self.constImports[module]\n\n        outDict = OrderedDict()\n        outDict['class'] = 'imports'\n        for module in sorted(imports):\n            symbols = []\n            for symbol in set(imports[module]):\n                symbols.append(symbol)\n\n            if symbols:\n                self._seenSyms.update(\n                    [self.transOpers(s) for s in symbols]\n                )\n                self._importMap.update(\n                    [(self.transOpers(s), module) for s in symbols]\n                )\n                if module not in outDict:\n                    outDict[module] = []\n\n                outDict[module].extend(symbols)\n\n        return OrderedDict(imports=outDict), tuple(sorted(imports))\n\n    # noinspection PyMethodMayBeStatic\n    def genLabel(self, symbol):\n        return '-' in symbol and symbol or ''\n\n    def addToExports(self, symbol, moduleIdentity=0):\n        self._seenSyms.add(symbol)\n\n    # noinspection PyUnusedLocal\n    def regSym(self, symbol, outDict, parentOid=None, moduleIdentity=False, moduleCompliance=False):\n        if symbol in self._seenSyms and symbol not in self._importMap:\n            raise error.PySmiSemanticError('Duplicate symbol found: %s' % symbol)\n\n        self.addToExports(symbol, moduleIdentity)\n        self._out[symbol] = outDict\n\n        if 'oid' in outDict:\n            self._oids.add(outDict['oid'])\n\n            if not self._enterpriseOid and outDict['oid'].startswith('1.3.6.1.4.1.'):\n                self._enterpriseOid = '.'.join(outDict['oid'].split('.')[:7])\n\n            if moduleIdentity:\n                if self._moduleIdentityOid:\n                    raise error.PySmiSemanticError('Duplicate module identity')\n                self._moduleIdentityOid = outDict['oid']\n\n            if moduleCompliance:\n                self._complianceOids.append(outDict['oid'])\n\n    def genNumericOid(self, oid):\n        numericOid = ()\n\n        for part in oid:\n            if isinstance(part, tuple):\n                parent, module = part\n                if parent == 'iso':\n                    numericOid += (1,)\n                    continue\n\n                if module not in self.symbolTable:\n                    # XXX do getname for possible future borrowed mibs\n                    raise error.PySmiSemanticError('no module \"%s\" in symbolTable' % module)\n\n                if parent not in self.symbolTable[module]:\n                    raise error.PySmiSemanticError('no symbol \"%s\" in module \"%s\"' % (parent, module))\n                numericOid += self.genNumericOid(self.symbolTable[module][parent]['oid'])\n\n            else:\n                numericOid += (part,)\n\n        return numericOid\n\n    def getBaseType(self, symName, module):\n        if module not in self.symbolTable:\n            raise error.PySmiSemanticError('no module \"%s\" in symbolTable' % module)\n\n        if symName not in self.symbolTable[module]:\n            raise error.PySmiSemanticError('no symbol \"%s\" in module \"%s\"' % (symName, module))\n\n        symType, symSubtype = self.symbolTable[module][symName].get('syntax', (('', ''), ''))\n        if not symType[0]:\n            raise error.PySmiSemanticError('unknown type for symbol \"%s\"' % symName)\n\n        if symType[0] in self.baseTypes:\n            return symType, symSubtype\n\n        else:\n            baseSymType, baseSymSubtype = self.getBaseType(*symType)\n            if isinstance(baseSymSubtype, list):\n                if isinstance(symSubtype, list):\n                    symSubtype += baseSymSubtype\n                else:\n                    symSubtype = baseSymSubtype\n\n            return baseSymType, symSubtype\n\n    # Clause generation functions\n\n    # noinspection PyUnusedLocal\n    def genAgentCapabilities(self, data):\n        name, productRelease, status, description, reference, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'agentcapabilities'\n\n        if productRelease:\n            outDict['productrelease'] = productRelease\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genModuleIdentity(self, data):\n        name, lastUpdated, organization, contactInfo, description, revisions, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'moduleidentity'\n\n        if revisions:\n            outDict['revisions'] = revisions\n\n            self._moduleRevision = revisions[0]['revision']\n\n        if self.genRules['text']:\n            if lastUpdated:\n                outDict['lastupdated'] = lastUpdated\n            if organization:\n                outDict['organization'] = organization\n            if contactInfo:\n                outDict['contactinfo'] = contactInfo\n            if description:\n                outDict['description'] = description\n\n        self.regSym(name, outDict, parentOid, moduleIdentity=True)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genModuleCompliance(self, data):\n        name, status, description, reference, compliances, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'modulecompliance'\n\n        if compliances:\n            outDict['modulecompliance'] = compliances\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid, moduleCompliance=True)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genNotificationGroup(self, data):\n        name, objects, status, description, reference, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'notificationgroup'\n\n        if objects:\n            outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genNotificationType(self, data):\n        name, objects, status, description, reference, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'notificationtype'\n\n        if objects:\n            outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genObjectGroup(self, data):\n        name, objects, status, description, reference, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n        outDict = OrderedDict({'name': name,\n                               'oid': oidStr,\n                               'class': 'objectgroup'})\n\n        if objects:\n            outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in objects]\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genObjectIdentity(self, data):\n        name, status, description, reference, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'objectidentity'\n\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genObjectType(self, data):\n        name, syntax, units, maxaccess, status, description, reference, augmention, index, defval, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n        indexStr, fakeStrlist, fakeSyms = index or ('', '', [])\n\n        defval = self.genDefVal(defval, objname=name)\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n\n        if syntax[0]:\n            nodetype = syntax[0] == 'Bits' and 'scalar' or syntax[0]  # Bits hack\n            nodetype = name in self.symbolTable[self.moduleName[0]]['_symtable_cols'] and 'column' or nodetype\n            outDict['nodetype'] = nodetype\n\n        outDict['class'] = 'objecttype'\n\n        if syntax[1]:\n            outDict['syntax'] = syntax[1]\n        if defval:\n            outDict['default'] = defval\n        if units:\n            outDict['units'] = units\n        if maxaccess:\n            outDict['maxaccess'] = maxaccess\n        if indexStr:\n            outDict['indices'] = indexStr\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n        if augmention:\n            augmention = self.transOpers(augmention)\n            outDict['augmention'] = OrderedDict()\n            outDict['augmention']['name'] = name\n            outDict['augmention']['module'] = self.moduleName[0]\n            outDict['augmention']['object'] = augmention\n        if status:\n            outDict['status'] = status\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        self.regSym(name, outDict, parentOid)\n# TODO\n#        if fakeSyms:  # fake symbols for INDEX to support SMIv1\n#            for i in range(len(fakeSyms)):\n#                fakeOutStr = fakeStrlist[i] % oidStr\n#                self.regSym(fakeSyms[i], fakeOutStr, name)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genTrapType(self, data):\n        name, enterprise, variables, description, reference, value = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        enterpriseStr, parentOid = enterprise\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = enterpriseStr + '.0.' + str(value)\n        outDict['class'] = 'notificationtype'\n\n        if variables:\n            outDict['objects'] = [{'module': self._importMap.get(obj, self.moduleName[0]), 'object': self.transOpers(obj)} for obj in variables]\n\n        if self.genRules['text'] and description:\n            outDict['description'] = description\n\n        if self.genRules['text'] and reference:\n            outDict['reference'] = reference\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genTypeDeclaration(self, data):\n        name, declaration = data\n\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['class'] = 'type'\n\n        if declaration:\n            parentType, attrs = declaration\n            if parentType:  # skipping SEQUENCE case\n                name = self.transOpers(name)\n                outDict.update(attrs)\n                self.regSym(name, outDict)\n\n        return outDict\n\n    # noinspection PyUnusedLocal\n    def genValueDeclaration(self, data):\n        name, oid = data\n\n        label = self.genLabel(name)\n        name = self.transOpers(name)\n\n        oidStr, parentOid = oid\n        outDict = OrderedDict()\n        outDict['name'] = name\n        outDict['oid'] = oidStr\n        outDict['class'] = 'objectidentity'\n\n        self.regSym(name, outDict, parentOid)\n\n        return outDict\n\n    # Subparts generation functions\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genBitNames(self, data):\n        names = data[0]\n        return names\n\n    def genBits(self, data):\n        bits = data[0]\n\n        outDict = OrderedDict()\n        outDict['type'] = 'Bits'\n        outDict['class'] = 'type'\n        outDict['bits'] = OrderedDict()\n\n        for name, bit in sorted(bits, key=lambda x: x[1]):\n            outDict['bits'][name] = bit\n\n        return 'scalar', outDict\n\n    # noinspection PyUnusedLocal\n    def genCompliances(self, data):\n        compliances = []\n\n        for complianceModule in data[0]:\n            name = complianceModule[0] or self.moduleName[0]\n            compliances += [{'object': self.transOpers(compl), 'module': name} for compl in complianceModule[1]]\n\n        return compliances\n\n    # noinspection PyUnusedLocal\n    def genConceptualTable(self, data):\n        row = data[0]\n\n        if row[1] and row[1][-2:] == '()':\n            row = row[1][:-2]\n            self._rows.add(row)\n\n        return 'table', ''\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genContactInfo(self, data):\n        text = data[0]\n        return self.textFilter('contact-info', text)\n\n    # noinspection PyUnusedLocal\n    def genDisplayHint(self, data):\n        return data[0]\n\n    # noinspection PyUnusedLocal\n    def genDefVal(self, data, objname=None):\n        if not data:\n            return {}\n\n        if not objname:\n            return data\n\n        defval = data[0]\n        defvalType = self.getBaseType(objname, self.moduleName[0])\n\n        outDict = OrderedDict(basetype=defvalType[0][0])\n\n        if isinstance(defval, (int, long)):  # number\n            outDict.update(\n                value=defval,\n                format='decimal'\n            )\n\n        elif self.isHex(defval):  # hex\n            # common bug in MIBs\n            if defvalType[0][0] in ('Integer32', 'Integer'):\n                outDict.update(\n                    value=str(int(len(defval) > 3 and\n                                  defval[1:-2] or '0', 16)),\n                    format='hex'\n                )\n\n            else:\n                outDict.update(\n                    value=defval[1:-2],\n                    format='hex'\n                )\n\n        elif self.isBinary(defval):  # binary\n            binval = defval[1:-2]\n\n            # common bug in MIBs\n            if defvalType[0][0] in ('Integer32', 'Integer'):\n                outDict.update(\n                    value=str(int(binval or '0', 2)),\n                    format='bin'\n                )\n\n            else:\n                hexval = binval and hex(int(binval, 2))[2:] or ''\n                outDict.update(value=hexval, format='hex')\n\n        # quoted string\n        elif defval[0] == defval[-1] and defval[0] == '\"':\n            # common bug in MIBs\n            if defval[1:-1] == '' and defvalType != 'OctetString':\n                # a warning should be here\n                return {}  # we will set no default value\n\n            outDict.update(\n                value=defval[1:-1],\n                format='string'\n            )\n\n        # symbol (oid as defval) or name for enumeration member\n        else:\n            # oid\n            if (defvalType[0][0] == 'ObjectIdentifier' and\n                    (defval in self.symbolTable[self.moduleName[0]] or\n                     defval in self._importMap)):\n\n                module = self._importMap.get(defval, self.moduleName[0])\n\n                try:\n                    val = str(self.genNumericOid(\n                        self.symbolTable[module][defval]['oid']))\n\n                    outDict.update(\n                        value=val,\n                        format='oid'\n                    )\n\n                except Exception:\n                    # or no module if it will be borrowed later\n                    raise error.PySmiSemanticError(\n                        'no symbol \"%s\" in module \"%s\"' % (defval, module))\n\n            # enumeration\n            elif (defvalType[0][0] in ('Integer32', 'Integer') and\n                  isinstance(defvalType[1], list)):\n\n                # buggy MIB: DEFVAL { { ... } }\n                if isinstance(defval, list):\n                    defval = [dv for dv in defval\n                              if dv in dict(defvalType[1])]\n                    if defval:\n                        outDict.update(\n                            value=defval[0],\n                            format='enum'\n                        )\n\n                # good MIB: DEFVAL { ... }\n                elif defval in dict(defvalType[1]):\n                    outDict.update(\n                        value=defval,\n                        format='enum'\n                    )\n\n            elif defvalType[0][0] == 'Bits':\n                defvalBits = []\n\n                bits = dict(defvalType[1])\n\n                for bit in defval:\n                    bitValue = bits.get(bit, None)\n                    if bitValue is not None:\n                        defvalBits.append((bit, bitValue))\n\n                    else:\n                        raise error.PySmiSemanticError(\n                            'no such bit as \"%s\" for symbol \"%s\"' % (\n                                bit, objname))\n\n                outDict.update(\n                    value=self.genBits([defvalBits])[1],\n                    format='bits'\n                )\n\n                return outDict\n\n            else:\n                raise error.PySmiSemanticError(\n                    'unknown type \"%s\" for defval \"%s\" of symbol \"%s\"' % (\n                        defvalType, defval, objname))\n\n        return {'default': outDict}\n\n    # noinspection PyMethodMayBeStatic\n    def genDescription(self, data):\n        return self.textFilter('description', data[0])\n\n    # noinspection PyMethodMayBeStatic\n    def genReference(self, data):\n        return self.textFilter('reference', data[0])\n\n    # noinspection PyMethodMayBeStatic\n    def genStatus(self, data):\n        return data[0]\n\n    def genProductRelease(self, data):\n        return data[0]\n\n    def genEnumSpec(self, data):\n        items = data[0]\n        return {'enumeration': dict(items)}\n\n    # noinspection PyUnusedLocal\n    def genTableIndex(self, data):\n        def genFakeSyms(fakeidx, idxType):\n            objType = self.SMI_TYPES.get(idxType, idxType)\n            objType = self.transOpers(objType)\n\n            return {'module': self.moduleName[0],\n                    object: objType}\n\n        indexes = data[0]\n        idxStrlist, fakeSyms, fakeStrlist = [], [], []\n\n        for idx in indexes:\n            isImplied = idx[0]\n            idxName = idx[1]\n            if idxName in self.smiv1IdxTypes:  # SMIv1 support\n                idxType = idxName\n                fakeSymStr, idxName = genFakeSyms(self.fakeidx, idxType)\n                fakeStrlist.append(fakeSymStr)\n                fakeSyms.append(idxName)\n                self.fakeidx += 1\n\n            index = OrderedDict()\n            index['module'] = self._importMap.get(idxName, self.moduleName[0])\n            index['object'] = idxName\n            index['implied'] = isImplied\n            idxStrlist.append(index)\n\n        return idxStrlist, fakeStrlist, fakeSyms\n\n    def genIntegerSubType(self, data):\n        ranges = []\n        for rng in data[0]:\n            vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng\n            vmin, vmax = self.str2int(vmin), self.str2int(vmax)\n            ran = OrderedDict()\n            ran['min'] = vmin\n            ran['max'] = vmax\n            ranges.append(ran)\n\n        return {'range': ranges}\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genMaxAccess(self, data):\n        return data[0]\n\n    def genOctetStringSubType(self, data):\n        sizes = []\n        for rng in data[0]:\n            vmin, vmax = len(rng) == 1 and (rng[0], rng[0]) or rng\n            vmin, vmax = self.str2int(vmin), self.str2int(vmax)\n\n            size = OrderedDict()\n            size['min'] = vmin\n            size['max'] = vmax\n            sizes.append(size)\n\n        return {'size': sizes}\n\n    # noinspection PyUnusedLocal\n    def genOid(self, data):\n        out = ()\n        parent = ''\n        for el in data[0]:\n            if isinstance(el, (str, unicode)):\n                parent = self.transOpers(el)\n                out += ((parent, self._importMap.get(parent, self.moduleName[0])),)\n\n            elif isinstance(el, (int, long)):\n                out += (el,)\n\n            elif isinstance(el, tuple):\n                out += (el[1],)  # XXX Do we need to create a new object el[0]?\n\n            else:\n                raise error.PySmiSemanticError('unknown datatype for OID: %s' % el)\n\n        return '.'.join([str(x) for x in self.genNumericOid(out)]), parent\n\n    # noinspection PyUnusedLocal\n    def genObjects(self, data):\n        if data[0]:\n            return [self.transOpers(obj) for obj in data[0]]  # XXX self.transOpers or not??\n        return []\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genTime(self, data):\n        times = []\n        for timeStr in data:\n\n            if len(timeStr) == 11:\n                timeStr = '19' + timeStr\n\n            # XXX raise in strict mode\n            # elif lenTimeStr != 13:\n            #  raise error.PySmiSemanticError(\"Invalid date %s\" % t)\n            try:\n                times.append(strftime('%Y-%m-%d %H:%M', strptime(timeStr, '%Y%m%d%H%MZ')))\n\n            except ValueError:\n                # XXX raise in strict mode\n                # raise error.PySmiSemanticError(\"Invalid date %s: %s\" % (t, sys.exc_info()[1]))\n                timeStr = '197001010000Z'  # dummy date for dates with typos\n                times.append(strftime('%Y-%m-%d %H:%M', strptime(timeStr, '%Y%m%d%H%MZ')))\n\n        return times\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genLastUpdated(self, data):\n        return data[0]\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genOrganization(self, data):\n        return self.textFilter('organization', data[0])\n\n    # noinspection PyUnusedLocal\n    def genRevisions(self, data):\n        revisions = []\n        for x in data[0]:\n            revision = OrderedDict()\n            revision['revision'] = self.genTime([x[0]])[0]\n            revision['description'] = self.textFilter('description', x[1][1])\n            revisions.append(revision)\n        return revisions\n\n    def genRow(self, data):\n        row = data[0]\n        row = self.transOpers(row)\n\n        return row in self.symbolTable[self.moduleName[0]]['_symtable_rows'] and (\n             'row', '') or self.genSimpleSyntax(data)\n\n    # noinspection PyUnusedLocal\n    def genSequence(self, data):\n        cols = data[0]\n        self._cols.update(cols)\n        return '', ''\n\n    def genSimpleSyntax(self, data):\n        objType = data[0]\n        objType = self.SMI_TYPES.get(objType, objType)\n        objType = self.transOpers(objType)\n\n        subtype = len(data) == 2 and data[1] or {}\n\n        outDict = OrderedDict()\n        outDict['type'] = objType\n        outDict['class'] = 'type'\n\n        if subtype:\n            outDict['constraints'] = subtype\n\n        return 'scalar', outDict\n\n    # noinspection PyUnusedLocal\n    def genTypeDeclarationRHS(self, data):\n        if len(data) == 1:\n            parentType, attrs = data[0]\n\n            outDict = OrderedDict()\n            if not attrs:\n                return outDict\n            # just syntax\n            outDict['type'] = attrs\n\n        else:\n            # Textual convention\n            display, status, description, reference, syntax = data\n            parentType, attrs = syntax\n\n            outDict = OrderedDict()\n            outDict['type'] = attrs\n            outDict['class'] = 'textualconvention'\n            if display:\n                outDict['displayhint'] = display\n            if status:\n                outDict['status'] = status\n            if self.genRules['text'] and description:\n                outDict['description'] = description\n            if self.genRules['text'] and reference:\n                outDict['reference'] = reference\n\n        return parentType, outDict\n\n    # noinspection PyMethodMayBeStatic,PyUnusedLocal\n    def genUnits(self, data):\n        text = data[0]\n        return self.textFilter('units', text)\n\n    handlersTable = {\n        'agentCapabilitiesClause': genAgentCapabilities,\n        'moduleIdentityClause': genModuleIdentity,\n        'moduleComplianceClause': genModuleCompliance,\n        'notificationGroupClause': genNotificationGroup,\n        'notificationTypeClause': genNotificationType,\n        'objectGroupClause': genObjectGroup,\n        'objectIdentityClause': genObjectIdentity,\n        'objectTypeClause': genObjectType,\n        'trapTypeClause': genTrapType,\n        'typeDeclaration': genTypeDeclaration,\n        'valueDeclaration': genValueDeclaration,\n        'PRODUCT-RELEASE': genProductRelease,\n        'ApplicationSyntax': genSimpleSyntax,\n        'BitNames': genBitNames,\n        'BITS': genBits,\n        'ComplianceModules': genCompliances,\n        'conceptualTable': genConceptualTable,\n        'CONTACT-INFO': genContactInfo,\n        'DISPLAY-HINT': genDisplayHint,\n        'DEFVAL': genDefVal,\n        'DESCRIPTION': genDescription,\n        'REFERENCE': genReference,\n        'Status': genStatus,\n        'enumSpec': genEnumSpec,\n        'INDEX': genTableIndex,\n        'integerSubType': genIntegerSubType,\n        'MaxAccessPart': genMaxAccess,\n        'Notifications': genObjects,\n        'octetStringSubType': genOctetStringSubType,\n        'objectIdentifier': genOid,\n        'Objects': genObjects,\n        'LAST-UPDATED': genLastUpdated,\n        'ORGANIZATION': genOrganization,\n        'Revisions': genRevisions,\n        'row': genRow,\n        'SEQUENCE': genSequence,\n        'SimpleSyntax': genSimpleSyntax,\n        'typeDeclarationRHS': genTypeDeclarationRHS,\n        'UNITS': genUnits,\n        'VarTypes': genObjects,\n        # 'a': lambda x: genXXX(x, 'CONSTRAINT')\n    }\n\n    # TODO: make intermediate format less tied to JSON\n    # One thing is to produce OIDs in a tuple form\n    # The other thing is index data - may be we should\n    # have it prepared at the intermediate stage...?\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        self.genRules['text'] = kwargs.get('genTexts', False)\n        self.textFilter = kwargs.get('textFilter') or (lambda symbol, text: re.sub(r'\\s+', ' ', text))\n        self.symbolTable = symbolTable\n        self._rows.clear()\n        self._cols.clear()\n        self._seenSyms.clear()\n        self._importMap.clear()\n        self._out.clear()\n        self._moduleIdentityOid = None\n        self._enterpriseOid = None\n        self._oids = set()\n        self._complianceOids = []\n        self.moduleName[0], moduleOid, imports, declarations = ast\n\n        outDict, importedModules = self.genImports(imports and imports or {})\n\n        for declr in declarations or []:\n            if declr:\n                self.handlersTable[declr[0]](self, self.prepData(declr[1:]))\n\n        for sym in self.symbolTable[self.moduleName[0]]['_symtable_order']:\n            if sym not in self._out:\n                raise error.PySmiCodegenError('No generated code for symbol %s' % sym)\n\n            outDict[sym] = self._out[sym]\n\n        outDict['meta'] = OrderedDict()\n        outDict['meta']['module'] = self.moduleName[0]\n\n        if 'comments' in kwargs:\n            outDict['meta']['comments'] = kwargs['comments']\n\n        debug.logger & debug.flagCodegen and debug.logger(\n            'canonical MIB name %s (%s), imported MIB(s) %s' % (\n                self.moduleName[0], moduleOid, ','.join(importedModules) or '<none>'))\n\n        return MibInfo(oid=moduleOid,\n                       identity=self._moduleIdentityOid,\n                       name=self.moduleName[0],\n                       revision=self._moduleRevision,\n                       oids=self._oids,\n                       enterprise=self._enterpriseOid,\n                       compliance=self._complianceOids,\n                       imported=tuple([x for x in importedModules if x not in self.fakeMibs])), outDict\n"
  },
  {
    "path": "pysmi/codegen/jfilters.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2019, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n\ndef capfirst(text):\n    if not text:\n        return text\n\n    return text[0].upper() + text[1:]\n"
  },
  {
    "path": "pysmi/codegen/jsondoc.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport os\ntry:\n    import json\nexcept ImportError:\n    import simplejson as json\ntry:\n    from collections import OrderedDict\nexcept ImportError:\n    from ordereddict import OrderedDict\nfrom pysmi.codegen.intermediate import IntermediateCodeGen\nfrom pysmi.codegen import jfilters\nfrom pysmi import error\nfrom pysmi import debug\n\nimport jinja2\n\n\nif sys.version_info[0] > 2:\n    # noinspection PyShadowingBuiltins\n    unicode = str\n    # noinspection PyShadowingBuiltins\n    long = int\n\n\nclass JsonCodeGen(IntermediateCodeGen):\n    \"\"\"Turns MIB AST into JSON document.\n\n    Builds JSON document representing MIB module supplied in form of\n    an Abstract Syntax Tree on input.\n\n    Instance of this class is supposed to be passed to *MibCompiler*,\n    the rest is internal to *MibCompiler*.\n    \"\"\"\n    TEMPLATE_NAME = 'jsondoc/base.j2'\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        mibInfo, context = IntermediateCodeGen.genCode(self, ast, symbolTable, **kwargs)\n\n        # TODO: reduce code duplication with the other codegens\n\n        searchPath = os.path.join(os.path.dirname(__file__), 'templates')\n\n        dstTemplate = kwargs.get('dstTemplate')\n        if dstTemplate:\n            searchPath.insert(0, os.path.dirname(os.path.abspath(dstTemplate)))\n\n        env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchPath),\n                                 trim_blocks=True, lstrip_blocks=True)\n\n        env.filters['capfirst'] = jfilters.capfirst\n\n        try:\n            tmpl = env.get_template(dstTemplate or self.TEMPLATE_NAME)\n            text = tmpl.render(mib=context)\n\n        except jinja2.exceptions.TemplateError:\n            err = sys.exc_info()[1]\n            raise error.PySmiCodegenError('Jinja template rendering error: %s' % err)\n\n        debug.logger & debug.flagCodegen and debug.logger(\n            'canonical MIB name %s (%s), imported MIB(s) %s, rendered from '\n            '%s, JSON document size %d bytes' % (\n                mibInfo.name, mibInfo.identity,\n                ','.join(mibInfo.imported) or '<none>',\n                dstTemplate, len(text)))\n\n        return mibInfo, text\n\n    # TODO: move this to a template\n    def genIndex(self, processed, **kwargs):\n        outDict = {\n            'meta': {},\n            'identity': {},\n            'enterprise': {},\n            'compliance': {},\n            'oids': {},\n        }\n        if kwargs.get('old_index_data'):\n            try:\n                outDict.update(\n                    json.loads(kwargs['old_index_data'])\n                )\n\n            except Exception:\n                raise error.PySmiCodegenError('Index load error: %s' % sys.exc_info()[1])\n\n        def order(top):\n            if isinstance(top, dict):\n                new_top = OrderedDict()\n                try:\n                    # first try to sort keys as OIDs\n                    for k in sorted(top, key=lambda x: [int(y) for y in x.split('.')]):\n                        new_top[k] = order(top[k])\n\n                except ValueError:\n                    for k in sorted(top):\n                        new_top[k] = order(top[k])\n\n                return new_top\n            elif isinstance(top, list):\n                new_top = []\n                for e in sorted(set(top)):\n                    new_top.append(order(e))\n\n                return new_top\n\n            return top\n\n        for module, status in processed.items():\n            modData = outDict['identity']\n            identity_oid = getattr(status, 'identity', None)\n            if identity_oid:\n                if identity_oid not in modData:\n                    modData[identity_oid] = []\n\n                modData[identity_oid].append(module)\n\n            modData = outDict['enterprise']\n            enterprise_oid = getattr(status, 'enterprise', None)\n            if enterprise_oid:\n                if enterprise_oid not in modData:\n                    modData[enterprise_oid] = []\n\n                modData[enterprise_oid].append(module)\n\n            modData = outDict['compliance']\n            compliance_oids = getattr(status, 'compliance', ())\n            for compliance_oid in compliance_oids:\n                if compliance_oid not in modData:\n                    modData[compliance_oid] = []\n                modData[compliance_oid].append(module)\n\n            modData = outDict['oids']\n            objects_oids = getattr(status, 'oids', ())\n            for object_oid in objects_oids:\n                if object_oid not in modData:\n                    modData[object_oid] = []\n\n                modData[object_oid].append(module)\n\n            if modData:\n                unique_prefixes = {}\n                for oid in sorted(modData, key=lambda x: x.count('.')):\n                    for oid_prefix, modules in unique_prefixes.items():\n                        if oid.startswith(oid_prefix) and set(modules).issuperset(modData[oid]):\n                            break\n                    else:\n                        unique_prefixes[oid] = modData[oid]\n\n                outDict['oids'] = unique_prefixes\n\n        if 'comments' in kwargs:\n            outDict['meta']['comments'] = kwargs['comments']\n\n        debug.logger & debug.flagCodegen and debug.logger(\n            'OID->MIB index built, %s entries' % len(processed))\n\n        return json.dumps(order(outDict), indent=2)\n"
  },
  {
    "path": "pysmi/codegen/null.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.codegen.base import AbstractCodeGen\nfrom pysmi import debug\n\n\nclass NullCodeGen(AbstractCodeGen):\n    \"\"\"Dummy code generation backend.\n\n       Could be used for disabling code generation at *MibCompiler*.\n    \"\"\"\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        debug.logger & debug.flagCodegen and debug.logger('%s invoked' % self.__class__.__name__)\n        return MibInfo(oid=None, name='', imported=[]), ''\n\n    def genIndex(self, mibsMap, **kwargs):\n        return ''\n"
  },
  {
    "path": "pysmi/codegen/pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport os\ntry:\n    from collections import OrderedDict\nexcept ImportError:\n    from ordereddict import OrderedDict\nfrom pysmi.codegen.intermediate import IntermediateCodeGen\nfrom pysmi.codegen import jfilters\nfrom pysmi import error\nfrom pysmi import debug\n\nimport jinja2\n\n\nif sys.version_info[0] > 2:\n    # noinspection PyShadowingBuiltins\n    unicode = str\n    # noinspection PyShadowingBuiltins\n    long = int\n\n\nclass PySnmpCodeGen(IntermediateCodeGen):\n    \"\"\"Turns MIB AST into pysnmp Python code.\n\n    Builds Python module representing MIB module in terms of pysnmp objects\n    from MIB supplied in form of an Abstract Syntax Tree on input.\n\n    Instance of this class is supposed to be passed to *MibCompiler*,\n    the rest is internal to *MibCompiler*.\n    \"\"\"\n\n    defaultMibPackages = ('pysnmp.smi.mibs', 'pysnmp_mibs')\n\n    TEMPLATE_NAME = 'pysnmp/mib-definitions.j2'\n\n    SMI_OBJECTS = {\n        'MODULE-IDENTITY': ['ModuleIdentity'],\n        'OBJECT-TYPE': ['MibScalar', 'MibTable', 'MibTableRow', 'MibTableColumn'],\n        'NOTIFICATION-TYPE': ['NotificationType'],\n        'TEXTUAL-CONVENTION': ['TextualConvention'],\n        'MODULE-COMPLIANCE': ['ModuleCompliance'],\n        'OBJECT-GROUP': ['ObjectGroup'],\n        'NOTIFICATION-GROUP': ['NotificationGroup'],\n        'AGENT-CAPABILITIES': ['AgentCapabilities'],\n        'OBJECT-IDENTITY': ['ObjectIdentity'],\n        'TRAP-TYPE': ['NotificationType'],\n        'BITS': ['Bits']\n    }\n\n    SMI_TYPES = {\n        'COUNTER32': 'Counter32',\n        'COUNTER64': 'Counter64',\n        'GAUGE32': 'Gauge32',\n        'INTEGER': 'Integer32',  # XXX\n        'INTEGER32': 'Integer32',\n        'IPADDRESS': 'IpAddress',\n        'NETWORKADDRESS': 'IpAddress',\n        'OBJECT IDENTIFIER': 'ObjectIdentifier',\n        'OCTET STRING': 'OctetString',\n        'OPAQUE': 'Opaque',\n        'TIMETICKS': 'TimeTicks',\n        'UNSIGNED32': 'Unsigned32',\n        'Counter': 'Counter32',\n        'Gauge': 'Gauge32',\n        'NetworkAddress': 'IpAddress',  # RFC1065-SMI, RFC1155-SMI -> SNMPv2-SMI\n        'nullSpecific': 'zeroDotZero',  # RFC1158-MIB -> SNMPv2-SMI\n        'ipRoutingTable': 'ipRouteTable',  # RFC1158-MIB -> RFC1213-MIB\n        'snmpEnableAuthTraps': 'snmpEnableAuthenTraps'  # RFC1158-MIB -> SNMPv2-MIB\n    }\n\n    # never compile these, they either:\n    # - define MACROs (implementation supplies them)\n    # - or carry conflicting OIDs (so that all IMPORT's of them will be rewritten)\n    # - or have manual fixes\n    # - or import base ASN.1 types from implementation-specific MIBs\n    fakeMibs = ('ASN1',\n                'ASN1-ENUMERATION',\n                'ASN1-REFINEMENT')\n    baseMibs = ('PYSNMP-USM-MIB',\n                'SNMP-FRAMEWORK-MIB',\n                'SNMP-TARGET-MIB',\n                'TRANSPORT-ADDRESS-MIB',\n                'INET-ADDRESS-MIB') + IntermediateCodeGen.baseMibs\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        mibInfo, context = IntermediateCodeGen.genCode(self, ast, symbolTable, **kwargs)\n\n        # Adapt intermediate context to pysnmp template requirements\n\n        # Translate SMI objects names in IMPORT\n\n        imports = OrderedDict()\n\n        for module, symbols in context.get('imports', {}).items():\n            if not isinstance(symbols, list):\n                continue\n\n            imports[module] = []\n\n            for symbol in symbols:\n                if symbol in self.SMI_OBJECTS:\n                    imports[module].extend(self.SMI_OBJECTS[symbol])\n                else:\n                    imports[module].append(symbol)\n\n        context['imports'] = imports\n\n        # Turn string OIDs into tuples which is native to pysnmp\n        # TODO: we should make intermediate format producing tuples\n\n        def translateOids(dct):\n            for key, value in tuple(dct.items()):\n                if isinstance(value, dict):\n                    translateOids(value)\n                elif key == 'oid':\n                    dct[key] = tuple(int(x) for x in value.split('.'))\n\n        translateOids(context)\n\n        # Translate SMI types into pysnmp class names\n\n        # Sort Managed Objects by OID\n        objects = OrderedDict()\n\n        for symbol, definition in sorted(\n                context.items(), key=lambda x: x[1].get('oid', ())):\n            objects[symbol] = definition\n\n        context = objects\n\n        # Render Python code\n\n        searchPath = [os.path.join(os.path.dirname(__file__), 'templates')]\n\n        # TODO: add unit test on custom template\n\n        dstTemplate = kwargs.get('dstTemplate')\n        if dstTemplate:\n            searchPath.insert(0, os.path.dirname(os.path.abspath(dstTemplate)))\n\n        env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchPath),\n                                 trim_blocks=True, lstrip_blocks=True)\n\n        env.filters['capfirst'] = jfilters.capfirst\n\n        try:\n            tmpl = env.get_template(dstTemplate or self.TEMPLATE_NAME)\n            text = tmpl.render(mib=context)\n\n        except jinja2.exceptions.TemplateError:\n            err = sys.exc_info()[1]\n            raise error.PySmiCodegenError('Jinja template rendering error: %s' % err)\n\n        debug.logger & debug.flagCodegen and debug.logger(\n            'canonical MIB name %s (%s), imported MIB(s) %s, rendered from '\n            '%s, Python code size %d bytes' % (\n                mibInfo.name, mibInfo.identity,\n                ','.join(mibInfo.imported) or '<none>',\n                dstTemplate, len(text)))\n\n        return mibInfo, text\n\n\n# backward compatibility\nbaseMibs = PySnmpCodeGen.baseMibs\nfakeMibs = PySnmpCodeGen.fakeMibs\n"
  },
  {
    "path": "pysmi/codegen/symtable.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n# Build an internally used symbol table for each passed MIB.\n#\nimport sys\nfrom keyword import iskeyword\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.codegen.base import AbstractCodeGen, dorepr\nfrom pysmi import error\nfrom pysmi import debug\n\nif sys.version_info[0] > 2:\n    # noinspection PyShadowingBuiltins\n    unicode = str\n    # noinspection PyShadowingBuiltins\n    long = int\n\n\nclass SymtableCodeGen(AbstractCodeGen):\n    symsTable = {\n        'MODULE-IDENTITY': ('ModuleIdentity',),\n        'OBJECT-TYPE': ('MibScalar', 'MibTable', 'MibTableRow', 'MibTableColumn'),\n        'NOTIFICATION-TYPE': ('NotificationType',),\n        'TEXTUAL-CONVENTION': ('TextualConvention',),\n        'MODULE-COMPLIANCE': ('ModuleCompliance',),\n        'OBJECT-GROUP': ('ObjectGroup',),\n        'NOTIFICATION-GROUP': ('NotificationGroup',),\n        'AGENT-CAPABILITIES': ('AgentCapabilities',),\n        'OBJECT-IDENTITY': ('ObjectIdentity',),\n        'TRAP-TYPE': ('NotificationType',),  # smidump always uses NotificationType\n        'BITS': ('Bits',),\n    }\n\n    constImports = {\n        'SNMPv2-SMI': ('iso',\n                       'Bits',  # XXX\n                       'Integer32',  # XXX\n                       'TimeTicks',  # bug in some IETF MIBs\n                       'Counter32',  # bug in some IETF MIBs (e.g. DSA-MIB)\n                       'Counter64',  # bug in some MIBs (e.g.A3COM-HUAWEI-LswINF-MIB)\n                       'NOTIFICATION-TYPE',  # bug in some MIBs (e.g. A3COM-HUAWEI-DHCPSNOOP-MIB)\n                       'Gauge32',  # bug in some IETF MIBs (e.g. DSA-MIB)\n                       'MODULE-IDENTITY', 'OBJECT-TYPE', 'OBJECT-IDENTITY', 'Unsigned32', 'IpAddress',  # XXX\n                       'MibIdentifier'),  # OBJECT IDENTIFIER\n        'SNMPv2-TC': ('DisplayString', 'TEXTUAL-CONVENTION',),  # XXX\n        'SNMPv2-CONF': ('MODULE-COMPLIANCE', 'NOTIFICATION-GROUP',),  # XXX\n    }\n\n    baseTypes = ['Integer', 'Integer32', 'Bits', 'ObjectIdentifier', 'OctetString']\n\n    typeClasses = {\n        'COUNTER32': 'Counter32',\n        'COUNTER64': 'Counter64',\n        'GAUGE32': 'Gauge32',\n        'INTEGER': 'Integer32',  # XXX\n        'INTEGER32': 'Integer32',\n        'IPADDRESS': 'IpAddress',\n        'NETWORKADDRESS': 'IpAddress',\n        'OBJECT IDENTIFIER': 'ObjectIdentifier',\n        'OCTET STRING': 'OctetString',\n        'OPAQUE': 'Opaque',\n        'TIMETICKS': 'TimeTicks',\n        'UNSIGNED32': 'Unsigned32',\n        'Counter': 'Counter32',\n        'Gauge': 'Gauge32',\n        'NetworkAddress': 'IpAddress',  # RFC1065-SMI, RFC1155-SMI -> SNMPv2-SMI\n        'nullSpecific': 'zeroDotZero',  # RFC1158-MIB -> SNMPv2-SMI\n        'ipRoutingTable': 'ipRouteTable',  # RFC1158-MIB -> RFC1213-MIB\n        'snmpEnableAuthTraps': 'snmpEnableAuthenTraps'  # RFC1158-MIB -> SNMPv2-MIB\n    }\n\n    smiv1IdxTypes = ['INTEGER', 'OCTET STRING', 'IPADDRESS', 'NETWORKADDRESS']\n    ifTextStr = 'if mibBuilder.loadTexts: '\n    indent = ' ' * 4\n    fakeidx = 1000  # starting index for fake symbols\n\n    def __init__(self):\n        self._rows = set()\n        self._cols = {}  # k, v = name, datatype\n        self._exports = set()\n        self._postponedSyms = {}  # k, v = symbol, (parents, properties)\n        self._parentOids = set()\n        self._importMap = {}  # k, v = symbol, MIB\n        self._symsOrder = []\n        self._out = {}  # k, v = symbol, properties\n        self.moduleName = ['DUMMY']\n        self._moduleRevision = None\n        self.genRules = {'text': True}\n\n    def symTrans(self, symbol):\n        if symbol in self.symsTable:\n            return self.symsTable[symbol]\n\n        return symbol,\n\n    @staticmethod\n    def transOpers(symbol):\n        if iskeyword(symbol):\n            symbol = 'pysmi_' + symbol\n\n        return symbol.replace('-', '_')\n\n    def prepData(self, pdata, classmode=False):\n        data = []\n        for el in pdata:\n            if not isinstance(el, tuple):\n                data.append(el)\n\n            elif len(el) == 1:\n                data.append(el[0])\n\n            else:\n                data.append(self.handlersTable[el[0]](self, self.prepData(el[1:], classmode=classmode), classmode=classmode))\n\n        return data\n\n    def genImports(self, imports):\n        # convertion to SNMPv2\n        toDel = []\n        for module in list(imports):\n\n            if module in self.convertImportv2:\n\n                for symbol in imports[module]:\n\n                    if symbol in self.convertImportv2[module]:\n                        toDel.append((module, symbol))\n\n                        for newImport in self.convertImportv2[module][symbol]:\n                            newModule, newSymbol = newImport\n\n                            if newModule in imports:\n                                imports[newModule].append(newSymbol)\n                            else:\n                                imports[newModule] = [newSymbol]\n\n        # removing converted symbols\n        for d in toDel:\n            imports[d[0]].remove(d[1])\n\n        # merging mib and constant imports\n        for module in self.constImports:\n            if module in imports:\n                imports[module] += self.constImports[module]\n            else:\n                imports[module] = self.constImports[module]\n\n        for module in sorted(imports):\n            symbols = ()\n            for symbol in set(imports[module]):\n                symbols += self.symTrans(symbol)\n\n            if symbols:\n                self._importMap.update([(self.transOpers(s), module) for s in symbols])\n\n        return {}, tuple(sorted(imports))\n\n    def allParentsExists(self, parents):\n        parentsExists = True\n        for parent in parents:\n            if not (parent in self._out or\n                    parent in self._importMap or\n                    parent in self.baseTypes or\n                    parent in ('MibTable', 'MibTableRow', 'MibTableColumn') or\n                    parent in self._rows):\n                parentsExists = False\n                break\n\n        return parentsExists\n\n    def regSym(self, symbol, symProps, parents=()):\n        if symbol in self._out or symbol in self._postponedSyms:  # add to strict mode - or symbol in self._importMap:\n            raise error.PySmiSemanticError('Duplicate symbol found: %s' % symbol)\n\n        if self.allParentsExists(parents):\n            self._out[symbol] = symProps\n            self._symsOrder.append(symbol)\n            self.regPostponedSyms()\n\n        else:\n            self._postponedSyms[symbol] = (parents, symProps)\n\n    def regPostponedSyms(self):\n        regedSyms = []\n        for sym, val in self._postponedSyms.items():\n            parents, symProps = val\n\n            if self.allParentsExists(parents):\n                self._out[sym] = symProps\n                self._symsOrder.append(sym)\n                regedSyms.append(sym)\n\n        for sym in regedSyms:\n            self._postponedSyms.pop(sym)\n\n        # Clause handlers\n\n    # noinspection PyUnusedLocal\n    def genAgentCapabilities(self, data, classmode=False):\n        origName, release, status, description, reference, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'AgentCapabilities',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genModuleIdentity(self, data, classmode=False):\n        origName, lastUpdated, organization, contactInfo, description, revisions, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'ModuleIdentity',\n                    'oid': oid,\n                    'origName': origName}\n\n        if revisions:\n            self._moduleRevision = revisions[0]\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genModuleCompliance(self, data, classmode=False):\n        origName, status, description, reference, compliances, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'ModuleCompliance',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genNotificationGroup(self, data, classmode=False):\n        origName, objects, status, description, reference, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'NotificationGroup',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genNotificationType(self, data, classmode=False):\n        origName, objects, status, description, reference, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'NotificationType',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genObjectGroup(self, data, classmode=False):\n        origName, objects, status, description, reference, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'ObjectGroup',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genObjectIdentity(self, data, classmode=False):\n        origName, status, description, reference, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'ObjectIdentity',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genObjectType(self, data, classmode=False):\n        origName, syntax, units, maxaccess, status, description, reference, augmention, index, defval, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'ObjectType',\n                    'oid': oid,\n                    'syntax': syntax,  # (type, module), subtype\n                    'origName': origName}\n\n        parents = [syntax[0][0]]\n\n        if augmention:\n            parents.append(self.transOpers(augmention))\n\n        if defval:  # XXX\n            symProps['defval'] = defval\n\n        if index and index[1]:\n            namepart, fakeIndexes, fakeSymSyntax = index\n            for fakeIdx, fakeSyntax in zip(fakeIndexes, fakeSymSyntax):\n                fakeName = namepart + str(fakeIdx)\n\n                fakeSymProps = {'type': 'fakeColumn',\n                                'oid': oid + (fakeIdx,),\n                                'syntax': fakeSyntax,\n                                'origName': fakeName}\n\n                self.regSym(fakeName, fakeSymProps)\n\n        self.regSym(pysmiName, symProps, parents)\n\n    # noinspection PyUnusedLocal\n    def genTrapType(self, data, classmode=False):\n        origName, enterprise, variables, description, reference, value = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'NotificationType',\n                    'oid': enterprise + (0, value),\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # noinspection PyUnusedLocal\n    def genTypeDeclaration(self, data, classmode=False):\n        origName, declaration = data\n\n        pysmiName = self.transOpers(origName)\n\n        if declaration:\n            parentType, attrs = declaration\n            if parentType:  # skipping SEQUENCE case\n                symProps = {'type': 'TypeDeclaration',\n                            'syntax': declaration,  # (type, module), subtype\n                            'origName': origName}\n\n                self.regSym(pysmiName, symProps, [declaration[0][0]])\n\n    # noinspection PyUnusedLocal\n    def genValueDeclaration(self, data, classmode=False):\n        origName, oid = data\n\n        pysmiName = self.transOpers(origName)\n\n        symProps = {'type': 'MibIdentifier',\n                    'oid': oid,\n                    'origName': origName}\n\n        self.regSym(pysmiName, symProps)\n\n    # Subparts generation functions\n    # noinspection PyUnusedLocal,PyMethodMayBeStatic\n    def genBitNames(self, data, classmode=False):\n        names = data[0]\n        return names\n\n    # noinspection PyUnusedLocal,PyMethodMayBeStatic\n    def genBits(self, data, classmode=False):\n        bits = data[0]\n        return ('Bits', ''), bits\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genCompliances(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal\n    def genConceptualTable(self, data, classmode=False):\n        row = data[0]\n        if row[0] and row[0][0]:\n            self._rows.add(self.transOpers(row[0][0]))\n        return ('MibTable', ''), ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genContactInfo(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genDisplayHint(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal\n    def genDefVal(self, data, classmode=False):  # XXX should be fixed, see pysnmp.py\n        defval = data[0]\n\n        if isinstance(defval, (int, long)):  # number\n            val = str(defval)\n\n        elif self.isHex(defval):  # hex\n            val = 'hexValue=\"' + defval[1:-2] + '\"'  # not working for Integer baseTypes\n\n        elif self.isBinary(defval):  # binary\n            binval = defval[1:-2]\n            hexval = binval and hex(int(binval, 2))[2:] or ''\n            val = 'hexValue=\"' + hexval + '\"'\n\n        elif isinstance(defval, list):  # bits list\n            val = defval\n\n        elif defval[0] == defval[-1] and defval[0] == '\"':  # quoted strimg\n            val = dorepr(defval[1:-1])\n\n        else:  # symbol (oid as defval) or name for enumeration member\n            if defval in self._out or defval in self._importMap:\n                val = defval + '.getName()'\n            else:\n                val = dorepr(defval)\n\n        return val\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genDescription(self, data, classmode=False):\n        return ''\n\n    def genReference(self, data, classmode=False):\n        return ''\n\n    def genStatus(self, data, classmode=False):\n        return ''\n\n    def genProductRelease(self, data, classmode=False):\n        return ''\n\n    def genEnumSpec(self, data, classmode=False):\n        return self.genBits(data, classmode=classmode)[1]\n\n    def genIndex(self, data, classmode=False):\n        indexes = data[0]\n\n        fakeIdxName = 'pysmiFakeCol'\n        fakeIndexes, fakeSymsSyntax = [], []\n\n        for idx in indexes:\n            idxName = idx[1]\n            if idxName in self.smiv1IdxTypes:  # SMIv1 support\n                idxType = idxName\n\n                objType = self.typeClasses.get(idxType, idxType)\n                objType = self.transOpers(objType)\n\n                fakeIndexes.append(self.fakeidx)\n                fakeSymsSyntax.append((('MibTableColumn', ''), objType))\n                self.fakeidx += 1\n\n        return fakeIdxName, fakeIndexes, fakeSymsSyntax\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genIntegerSubType(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genMaxAccess(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genOctetStringSubType(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal\n    def genOid(self, data, classmode=False):\n        out = ()\n        for el in data[0]:\n            if isinstance(el, (str, unicode)):\n                parent = self.transOpers(el)\n                self._parentOids.add(parent)\n                out += ((parent, self._importMap.get(parent, self.moduleName[0])),)\n\n            elif isinstance(el, (int, long)):\n                out += (el,)\n\n            elif isinstance(el, tuple):\n                out += (el[1],)  # XXX Do we need to create a new object el[0]?\n\n            else:\n                raise error.PySmiSemanticError('unknown datatype for OID: %s' % el)\n\n        return out\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genObjects(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genTime(self, data, classmode=False):\n        return ''\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genLastUpdated(self, data, classmode=False):\n        return data[0]\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genOrganization(self, data, classmode=False):\n        return data[0]\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genRevisions(self, data, classmode=False):\n        lastRevision, lastDescription = data[0][0][0], data[0][0][1][1]\n        return lastRevision, lastDescription\n\n    def genRow(self, data, classmode=False):\n        row = data[0]\n        row = self.transOpers(row)\n        return row in self._rows and (('MibTableRow', ''), '') or self.genSimpleSyntax(data, classmode=classmode)\n\n    # noinspection PyUnusedLocal\n    def genSequence(self, data, classmode=False):\n        cols = data[0]\n        self._cols.update(cols)\n        return '', ''\n\n    # noinspection PyUnusedLocal\n    def genSimpleSyntax(self, data, classmode=False):\n        objType = data[0]\n\n        module = ''\n\n        objType = self.typeClasses.get(objType, objType)\n        objType = self.transOpers(objType)\n\n        if objType not in self.baseTypes:\n            module = self._importMap.get(objType, self.moduleName[0])\n\n        subtype = len(data) == 2 and data[1] or ''\n\n        return (objType, module), subtype\n\n    # noinspection PyUnusedLocal,PyMethodMayBeStatic\n    def genTypeDeclarationRHS(self, data, classmode=False):\n        if len(data) == 1:\n            parentType, attrs = data[0]  # just syntax\n\n        else:\n            # Textual convention\n            display, status, description, reference, syntax = data\n            parentType, attrs = syntax\n\n        return parentType, attrs\n\n    # noinspection PyUnusedLocal,PyUnusedLocal,PyMethodMayBeStatic\n    def genUnits(self, data, classmode=False):\n        return ''\n\n    handlersTable = {\n        'agentCapabilitiesClause': genAgentCapabilities,\n        'moduleIdentityClause': genModuleIdentity,\n        'moduleComplianceClause': genModuleCompliance,\n        'notificationGroupClause': genNotificationGroup,\n        'notificationTypeClause': genNotificationType,\n        'objectGroupClause': genObjectGroup,\n        'objectIdentityClause': genObjectIdentity,\n        'objectTypeClause': genObjectType,\n        'trapTypeClause': genTrapType,\n        'typeDeclaration': genTypeDeclaration,\n        'valueDeclaration': genValueDeclaration,\n\n        'ApplicationSyntax': genSimpleSyntax,\n        'BitNames': genBitNames,\n        'BITS': genBits,\n        'ComplianceModules': genCompliances,\n        'conceptualTable': genConceptualTable,\n        'CONTACT-INFO': genContactInfo,\n        'DISPLAY-HINT': genDisplayHint,\n        'DEFVAL': genDefVal,\n        'DESCRIPTION': genDescription,\n        'REFERENCE': genReference,\n        'Status': genStatus,\n        'PRODUCT-RELEASE': genProductRelease,\n        'enumSpec': genEnumSpec,\n        'INDEX': genIndex,\n        'integerSubType': genIntegerSubType,\n        'MaxAccessPart': genMaxAccess,\n        'Notifications': genObjects,\n        'octetStringSubType': genOctetStringSubType,\n        'objectIdentifier': genOid,\n        'Objects': genObjects,\n        'LAST-UPDATED': genLastUpdated,\n        'ORGANIZATION': genOrganization,\n        'Revisions': genRevisions,\n        'row': genRow,\n        'SEQUENCE': genSequence,\n        'SimpleSyntax': genSimpleSyntax,\n        'typeDeclarationRHS': genTypeDeclarationRHS,\n        'UNITS': genUnits,\n        'VarTypes': genObjects,\n    }\n\n    def genCode(self, ast, symbolTable, **kwargs):\n        self.genRules['text'] = kwargs.get('genTexts', False)\n        self._rows.clear()\n        self._cols.clear()\n        self._parentOids.clear()\n        self._symsOrder = []\n        self._postponedSyms.clear()\n        self._importMap.clear()\n        self._out = {}  # should be new object, do not use `clear` method\n        self.moduleName[0], moduleOid, imports, declarations = ast\n\n        out, importedModules = self.genImports(imports or {})\n\n        for declr in declarations or []:\n            if declr:\n                clausetype = declr[0]\n                classmode = clausetype == 'typeDeclaration'\n                self.handlersTable[declr[0]](self, self.prepData(declr[1:], classmode), classmode)\n\n        if self._postponedSyms:\n            raise error.PySmiSemanticError('Unknown parents for symbols: %s' % ', '.join(self._postponedSyms))\n\n        for sym in self._parentOids:\n            if sym not in self._out and sym not in self._importMap:\n                raise error.PySmiSemanticError('Unknown parent symbol: %s' % sym)\n\n        self._out['_symtable_order'] = list(self._symsOrder)\n        self._out['_symtable_cols'] = list(self._cols)\n        self._out['_symtable_rows'] = list(self._rows)\n\n        debug.logger & debug.flagCodegen and debug.logger(\n            'canonical MIB name %s (%s), imported MIB(s) %s, Symbol table size %s symbols' % (\n                self.moduleName[0], moduleOid, ','.join(importedModules) or '<none>', len(self._out)))\n\n        return MibInfo(oid=None,\n                       name=self.moduleName[0],\n                       revision=self._moduleRevision,\n                       imported=tuple([x for x in importedModules])), self._out\n"
  },
  {
    "path": "pysmi/codegen/templates/jsondoc/base.j2",
    "content": "{% block jsondump %}\n{{ mib|tojson(indent=2) }}\n{% endblock %}"
  },
  {
    "path": "pysmi/codegen/templates/pysnmp/base.j2",
    "content": "{% block init scoped %}\n{% endblock %}\n{% block docstring scoped %}\n\"\"\"SNMP MIB module ({{ mib['meta']['module'] }}) expressed in pysnmp data model.\n\nThis Python module is designed to be imported and executed by the\npysnmp library.\n\nSee http://snmplabs.com/pysnmp for further information.\n\nNotes\n-----\n{% for comment in mib['meta']['comments'] -%}\n{{ comment }}\n{% endfor -%}\n\"\"\"\n{% endblock %}\n{% block api_version_check scoped %}\nif 'mibBuilder' not in globals():\n    import sys\n\n    sys.stderr.write(__doc__)\n    sys.exit(1)\n{% endblock %}\n"
  },
  {
    "path": "pysmi/codegen/templates/pysnmp/managed-objects-instances.j2",
    "content": "{#\nThis template renders (commented out) Managed Objects Instances\nfor scalar and columnar Managed Objects.\n\nThe user is expected to provide:\n\n * values for all Managed Objects\n * proper indices and values for zero or more tables rows\n\n#}\n{% include \"pysnmp/base.j2\" %}\n\n{% block smi_imports scoped %}\n\nMibScalarInstance, = mibBuilder.importSymbols(\n    'SNMPv2-SMI',\n    'MibScalarInstance'\n)\n\n# Import Managed Objects to base Managed Objects Instances on\n\n{% for symbol, definition in mib.items()|sort\n   if definition['class'] == 'objecttype' and\n      definition['nodetype'] in ('scalar', 'column') %}\n    {% if loop.first and loop.last %}\n({{ symbol|replace('-', '_') }},) = mibBuilder.importSymbols(\n    \"{{ mib['meta']['module'] }}\",\n    {% elif loop.first %}\n({{ symbol|replace('-', '_') }},\n    {% elif loop.last %}\n {{ symbol|replace('-', '_') }}) = mibBuilder.importSymbols(\n    \"{{ mib['meta']['module'] }}\",\n    {%  else %}\n {{ symbol|replace('-', '_') }},\n    {%  endif %}\n{% endfor %}\n{% for symbol, definition in mib.items()|sort\n       if definition['class'] == 'objecttype' and\n           definition['nodetype'] in ('scalar', 'column') %}\n    {% if loop.last %}\n    \"{{ symbol }}\")\n    {% else %}\n    \"{{ symbol }}\",\n    {% endif %}\n{% endfor %}\n\n{% endblock %}\n{% block managed_objects_instances scoped %}\n\n# MIB Managed Objects in the order of their OIDs\n{% for symbol, definition in mib.items() %}\n    {% if definition['nodetype'] == 'scalar' %}\n        {% block mib_scalar_object_instance_definition scoped %}\n{{ symbol|replace('-', '_')|capfirst }}_ObjectInstance = MibScalarInstance\n        {% endblock %}\n        {% block mib_scalar_object_instantiation scoped %}\n# TODO: uncomment Managed Object Instance instantiation optionally\n#       setting a default value (via `.syntax.clone()`)\n# _{{ symbol|replace('-', '_') }} = {{ symbol|replace('-', '_')|capfirst }}_ObjectInstance(\n#      {{ symbol|replace('-', '_') }}.name,\n#      (0,),\n#      {{ symbol|replace('-', '_') }}.syntax\n# )\n        {% endblock %}\n    {% elif definition['nodetype'] == 'column' %}\n        {% block mib_table_column_object_instance_definition scoped %}\n{{ symbol|replace('-', '_')|capfirst }}_ObjectInstance = MibScalarInstance\n        {% endblock %}\n        {% block mib_column_instantiation scoped %}\n# TODO: Set proper OID for Managed Object Instance (see INDEX clause in MIB)\n# TODO: Initialize Managed Object Instance value (via `.syntax.clone()`)\n# _{{ symbol|replace('-', '_') }} = {{ symbol|replace('-', '_')|capfirst }}_ObjectInstance(\n#     {{ symbol|replace('-', '_') }}.name,\n#     (<add columnar indices here>,),\n#     {{ symbol|replace('-', '_') }}.syntax\n# )\n        {% endblock %}\n    {% endif %}\n{% endfor %}\n{% endblock %}\n\n{% block exports scoped %}\n\n# Export Managed Objects Instances to the MIB builder\n\n# TODO: complete Managed Objects Instances initialization above\n# and uncomment the exports below\n\nmibBuilder.exportSymbols(\n    \"__{{ mib['meta']['module'] }}\",\n    {% for symbol, definition in mib.items()\n       if definition['class'] == 'objecttype' and\n           definition['nodetype'] in ('scalar', 'column') %}\n        {% if loop.first and loop.last %}\n    # **{\"{{ symbol }}\": _{{ symbol|replace('-', '_') }}}\n        {% elif loop.first %}\n    # **{\"{{ symbol }}\": _{{ symbol|replace('-', '_') }},\n        {% elif loop.last %}\n    # \"{{ symbol }}\": _{{ symbol|replace('-', '_') }}}\n        {% else %}\n    # \"{{ symbol }}\": _{{ symbol|replace('-', '_') }},\n        {% endif %}\n    {%  endfor %}\n)\n{% endblock %}\n"
  },
  {
    "path": "pysmi/codegen/templates/pysnmp/mib-definitions.j2",
    "content": "{#\nThis template renders most of the MIB objects definitions but\nManaged Objects Instances.\n#}\n{% include \"pysnmp/base.j2\" %}\n{% block asn1_imports scoped %}\n\n# Import base ASN.1 objects even if this MIB does not use it\n\n(Integer,\n OctetString,\n ObjectIdentifier) = mibBuilder.importSymbols(\n    \"ASN1\",\n    \"Integer\",\n    \"OctetString\",\n    \"ObjectIdentifier\")\n\n(NamedValues,) = mibBuilder.importSymbols(\n    \"ASN1-ENUMERATION\",\n    \"NamedValues\")\n{% endblock -%}\n\n{% block asn1_constraints_imports scoped %}\n(ConstraintsIntersection,\n SingleValueConstraint,\n ValueRangeConstraint,\n ValueSizeConstraint,\n ConstraintsUnion) = mibBuilder.importSymbols(\n    \"ASN1-REFINEMENT\",\n    \"ConstraintsIntersection\",\n    \"SingleValueConstraint\",\n    \"ValueRangeConstraint\",\n    \"ValueSizeConstraint\",\n    \"ConstraintsUnion\")\n{% endblock -%}\n\n{% block smi_imports scoped %}\n\n# Import SMI symbols from the MIBs this MIB depends on\n\n{% for module, symbols in mib['imports'].items() %}\n    {% for symbol in symbols %}\n        {% if loop.first and loop.last %}\n({{ symbol|replace('-', '_') }},) = mibBuilder.importSymbols(\n    \"{{ module }}\",\n        {% elif loop.first %}\n({{ symbol|replace('-', '_') }},\n        {% elif loop.last %}\n {{ symbol|replace('-', '_') }}) = mibBuilder.importSymbols(\n    \"{{ module }}\",\n        {%  else %}\n {{ symbol|replace('-', '_') }},\n        {%  endif %}\n    {%  endfor %}\n    {% for symbol in symbols %}\n        {% if loop.last %}\n    \"{{ symbol }}\")\n        {% else %}\n    \"{{ symbol }}\",\n        {% endif %}\n    {%  endfor %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block module_identity scoped %}\n\n# MODULE-IDENTITY\n\n{% for symbol, definition in mib.items() if definition['class'] == 'moduleidentity' %}\n{{ symbol }} = ModuleIdentity(\n    {{ definition['oid'] }}\n)\n    {% if 'revisions' in definition %}\n{{ symbol }}.setRevisions(\n        {% for revision in definition.get('revisions', ()) %}\n            {% if loop.first and loop.last %}\n        (\"{{ revision['revision'] }}\",)\n            {% elif loop.first %}\n        (\"{{ revision['revision'] }}\",\n            {% elif loop.last %}\n         \"{{ revision['revision'] }}\")\n            {%  else %}\n         \"{{ revision['revision'] }}\",\n            {%  endif %}\n        {%  endfor %}\n)\n    {% endif %}\n    {% if 'lastupdated' in definition %}\n{{ symbol }}.setLastUpdated(\"{{ definition['lastupdated'] }}\")\n    {% endif %}\n    {% if 'organization' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol }}.setOrganization(\"\"\"\\\n{{ definition['organization']|wordwrap }}\n\"\"\")\n    {% endif %}\n    {% if 'contactinfo' in definition %}\n{{ symbol }}.setContactInfo(\"\"\"\\\n{{ definition['contactinfo']|wordwrap }}\n\"\"\")\n    {% endif %}\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% macro constraints(type, spec) %}\n    subtypeSpec = {{ type }}.subtypeSpec\n    {% if 'enumeration' in spec %}\n    subtypeSpec += ConstraintsUnion(\n        SingleValueConstraint(\n        {% for iden in spec['enumeration'].values()|sort %}\n            {% if loop.first and loop.last %}\n            {{ iden }}\n            {% elif loop.first %}\n            *({{ iden }},\n            {% elif loop.last %}\n              {{ iden }})\n            {% else %}\n              {{ iden }},\n            {% endif %}\n        {% endfor %}\n        )\n    )\n    namedValues = NamedValues(\n    {% for name, iden in spec['enumeration'].items()|sort %}\n        {% if loop.first and loop.last %}\n        (\"{{ name}}\", {{ iden }})\n        {% elif loop.first %}\n        *((\"{{ name}}\", {{ iden }}),\n        {% elif loop.last %}\n          (\"{{ name}}\", {{ iden }}))\n        {% else %}\n          (\"{{ name}}\", {{ iden }}),\n        {% endif %}\n    {% endfor %}\n    )\n    {% elif 'range' in spec %}\n    subtypeSpec += ConstraintsUnion(\n        {% for range in spec['range'] %}\n        ValueRangeConstraint({{ range['min'] }}, {{ range['max'] }}),\n        {% endfor %}\n    )\n    {% elif 'size' in spec %}\n    subtypeSpec += ConstraintsUnion(\n        {% for range in spec['size'] %}\n        ValueSizeConstraint({{ range['min'] }}, {{ range['max'] }}),\n        {% endfor %}\n    )\n    {% endif %}\n{% endmacro -%}\n\n{% macro default(definition) %}\n    {% if definition['default']['default']['format'] == 'decimal' %}\n    defaultValue = {{ definition['default']['default']['value'] }}\n    {% elif definition['default']['default']['format'] == 'hex' %}\n        {# TODO: pyasn1 Integer does not have defaultHexValue #}\n        {% if definition['default']['default']['basetype'] in ('Integer', 'Integer32') %}\n    defaultHexValue = {{ definition['default']['default']['value'] }}\n        {% else %}\n    defaultHexValue = \"{{ definition['default']['default']['value'] }}\"\n        {% endif %}\n    {# TODO: pyasn1 Integer does not have defaultBinValue #}\n    {% elif definition['default']['default']['format'] == 'bin' %}\n        {% if definition['default']['default']['basetype'] in ('Integer', 'Integer32') %}\n    defaultBinValue = {{ definition['default']['default']['value'] }}\n        {% else %}\n    defaultBinValue = \"{{ definition['default']['default']['value'] }}\"\n        {% endif %}\n    {% elif definition['default']['default']['format'] == 'string' %}\n    {# TODO: pyasn1 does not like defaulted strings #}\n    defaultValue = OctetString(\"{{ definition['default']['default']['value'] }}\")\n    {% elif definition['default']['default']['format'] == 'oid' %}\n    {# TODO: this OID might be in a string form #}\n    defaultValue = \"{{ definition['default']['default']['value'] }}\"\n    {% elif definition['default']['default']['format'] == 'enum'\n        and 'constraints' in definition['syntax'] %}\n    {# TODO: pyasn1 does not like default enum #}\n    defaultValue = {{ definition['syntax']['constraints']['enumeration'][definition['default']['default']['value']] }}\n    {% elif definition['default']['default']['format'] == 'bits' %}\n    {# TODO: pyasn1 does not like default named bits #}\n    defaultValue = {{ definition['syntax']['constraints']['enumeration'][definition['default']['default']['value']] }}\n    {%  endif %}\n{% endmacro -%}\n\n{% block types_definitions scoped %}\n\n# Types definitions\n\n{% for symbol, definition in mib.items() if definition['class'] == 'type' %}\n\n\nclass {{ symbol }}({{ definition['type']['type'] }}):\n    \"\"\"Custom type {{ symbol }} based on {{ definition['type']['type'] }}\"\"\"\n    {% if 'default' in definition %}\n{{ default(definition) }}\n    {% endif %}\n    {% if 'constraints' in definition['type'] %}\n{{ constraints(definition['type']['type'], definition['type']['constraints']) }}\n    {% endif %}\n\n\n{%  endfor %}\n{% endblock -%}\n\n{% block textual_conventions scoped %}\n\n# TEXTUAL-CONVENTIONS\n\n{% for symbol, definition in mib.items() if definition['class'] == 'textualconvention' %}\n\n\nclass {{ symbol }}(TextualConvention, {{ definition['type']['type'] }}):\n    status = \"{{ definition.get('status', 'current') }}\"\n    {% if 'displayhint' in definition %}\n    displayHint = \"{{ definition['displayhint'] }}\"\n    {% endif %}\n    {% if 'constraints' in definition['type'] %}\n{{ constraints(definition['type']['type'], definition['type']['constraints']) }}\n    {% endif %}\n    {% if 'description' in definition %}\n    if mibBuilder.loadTexts:\n        description = \"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\"\n    {% endif %}\n{% endfor %}\n\n{% endblock -%}\n\n{% block managed_objects scoped %}\n\n# MIB Managed Objects in the order of their OIDs\n\n{% for symbol, definition in mib.items()\n   if definition['class'] in ('objecttype', 'objectidentity') %}\n    {% if 'syntax' in definition %}\n        {% block mib_object_syntax_definition scoped %}\n            {% if 'default' in definition or 'constraints' in definition['syntax'] or 'bits' in definition['syntax'] %}\n\n\nclass _{{ symbol|replace('-', '_')|capfirst }}_Type({{ definition['syntax']['type'] }}):\n    \"\"\"Custom type {{ symbol }} based on {{ definition['syntax']['type'] }}\"\"\"\n                {% if 'default' in definition %}\n{{ default(definition) }}\n                {% endif %}\n                {% if 'constraints' in definition['syntax'] %}\n{{ constraints(definition['syntax']['type'], definition['syntax']['constraints']) }}\n                {% endif %}\n                {% if 'bits' in definition['syntax'] %}\n    namedValues = NamedValues(\n                    {% for name, iden in definition['syntax']['bits'].items()|sort %}\n                        {% if loop.first and loop.last %}\n        (\"{{ name}}\", {{ iden }})\n                        {% elif loop.first %}\n        *((\"{{ name}}\", {{ iden }}),\n                        {% elif loop.last %}\n          (\"{{ name}}\", {{ iden }}))\n                        {% else %}\n          (\"{{ name}}\", {{ iden }}),\n                        {% endif %}\n                    {% endfor %}\n    )\n                {% endif %}\n\n                {% if 'constraints' in definition['syntax'] or 'bits' in definition['syntax'] %}\n_{{ symbol|replace('-', '_')|capfirst }}_Type.__name__ = \"{{ definition['syntax']['type'] }}\"\n                {% endif %}\n            {% else %}\n_{{ symbol|replace('-', '_')|capfirst }}_Type = {{ definition['syntax']['type'] }}\n            {% endif %}\n        {% endblock %}\n    {% endif %}\n    {% if definition['class'] == 'objectidentity' %}\n        {% block mib_scalar_object_identity_definition scoped %}\n_{{ symbol|replace('-', '_')|capfirst }}_ObjectIdentity = ObjectIdentity\n        {% endblock %}\n        {% block mib_object_identity_instantiation scoped %}\n{{ symbol|replace('-', '_') }} = _{{ symbol|replace('-', '_')|capfirst }}_ObjectIdentity(\n    {{ definition['oid'] }}\n)\n        {% endblock %}\n    {% elif definition['nodetype'] == 'scalar' %}\n        {% block mib_scalar_object_definition scoped %}\n_{{ symbol|replace('-', '_')|capfirst }}_Object = MibScalar\n        {% endblock %}\n        {% block mib_scalar_object_instantiation scoped %}\n{{ symbol|replace('-', '_') }} = _{{ symbol|replace('-', '_')|capfirst }}_Object(\n    {{ definition['oid'] }},\n    _{{ symbol|replace('-', '_')|capfirst }}_Type()\n)\n        {% endblock %}\n{{ symbol|replace('-', '_') }}.setMaxAccess(\"{{ definition['maxaccess'] }}\")\n    {% elif definition['nodetype'] == 'table' %}\n        {% block mib_table_object_definition scoped %}\n_{{ symbol|replace('-', '_')|capfirst }}_Object = MibTable\n        {% endblock %}\n        {% block mib_table_object_instantiation scoped %}\n{{ symbol|replace('-', '_') }} = _{{ symbol|replace('-', '_')|capfirst }}_Object(\n    {{ definition['oid'] }}\n)\n        {% endblock %}\n    {% elif definition['nodetype'] == 'row' %}\n        {% block mib_table_row_object_definition scoped %}\n_{{ symbol|replace('-', '_')|capfirst }}_Object = MibTableRow\n        {% endblock %}\n        {% block mib_table_row_object_instantiation scoped %}\n{{ symbol|replace('-', '_') }} = _{{ symbol|replace('-', '_')|capfirst }}_Object(\n    {{ definition['oid'] }}\n)\n        {% endblock %}\n        {% if 'indices' in definition %}\n{{ symbol|replace('-', '_') }}.setIndexNames(\n            {% for index in definition['indices'] %}\n    ({{ index['implied'] }}, \"{{ index['module'] }}\", \"{{ index['object'] }}\"),\n            {% endfor %}\n)\n        {% endif %}\n        {% if 'augmention' in definition %}\n{{ definition['augmention']['object'] }}.registerAugmentions(\n    (\"{{ mib['meta']['module'] }}\",\n     \"{{ symbol|replace('-', '_') }}\")\n)\n{{ symbol|replace('-', '_') }}.setIndexNames(*{{ definition['augmention']['object'] }}.getIndexNames())\n        {% endif %}\n    {% elif definition['nodetype'] == 'column' %}\n        {% block mib_table_column_object_definition scoped %}\n_{{ symbol|replace('-', '_')|capfirst }}_Object = MibTableColumn\n        {% endblock %}\n        {% block mib_table_column_object_instantiation scoped %}\n{{ symbol|replace('-', '_') }} = _{{ symbol|replace('-', '_')|capfirst }}_Object(\n    {{ definition['oid'] }},\n    _{{ symbol|replace('-', '_')|capfirst }}_Type()\n)\n        {% endblock %}\n{{ symbol|replace('-', '_') }}.setMaxAccess(\"{{ definition['maxaccess'] }}\")\n    {% endif %}\n    {% if 'status' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\"{{ definition['status'] }}\")\n    {% endif %}\n    {% if 'units' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setUnits(\"{{ definition['units'] }}\")\n    {% endif %}\n    {% if 'reference' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setReference(\"\"\"\\\n{{ definition['reference']|wordwrap }}\n\"\"\")\n    {% endif %}\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n{% endfor %}\n{% endblock -%}\n\n{% block managed_objects_groups scoped %}\n\n# Managed Objects groups\n\n{% for symbol, definition in mib.items()\n   if definition['class'] == 'objectgroup' %}\n{{ symbol|replace('-', '_') }} = ObjectGroup(\n    {{ definition['oid'] }}\n)\n    {% if 'objects' in definition %}\n{{ symbol|replace('-', '_') }}.setObjects(\n    {% for obj in definition['objects'] %}\n        {% if loop.first and loop.last %}\n    (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\")\n        {% elif loop.first %}\n      *((\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% elif loop.last %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"))\n        {% else %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% endif %}\n    {% endfor %}\n)\n    {% endif %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\"{{ definition['status'] }}\")\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block notification_objects scoped %}\n\n# Notification objects\n\n{% for symbol, definition in mib.items()\n   if definition['class'] == 'notificationtype' %}\n{{ symbol|replace('-', '_') }} = NotificationType(\n    {{ definition['oid'] }}\n)\n    {% if 'objects' in definition %}\n{{ symbol|replace('-', '_') }}.setObjects(\n    {% for obj in definition['objects'] %}\n        {% if loop.first and loop.last %}\n    (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\")\n        {% elif loop.first %}\n      *((\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% elif loop.last %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"))\n        {% else %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% endif %}\n    {% endfor %}\n)\n    {% endif %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\n        \"{{ definition['status'] }}\"\n    )\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block notification_groups scoped %}\n\n# Notifications groups\n\n{% for symbol, definition in mib.items()\n   if definition['class'] == 'notificationgroup' %}\n{{ symbol|replace('-', '_') }} = NotificationGroup(\n    {{ definition['oid'] }}\n)\n    {% if 'objects' in definition %}\n{{ symbol|replace('-', '_') }}.setObjects(\n    {% for obj in definition['objects'] %}\n        {% if loop.first and loop.last %}\n    (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\")\n        {% elif loop.first %}\n      *((\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% elif loop.last %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"))\n        {% else %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% endif %}\n    {% endfor %}\n)\n    {% endif %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\n        \"{{ definition['status'] }}\"\n    )\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block agent_capabilities scoped %}\n\n# Agent capabilities\n\n{% for symbol, definition in mib.items()\n   if definition['class'] == 'agentcapabilities' %}\n{{ symbol|replace('-', '_') }} = AgentCapabilities(\n    {{ definition['oid'] }}\n)\n    {% if 'productrelease' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setProductRelease(\n        \"{{ definition['productrelease'] }}\"\n    )\n    {% endif %}\n    {% if 'reference' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setReference(\n        \"{{ definition['reference'] }}\"\n    )\n    {% endif %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\n        \"{{ definition['status'] }}\"\n    )\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block module_compliance scoped %}\n\n# Module compliance\n\n{% for symbol, definition in mib.items()\n   if definition['class'] == 'modulecompliance' %}\n{{ symbol|replace('-', '_') }} = ModuleCompliance(\n    {{ definition['oid'] }}\n)\n    {% if 'objects' in definition %}\n{{ symbol|replace('-', '_') }}.setObjects(\n    {% for obj in definition['objects'] %}\n        {% if loop.first and loop.last %}\n    (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\")\n        {% elif loop.first %}\n      *((\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% elif loop.last %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"))\n        {% else %}\n        (\"{{ obj['module'] }}\", \"{{  obj['object'] }}\"),\n        {% endif %}\n    {% endfor %}\n)\n    {% endif %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setStatus(\n        \"{{ definition['status'] }}\"\n    )\n    {% if 'description' in definition %}\nif mibBuilder.loadTexts:\n    {{ symbol|replace('-', '_') }}.setDescription(\"\"\"\\\n{{ definition['description']|wordwrap }}\n\"\"\")\n    {% endif %}\n\n{% endfor %}\n{% endblock -%}\n\n{% block exports scoped %}\n\n# Export all MIB objects to the MIB builder\n\nmibBuilder.exportSymbols(\n    \"{{ mib['meta']['module'] }}\",\n    {% for symbol, definition in mib.items()\n       if definition['class'] in ('moduleidentity', 'objecttype',\n                                  'agentcapabilities', 'moduleidentity',\n                                  'modulecompliance', 'notificationgroup',\n                                  'notificationtype', 'objectgroup',\n                                  'objectidentity', 'textualconvention') %}\n        {% if loop.first and loop.last %}\n    **{\"{{ symbol }}\": {{ symbol|replace('-', '_') }}}\n        {% elif loop.first %}\n    **{\"{{ symbol }}\": {{ symbol|replace('-', '_') }},\n        {% elif loop.last %}\n       \"{{ symbol }}\": {{ symbol|replace('-', '_') }}}\n        {% else %}\n       \"{{ symbol }}\": {{ symbol|replace('-', '_') }},\n        {% endif %}\n    {%  endfor %}\n)\n{% endblock %}\n"
  },
  {
    "path": "pysmi/codegen/templates/pysnmp/mib-instrumentation/managed-objects-instances.j2",
    "content": "{#\nThis template renders MIB instrumentation hooks to the SMI classes\nrepresenting Managed Objects Instances for scalar and columnar\nManaged Objects.\n\nBy default all read/readnext/write/create/destroy hooks are generated.\nUser can extend this template muting some of the hooks to reduce code\nsize.\n\nIf the hook is not overridden, it will manage the volatile variable\nas defined by the MIB OBJECT-TYPE clause.\n\nThese hooks are asynchronous by design. Be sure to understand pysnmp\nSMI data model (`http://snmplabs.com/pysnmp`) if you are going to add\nyour code into these hooks.\n#}\n{% extends \"pysnmp/managed-objects-instances.j2\" %}\n\n{% block mib_scalar_object_instance_definition %}\n\n\nclass {{ symbol|replace('-', '_')|capfirst }}_ObjectInstance(MibScalarInstance):\n    \"\"\"Scalar Managed Object Instance with MIB instrumentation hooks.\n\n    User can override none, some or all of the method below interfacing\n    them to the data source they want to manage through SNMP.\n    Non-overridden methods could just be removed from this class.\n\n    See the SMI data model documentation at `http://snmplabs.com/pysnmp`.\n    \"\"\"\n    {% block mib_scalar_object_instance_read scoped %}\n    def readTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readTest(self, varBind, **context)\n\n    def readGet(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readGet(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_instance_readnext scoped %}\n    def readTestNext(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readTestNext(self, varBind, **context)\n\n    def readGetNext(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readGetNext(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_instance_write scoped %}\n    def writeTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeTest(self, varBind, **context)\n\n    def writeCommit(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeCommit(self, varBind, **context)\n\n    def writeCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeCleanup(self, varBind, **context)\n\n    def writeUndo(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_instance_create scoped %}\n    def createTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createTest(self, varBind, **context)\n\n    def createCommit(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createCommit(self, varBind, **context)\n\n    def createCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createCleanup(self, varBind, **context)\n\n    def createUndo(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createUndo(self, varBind, **context)\n    {% endblock %}\n\n\n{% endblock -%}\n\n{% block mib_table_column_object_instance_definition %}\n\n\nclass {{ symbol|replace('-', '_')|capfirst }}_ObjectInstance(MibScalarInstance):\n    \"\"\"Columnar Managed Object Instance with MIB instrumentation hooks.\n\n    User can override none, some or all of the method below interfacing\n    them to the data source they want to manage through SNMP.\n    Non-overridden methods could just be removed from this class.\n\n    See the SMI data model documentation at `http://snmplabs.com/pysnmp`.\n    \"\"\"\n    {% block mib_table_column_object_instance_read scoped %}\n    def readTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readTest(self, varBind, **context)\n\n    def readGet(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readGet(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_instance_readnext scoped %}\n    def readTestNext(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readTestNext(self, varBind, **context)\n\n    def readGetNext(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.readGetNext(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_instance_write scoped %}\n    def writeTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeTest(self, varBind, **context)\n\n    def writeCommit(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeCommit(self, varBind, **context)\n\n    def writeCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeCleanup(self, varBind, **context)\n\n    def writeUndo(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.writeUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_instance_create scoped %}\n    def createTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createTest(self, varBind, **context)\n\n    def createCommit(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createCommit(self, varBind, **context)\n\n    def createCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createCleanup(self, varBind, **context)\n\n    def createUndo(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.createUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_instance_destroy scoped %}\n    def destroyTest(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.destroyTest(self, varBind, **context)\n\n    def destroyCommit(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.destroyCommit(self, varBind, **context)\n\n    def destroyCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.destroyCleanup(self, varBind, **context)\n\n    def destroyUndo(self, varBind, **context):\n        # Put your code here\n        MibScalarInstance.destroyUndo(self, varBind, **context)\n    {% endblock %}\n\n\n{% endblock %}\n\n"
  },
  {
    "path": "pysmi/codegen/templates/pysnmp/mib-instrumentation/managed-objects.j2",
    "content": "{#\nThis template renders MIB instrumentation hooks to the SMI classes\nrepresenting \"leaf\" Managed Objects (but not Managed Objects\nInstances). By leaf Managed Objects we mean MIB scalars and MIB\ncolumns.\n\nBy default all read/readnext/write/create/destroy hooks are generated.\nUser can extend this template muting some of the hooks to reduce code\nsize.\n\nIf the hook is not overridden, it will manage the volatile variable\nas defined by the MIB OBJECT-TYPE clause.\n\nThese hooks are asynchronous by design. Be sure to understand pysnmp\nSMI data model (`http://snmplabs.com/pysnmp`) if you are going to add\nyour code into these hooks.\n#}\n{% extends \"pysnmp/mib-definitions.j2\" %}\n\n{% block mib_scalar_object_definition %}\n\n\nclass _{{ symbol|replace('-', '_')|capfirst }}_Object(MibScalar):\n    \"\"\"Scalar MIB object with MIB instrumentation hooks.\n\n    User can override none, some or all of the method below interfacing\n    them to the data source they want to manage through SNMP.\n\n    See the SMI data model documentation at `http://snmplabs.com/pysnmp`.\n    \"\"\"\n    {% block mib_scalar_object_read %}\n    def readTest(self, varBind, **context):\n        # Put your code here\n        MibScalar.readTest(self, varBind, **context)\n\n    def readGet(self, varBind, **context):\n        # Put your code here\n        MibScalar.readGet(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_readnext %}\n    def readTestNext(self, varBind, **context):\n        # Put your code here\n        MibScalar.readTestNext(self, varBind, **context)\n\n    def readGetNext(self, varBind, **context):\n        # Put your code here\n        MibScalar.readGetNext(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_write %}\n    def writeTest(self, varBind, **context):\n        # Put your code here\n        MibScalar.writeTest(self, varBind, **context)\n\n    def writeCommit(self, varBind, **context):\n        # Put your code here\n        MibScalar.writeCommit(self, varBind, **context)\n\n    def writeCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalar.writeCleanup(self, varBind, **context)\n\n    def writeUndo(self, varBind, **context):\n        # Put your code here\n        MibScalar.writeUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_scalar_object_create %}\n    def createTest(self, varBind, **context):\n        # Put your code here\n        MibScalar.createTest(self, varBind, **context)\n\n    def createCommit(self, varBind, **context):\n        # Put your code here\n        MibScalar.createCommit(self, varBind, **context)\n\n    def createCleanup(self, varBind, **context):\n        # Put your code here\n        MibScalar.createCleanup(self, varBind, **context)\n\n    def createUndo(self, varBind, **context):\n        # Put your code here\n        MibScalar.createUndo(self, varBind, **context)\n    {% endblock %}\n\n\n{% endblock -%}\n\n{% block mib_table_column_object_definition %}\n\n\nclass _{{ symbol|replace('-', '_')|capfirst }}_Object(MibScalar):\n    \"\"\"Columnar MIB object with MIB instrumentation hooks.\n\n    User can override none, some or all of the method below interfacing\n    them to the data source they want to manage through SNMP.\n\n    See the SMI data model documentation at `http://snmplabs.com/pysnmp`.\n    \"\"\"\n    {% block mib_table_column_object_read %}\n    def readTest(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.readTest(self, varBind, **context)\n\n    def readGet(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.readGet(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_readnext %}\n    def readTestNext(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.readTestNext(self, varBind, **context)\n\n    def readGetNext(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.readGetNext(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_write %}\n    def writeTest(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.writeTest(self, varBind, **context)\n\n    def writeCommit(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.writeCommit(self, varBind, **context)\n\n    def writeCleanup(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.writeCleanup(self, varBind, **context)\n\n    def writeUndo(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.writeUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_create %}\n    def createTest(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.createTest(self, varBind, **context)\n\n    def createCommit(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.createCommit(self, varBind, **context)\n\n    def createCleanup(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.createCleanup(self, varBind, **context)\n\n    def createUndo(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.createUndo(self, varBind, **context)\n    {% endblock %}\n\n    {% block mib_table_column_object_destroy %}\n    def destroyTest(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.destroyTest(self, varBind, **context)\n\n    def destroyCommit(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.destroyCommit(self, varBind, **context)\n\n    def destroyCleanup(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.destroyCleanup(self, varBind, **context)\n\n    def destroyUndo(self, varBind, **context):\n        # Put your code here\n        MibTableColumn.destroyUndo(self, varBind, **context)\n    {% endblock %}\n\n\n{% endblock %}\n"
  },
  {
    "path": "pysmi/compat.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\n\nif sys.version_info[0] > 2:\n    def encode(s):\n        if isinstance(s, str):\n            s = s.encode('utf-8', 'ignore')\n        return s\n\n\n    def decode(s):\n        if isinstance(s, bytes):\n            s = s.decode('utf-8', 'ignore')\n        return s\nelse:\n    def encode(s):\n        if isinstance(s, unicode):\n            s = s.encode('utf-8', 'ignore')\n        return s\n\n\n    def decode(s):\n        if isinstance(s, str):\n            s = s.decode('utf-8', 'ignore')\n        return s\n"
  },
  {
    "path": "pysmi/compiler.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport os\nimport time\n\ntry:\n    from pwd import getpwuid\nexcept ImportError:\n    # noinspection PyPep8\n    getpwuid = lambda x: ['<unknown>']\nfrom pysmi import __name__ as packageName\nfrom pysmi import __version__ as packageVersion\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysmi import error\nfrom pysmi import debug\n\n\nclass MibStatus(str):\n    \"\"\"Indicate MIB transformation result.\n\n    *MibStatus* is a subclass of Python string type. Some additional\n    attributes may be set to indicate the details.\n\n    The following *MibStatus* class instances are defined:\n\n    * *compiled* - MIB is successfully transformed\n    * *untouched* - fresh transformed version of this MIB already exisits\n    * *failed* - MIB transformation failed. *error* attribute carries details.\n    * *unprocessed* - MIB transformation required but waived for some reason\n    * *missing* - ASN.1 MIB source can't be found\n    * *borrowed* - MIB transformation failed but pre-transformed version was used\n    \"\"\"\n\n    def setOptions(self, **kwargs):\n        n = self.__class__(self)\n        for k in kwargs:\n            setattr(n, k, kwargs[k])\n        return n\n\n\nstatusCompiled = MibStatus('compiled')\nstatusUntouched = MibStatus('untouched')\nstatusFailed = MibStatus('failed')\nstatusUnprocessed = MibStatus('unprocessed')\nstatusMissing = MibStatus('missing')\nstatusBorrowed = MibStatus('borrowed')\n\n\nclass MibCompiler(object):\n    \"\"\"Top-level, user-facing, composite MIB compiler object.\n\n    MibCompiler implements high-level MIB transformation processing logic.\n    It executes its actions by calling the following specialized objects:\n\n      * *readers* - to acquire ASN.1 MIB data\n      * *searchers* - to see if transformed MIB already exists and no processing is necessary\n      * *parser* - to parse ASN.1 MIB into AST\n      * *code generator* - to perform actual MIB transformation\n      * *borrowers* - to fetch pre-transformed MIB if transformation is impossible\n      * *writer* - to store transformed MIB data\n\n    Required components must be passed to MibCompiler on instantiation. Those\n    components are: *parser*, *codegenerator* and *writer*.\n\n    Optional components could be set or modified at later phases of MibCompiler\n    life. Unlike singular, required components, optional one can be present\n    in sequences to address many possible sources of data. They are\n    *readers*, *searchers* and *borrowers*.\n    \"\"\"\n    indexFile = 'index'\n\n    def __init__(self, parser, codegen, writer):\n        \"\"\"Creates an instance of *MibCompiler* class.\n\n           Args:\n               parser: ASN.1 MIB parser object\n               codegen: MIB transformation object\n               writer: transformed MIB storing object\n        \"\"\"\n        self._parser = parser\n        self._codegen = codegen\n        self._symbolgen = SymtableCodeGen()\n        self._writer = writer\n        self._sources = []\n        self._searchers = []\n        self._borrowers = []\n\n    def addSources(self, *sources):\n        \"\"\"Add more ASN.1 MIB source repositories.\n\n        MibCompiler.compile will invoke each of configured source objects\n        in order of their addition asking each to fetch MIB module specified\n        by name.\n\n        Args:\n            sources: reader object(s)\n\n        Returns:\n            reference to itself (can be used for call chaining)\n\n        \"\"\"\n        self._sources.extend(sources)\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'current MIB source(s): %s' % ', '.join([str(x) for x in self._sources]))\n\n        return self\n\n    def addSearchers(self, *searchers):\n        \"\"\"Add more transformed MIBs repositories.\n\n        MibCompiler.compile will invoke each of configured searcher objects\n        in order of their addition asking each if already transformed MIB\n        module already exists and is more recent than specified.\n\n        Args:\n            searchers: searcher object(s)\n\n        Returns:\n            reference to itself (can be used for call chaining)\n\n        \"\"\"\n        self._searchers.extend(searchers)\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'current compiled MIBs location(s): %s' % ', '.join([str(x) for x in self._searchers]))\n\n        return self\n\n    def addBorrowers(self, *borrowers):\n        \"\"\"Add more transformed MIBs repositories to borrow MIBs from.\n\n        Whenever MibCompiler.compile encounters MIB module which neither of\n        the *searchers* can find or fetched ASN.1 MIB module can not be\n        parsed (due to syntax errors), these *borrowers* objects will be\n        invoked in order of their addition asking each if already transformed\n        MIB can be fetched (borrowed).\n\n        Args:\n            borrowers: borrower object(s)\n\n        Returns:\n            reference to itself (can be used for call chaining)\n\n        \"\"\"\n        self._borrowers.extend(borrowers)\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'current MIB borrower(s): %s' % ', '.join([str(x) for x in self._borrowers]))\n\n        return self\n\n    def _get_system_info(self):\n\n        try:\n            platform_info = os.uname()\n\n        except AttributeError:\n            platform_info = ('?',) * 6\n\n        try:\n            user_info = getpwuid(os.getuid())\n\n        except Exception:\n            user_info = ('?',) * 7\n\n        return platform_info, user_info\n\n    def compile(self, *mibnames, **options):\n        \"\"\"Transform requested and possibly referred MIBs.\n\n        The *compile* method should be invoked when *MibCompiler* object\n        is operational meaning at least *sources* are specified.\n\n        Once called with a MIB module name, *compile* will:\n\n        * fetch ASN.1 MIB module with given name by calling *sources*\n        * make sure no such transformed MIB already exists (with *searchers*)\n        * parse ASN.1 MIB text with *parser*\n        * perform actual MIB transformation into target format with *code generator*\n        * may attempt to borrow pre-transformed MIB through *borrowers*\n        * write transformed MIB through *writer*\n\n        The above sequence will be performed for each MIB name given in\n        *mibnames* and may be performed for all MIBs referred to from\n        MIBs being processed.\n\n        Args:\n            mibnames: list of ASN.1 MIBs names\n            options: options that affect the way PySMI components work\n\n        Returns:\n            A dictionary of MIB module names processed (keys) and *MibStatus*\n            class instances (values)\n\n        \"\"\"\n        processed = {}\n        parsedMibs = {}\n        failedMibs = {}\n        borrowedMibs = {}\n        builtMibs = {}\n        symbolTableMap = {}\n        mibsToParse = [x for x in mibnames]\n        canonicalMibNames = {}\n\n        while mibsToParse:\n            mibname = mibsToParse.pop(0)\n\n            if mibname in parsedMibs:\n                debug.logger & debug.flagCompiler and debug.logger('MIB %s already parsed' % mibname)\n                continue\n\n            if mibname in failedMibs:\n                debug.logger & debug.flagCompiler and debug.logger('MIB %s already failed' % mibname)\n                continue\n\n            for source in self._sources:\n                debug.logger & debug.flagCompiler and debug.logger('trying source %s' % source)\n\n                try:\n                    fileInfo, fileData = source.getData(mibname)\n\n                    for mibTree in self._parser.parse(fileData):\n                        mibInfo, symbolTable = self._symbolgen.genCode(\n                            mibTree, symbolTableMap\n                        )\n\n                        symbolTableMap[mibInfo.name] = symbolTable\n\n                        parsedMibs[mibInfo.name] = fileInfo, mibInfo, mibTree\n\n                        if mibname in failedMibs:\n                            del failedMibs[mibname]\n\n                        mibsToParse.extend(mibInfo.imported)\n\n                        if fileInfo.name in mibnames:\n                            if mibInfo.name not in canonicalMibNames:\n                                canonicalMibNames[mibInfo.name] = []\n                            canonicalMibNames[mibInfo.name].append(fileInfo.name)\n\n                        debug.logger & debug.flagCompiler and debug.logger(\n                            '%s (%s) read from %s, immediate dependencies: %s' % (\n                                mibInfo.name, mibname, fileInfo.path, ', '.join(mibInfo.imported) or '<none>'))\n\n                    break\n\n                except error.PySmiReaderFileNotFoundError:\n                    debug.logger & debug.flagCompiler and debug.logger('no %s found at %s' % (mibname, source))\n                    continue\n\n                except error.PySmiError:\n                    exc_class, exc, tb = sys.exc_info()\n                    exc.source = source\n                    exc.mibname = mibname\n                    exc.msg += ' at MIB %s' % mibname\n\n                    debug.logger & debug.flagCompiler and debug.logger('%serror %s from %s' % (\n                        options.get('ignoreErrors') and 'ignoring ' or 'failing on ', exc, source))\n\n                    failedMibs[mibname] = exc\n\n                    processed[mibname] = statusFailed.setOptions(error=exc)\n\n            else:\n                exc = error.PySmiError('MIB source %s not found' % mibname)\n                exc.mibname = mibname\n                debug.logger & debug.flagCompiler and debug.logger('no %s found everywhere' % mibname)\n\n                if mibname not in failedMibs:\n                    failedMibs[mibname] = exc\n\n                if mibname not in processed:\n                    processed[mibname] = statusMissing\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs analyzed %s, MIBs failed %s' % (len(parsedMibs), len(failedMibs)))\n\n        #\n        # See what MIBs need generating\n        #\n\n        for mibname in tuple(parsedMibs):\n            fileInfo, mibInfo, mibTree = parsedMibs[mibname]\n\n            debug.logger & debug.flagCompiler and debug.logger('checking if %s requires updating' % mibname)\n\n            for searcher in self._searchers:\n                try:\n                    searcher.fileExists(mibname, fileInfo.mtime, rebuild=options.get('rebuild'))\n\n                except error.PySmiFileNotFoundError:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'no compiled MIB %s available through %s' % (mibname, searcher))\n                    continue\n\n                except error.PySmiFileNotModifiedError:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'will be using existing compiled MIB %s found by %s' % (mibname, searcher))\n                    del parsedMibs[mibname]\n                    processed[mibname] = statusUntouched\n                    break\n\n                except error.PySmiError:\n                    exc_class, exc, tb = sys.exc_info()\n                    exc.searcher = searcher\n                    exc.mibname = mibname\n                    exc.msg += ' at MIB %s' % mibname\n                    debug.logger & debug.flagCompiler and debug.logger('error from %s: %s' % (searcher, exc))\n                    continue\n\n            else:\n                debug.logger & debug.flagCompiler and debug.logger(\n                    'no suitable compiled MIB %s found anywhere' % mibname)\n\n                if options.get('noDeps') and mibname not in canonicalMibNames:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'excluding imported MIB %s from code generation' % mibname)\n                    del parsedMibs[mibname]\n                    processed[mibname] = statusUntouched\n                    continue\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs parsed %s, MIBs failed %s' % (len(parsedMibs), len(failedMibs)))\n\n        #\n        # Generate code for parsed MIBs\n        #\n\n        for mibname in parsedMibs.copy():\n            fileInfo, mibInfo, mibTree = parsedMibs[mibname]\n\n            debug.logger & debug.flagCompiler and debug.logger('compiling %s read from %s' % (mibname, fileInfo.path))\n\n            platform_info, user_info = self._get_system_info()\n\n            comments = [\n                'ASN.1 source %s' % fileInfo.path,\n                'Produced by %s-%s at %s' % (packageName, packageVersion, time.asctime()),\n                'On host %s platform %s version %s by user %s' % (platform_info[1], platform_info[0],\n                                                                  platform_info[2], user_info[0]),\n                'Using Python version %s' % sys.version.split('\\n')[0]\n            ]\n\n            try:\n                mibInfo, mibData = self._codegen.genCode(\n                    mibTree,\n                    symbolTableMap,\n                    comments=comments,\n                    dstTemplate=options.get('dstTemplate'),\n                    genTexts=options.get('genTexts'),\n                    textFilter=options.get('textFilter')\n                )\n\n                builtMibs[mibname] = fileInfo, mibInfo, mibData\n                del parsedMibs[mibname]\n\n                debug.logger & debug.flagCompiler and debug.logger(\n                    '%s read from %s and compiled by %s' % (mibname, fileInfo.path, self._writer))\n\n            except error.PySmiError:\n                exc_class, exc, tb = sys.exc_info()\n                exc.handler = self._codegen\n                exc.mibname = mibname\n                exc.msg += ' at MIB %s' % mibname\n\n                debug.logger & debug.flagCompiler and debug.logger('error from %s: %s' % (self._codegen, exc))\n\n                processed[mibname] = statusFailed.setOptions(error=exc)\n\n                failedMibs[mibname] = exc\n                del parsedMibs[mibname]\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs built %s, MIBs failed %s' % (len(parsedMibs), len(failedMibs)))\n\n        #\n        # Try to borrow pre-compiled MIBs for failed ones\n        #\n\n        for mibname in failedMibs.copy():\n            if options.get('noDeps') and mibname not in canonicalMibNames:\n                debug.logger & debug.flagCompiler and debug.logger('excluding imported MIB %s from borrowing' % mibname)\n                continue\n\n            for borrower in self._borrowers:\n                debug.logger & debug.flagCompiler and debug.logger('trying to borrow %s from %s' % (mibname, borrower))\n                try:\n                    fileInfo, fileData = borrower.getData(\n                        mibname,\n                        genTexts=options.get('genTexts')\n                    )\n\n                    borrowedMibs[mibname] = fileInfo, MibInfo(name=mibname, imported=[]), fileData\n\n                    del failedMibs[mibname]\n\n                    debug.logger & debug.flagCompiler and debug.logger('%s borrowed with %s' % (mibname, borrower))\n                    break\n\n                except error.PySmiError:\n                    debug.logger & debug.flagCompiler and debug.logger('error from %s: %s' % (borrower, sys.exc_info()[1]))\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs available for borrowing %s, MIBs failed %s' % (len(borrowedMibs), len(failedMibs)))\n\n        #\n        # See what MIBs need borrowing\n        #\n\n        for mibname in borrowedMibs.copy():\n            debug.logger & debug.flagCompiler and debug.logger('checking if failed MIB %s requires borrowing' % mibname)\n\n            fileInfo, mibInfo, mibData = borrowedMibs[mibname]\n\n            for searcher in self._searchers:\n                try:\n                    searcher.fileExists(mibname, fileInfo.mtime, rebuild=options.get('rebuild'))\n\n                except error.PySmiFileNotFoundError:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'no compiled MIB %s available through %s' % (mibname, searcher))\n                    continue\n\n                except error.PySmiFileNotModifiedError:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'will be using existing compiled MIB %s found by %s' % (mibname, searcher))\n                    del borrowedMibs[mibname]\n                    processed[mibname] = statusUntouched\n                    break\n\n                except error.PySmiError:\n                    exc_class, exc, tb = sys.exc_info()\n                    exc.searcher = searcher\n                    exc.mibname = mibname\n                    exc.msg += ' at MIB %s' % mibname\n\n                    debug.logger & debug.flagCompiler and debug.logger('error from %s: %s' % (searcher, exc))\n\n                    continue\n            else:\n                debug.logger & debug.flagCompiler and debug.logger(\n                    'no suitable compiled MIB %s found anywhere' % mibname)\n\n                if options.get('noDeps') and mibname not in canonicalMibNames:\n                    debug.logger & debug.flagCompiler and debug.logger(\n                        'excluding imported MIB %s from borrowing' % mibname)\n                    processed[mibname] = statusUntouched\n\n                else:\n                    debug.logger & debug.flagCompiler and debug.logger('will borrow MIB %s' % mibname)\n                    builtMibs[mibname] = borrowedMibs[mibname]\n\n                    processed[mibname] = statusBorrowed.setOptions(\n                        path=fileInfo.path, file=fileInfo.file,\n                        alias=fileInfo.name\n                    )\n\n                del borrowedMibs[mibname]\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs built %s, MIBs failed %s' % (len(builtMibs), len(failedMibs)))\n\n        #\n        # We could attempt to ignore missing/failed MIBs\n        #\n\n        if failedMibs and not options.get('ignoreErrors'):\n            debug.logger & debug.flagCompiler and debug.logger('failing with problem MIBs %s' % ', '.join(failedMibs))\n\n            for mibname in builtMibs:\n                processed[mibname] = statusUnprocessed\n\n            return processed\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'proceeding with built MIBs %s, failed MIBs %s' % (', '.join(builtMibs), ', '.join(failedMibs)))\n\n        #\n        # Store compiled MIBs\n        #\n\n        for mibname in builtMibs.copy():\n            fileInfo, mibInfo, mibData = builtMibs[mibname]\n\n            try:\n                if options.get('writeMibs', True):\n                    self._writer.putData(\n                        mibname, mibData, dryRun=options.get('dryRun')\n                    )\n\n                debug.logger & debug.flagCompiler and debug.logger('%s stored by %s' % (mibname, self._writer))\n\n                del builtMibs[mibname]\n\n                if mibname not in processed:\n                    processed[mibname] = statusCompiled.setOptions(\n                        path=fileInfo.path,\n                        file=fileInfo.file,\n                        alias=fileInfo.name,\n                        oid=mibInfo.oid,\n                        oids=mibInfo.oids,\n                        identity=mibInfo.identity,\n                        revision=mibInfo.revision,\n                        enterprise=mibInfo.enterprise,\n                        compliance=mibInfo.compliance,\n                    )\n\n            except error.PySmiError:\n                exc_class, exc, tb = sys.exc_info()\n                exc.handler = self._codegen\n                exc.mibname = mibname\n                exc.msg += ' at MIB %s' % mibname\n\n                debug.logger & debug.flagCompiler and debug.logger('error %s from %s' % (exc, self._writer))\n\n                processed[mibname] = statusFailed.setOptions(error=exc)\n                failedMibs[mibname] = exc\n                del builtMibs[mibname]\n\n        debug.logger & debug.flagCompiler and debug.logger(\n            'MIBs modified: %s' % ', '.join([x for x in processed if processed[x] in ('compiled', 'borrowed')]))\n\n        return processed\n\n    def buildIndex(self, processedMibs, **options):\n        platform_info, user_info = self._get_system_info()\n\n        comments = [\n            'Produced by %s-%s at %s' % (packageName, packageVersion, time.asctime()),\n            'On host %s platform %s version %s by user %s' % (platform_info[1], platform_info[0],\n                                                              platform_info[2], user_info[0]),\n            'Using Python version %s' % sys.version.split('\\n')[0]\n        ]\n\n        try:\n            self._writer.putData(\n                self.indexFile,\n                self._codegen.genIndex(\n                    processedMibs,\n                    comments=comments,\n                    old_index_data=self._writer.getData(self.indexFile)\n                ),\n                dryRun=options.get('dryRun')\n            )\n        except error.PySmiError:\n            exc_class, exc, tb = sys.exc_info()\n            exc.msg += ' at MIB index %s' % self.indexFile\n\n            debug.logger & debug.flagCompiler and debug.logger('error %s when building %s' % (exc, self.indexFile))\n\n            if options.get('ignoreErrors'):\n                return\n\n            if hasattr(exc, 'with_traceback'):\n                raise exc.with_traceback(tb)\n            else:\n                raise exc\n"
  },
  {
    "path": "pysmi/debug.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport logging\nfrom pysmi import error\nfrom pysmi import __version__\n\nflagNone = 0x0000\nflagSearcher = 0x0001\nflagReader = 0x0002\nflagLexer = 0x0004\nflagParser = 0x0008\nflagGrammar = 0x0010\nflagCodegen = 0x0020\nflagWriter = 0x0040\nflagCompiler = 0x0080\nflagBorrower = 0x0100\nflagAll = 0xffff\n\nflagMap = {\n    'searcher': flagSearcher,\n    'reader': flagReader,\n    'lexer': flagLexer,\n    'parser': flagParser,\n    'grammar': flagGrammar,\n    'codegen': flagCodegen,\n    'writer': flagWriter,\n    'compiler': flagCompiler,\n    'borrower': flagBorrower,\n    'all': flagAll\n}\n\n\nclass Printer(object):\n    def __init__(self, logger=None, handler=None, formatter=None):\n        if logger is None:\n            logger = logging.getLogger('pysmi')\n\n        logger.setLevel(logging.DEBUG)\n\n        if handler is None:\n            handler = logging.StreamHandler()\n\n        if formatter is None:\n            formatter = logging.Formatter('%(asctime)s %(name)s: %(message)s')\n\n        handler.setFormatter(formatter)\n        handler.setLevel(logging.DEBUG)\n\n        logger.addHandler(handler)\n\n        self.__logger = logger\n\n    def __call__(self, msg):\n        self.__logger.debug(msg)\n\n    def __str__(self):\n        return '<python built-in logging>'\n\n    def getCurrentLogger(self):\n        return self.__logger\n\n\nif hasattr(logging, 'NullHandler'):\n    NullHandler = logging.NullHandler\nelse:\n    # Python 2.6 and older\n    class NullHandler(logging.Handler):\n        def emit(self, record):\n            pass\n\n\nclass Debug(object):\n    defaultPrinter = None\n\n    def __init__(self, *flags, **options):\n        self._flags = flagNone\n        if options.get('printer') is not None:\n            self._printer = options.get('printer')\n\n        elif self.defaultPrinter is not None:\n            self._printer = self.defaultPrinter\n\n        else:\n            if 'loggerName' in options:\n                # route our logs to parent logger\n                self._printer = Printer(\n                    logger=logging.getLogger(options['loggerName']),\n                    handler=NullHandler()\n                )\n            else:\n                self._printer = Printer()\n\n        self('running pysmi version %s' % __version__)\n\n        for flag in flags:\n            inverse = flag and flag[0] in ('!', '~')\n\n            if inverse:\n                flag = flag[1:]\n\n            try:\n                if inverse:\n                    self._flags &= ~flagMap[flag]\n                else:\n                    self._flags |= flagMap[flag]\n\n            except KeyError:\n                raise error.PySmiError('bad debug flag %s' % flag)\n\n            self('debug category \\'%s\\' %s' % (flag, inverse and 'disabled' or 'enabled'))\n\n    def __str__(self):\n        return 'logger %s, flags %x' % (self._printer, self._flags)\n\n    def __call__(self, msg):\n        self._printer(msg)\n\n    def __and__(self, flag):\n        return self._flags & flag\n\n    def __rand__(self, flag):\n        return flag & self._flags\n\n    def getCurrentPrinter(self):\n        return self._printer\n\n    def getCurrentLogger(self):\n        return self._printer and self._printer.getCurrentLogger() or None\n\n\n# This will yield false from bitwise and with a flag, and save\n# on unnecessary calls\nlogger = 0\n\n\ndef setLogger(l):\n    global logger\n    logger = l\n"
  },
  {
    "path": "pysmi/error.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n# Package exception model:\n# Here we subclass base Python exception overriding its constructor to\n# accomodate error message string as its first parameter and an open\n# set of keyword arguments that become exception object attributes.\n# While exception object is bubbling up the call stack, intermediate\n# exception handlers may insert their own attributes into exception\n# object.\n#\n\n\nclass PySmiError(Exception):\n    def __init__(self, *args, **kwargs):\n        Exception.__init__(self, *args)\n        self.msg = args and args[0] or ''\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n\n    def __repr__(self):\n        return '%s(%s)' % (self.__class__.__name__, ', '.join(\n            ['%s=%r' % (k, getattr(self, k)) for k in dir(self) if k[0] != '_' and k != 'args']))\n\n    def __str__(self):\n        return self.msg\n\n\nclass PySmiLexerError(PySmiError):\n    lineno = '?'\n\n    def __str__(self):\n        return self.msg + ', line %s' % self.lineno\n\n\nclass PySmiParserError(PySmiLexerError):\n    pass\n\n\nclass PySmiSyntaxError(PySmiParserError):\n    pass\n\n\nclass PySmiSearcherError(PySmiError):\n    pass\n\n\nclass PySmiFileNotModifiedError(PySmiSearcherError):\n    pass\n\n\nclass PySmiFileNotFoundError(PySmiSearcherError):\n    pass\n\n\nclass PySmiReaderError(PySmiError):\n    pass\n\n\nclass PySmiReaderFileNotModifiedError(PySmiReaderError):\n    pass\n\n\nclass PySmiReaderFileNotFoundError(PySmiReaderError):\n    pass\n\n\nclass PySmiCodegenError(PySmiError):\n    pass\n\n\nclass PySmiSemanticError(PySmiCodegenError):\n    pass\n\n\nclass PySmiWriterError(PySmiError):\n    pass\n"
  },
  {
    "path": "pysmi/lexer/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.lexer.smi import SmiV2Lexer\n"
  },
  {
    "path": "pysmi/lexer/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n\nclass AbstractLexer(object):\n    def reset(self):\n        raise NotImplementedError()\n"
  },
  {
    "path": "pysmi/lexer/smi.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport re\nimport ply.lex as lex\nfrom pysmi.lexer.base import AbstractLexer\nfrom pysmi import error\nfrom pysmi import debug\n\nUNSIGNED32_MAX = 4294967295\nUNSIGNED64_MAX = 18446744073709551615\nLEX_VERSION = [int(x) for x in lex.__version__.split('.')]\n\n# Do not overload single lexer methods - overload all or none of them!\n# noinspection PySingleQuotedDocstring,PyMethodMayBeStatic,PyIncorrectDocstring\nclass SmiV2Lexer(AbstractLexer):\n    reserved_words = [\n        'ACCESS', 'AGENT-CAPABILITIES', 'APPLICATION', 'AUGMENTS', 'BEGIN', 'BITS',\n        'CONTACT-INFO', 'CREATION-REQUIRES', 'Counter', 'Counter32', 'Counter64',\n        'DEFINITIONS', 'DEFVAL', 'DESCRIPTION', 'DISPLAY-HINT', 'END', 'ENTERPRISE',\n        'EXTENDS', 'FROM', 'GROUP', 'Gauge', 'Gauge32', 'IDENTIFIER', 'IMPLICIT',\n        'IMPLIED', 'IMPORTS', 'INCLUDES', 'INDEX', 'INSTALL-ERRORS', 'INTEGER',\n        'Integer32', 'IpAddress', 'LAST-UPDATED', 'MANDATORY-GROUPS',\n        'MAX-ACCESS', 'MIN-ACCESS', 'MODULE', 'MODULE-COMPLIANCE',\n        'MODULE-IDENTITY', 'NOTIFICATION-GROUP', 'NOTIFICATION-TYPE',\n        'NOTIFICATIONS', 'OBJECT', 'OBJECT-GROUP', 'OBJECT-IDENTITY', 'OBJECT-TYPE',\n        'OBJECTS', 'OCTET', 'OF', 'ORGANIZATION', 'Opaque', 'PIB-ACCESS',\n        'PIB-DEFINITIONS', 'PIB-INDEX', 'PIB-MIN-ACCESS', 'PIB-REFERENCES',\n        'PIB-TAG', 'POLICY-ACCESS', 'PRODUCT-RELEASE', 'REFERENCE', 'REVISION',\n        'SEQUENCE', 'SIZE', 'STATUS', 'STRING', 'SUBJECT-CATEGORIES', 'SUPPORTS',\n        'SYNTAX', 'TEXTUAL-CONVENTION', 'TimeTicks', 'TRAP-TYPE', 'UNIQUENESS',\n        'UNITS', 'UNIVERSAL', 'Unsigned32', 'VALUE', 'VARIABLES',\n        'VARIATION', 'WRITE-SYNTAX'\n    ]\n\n    reserved = {}\n    for w in reserved_words:\n        reserved[w] = w.replace('-', '_').upper()\n        # hack to support SMIv1\n        if w == 'Counter':\n            reserved[w] = 'COUNTER32'\n        elif w == 'Gauge':\n            reserved[w] = 'GAUGE32'\n\n    forbidden_words = [\n        'ABSENT', 'ANY', 'BIT', 'BOOLEAN', 'BY', 'COMPONENT', 'COMPONENTS',\n        'DEFAULT', 'DEFINED', 'ENUMERATED', 'EXPLICIT', 'EXTERNAL', 'FALSE', 'MAX',\n        'MIN', 'MINUS-INFINITY', 'NULL', 'OPTIONAL', 'PLUS-INFINITY', 'PRESENT',\n        'PRIVATE', 'REAL', 'SET', 'TAGS', 'TRUE', 'WITH'\n    ]\n\n    # Token names required!\n    tokens = list(set([\n                          'BIN_STRING',\n                          'CHOICE',\n                          'COLON_COLON_EQUAL',\n                          'DOT_DOT',\n                          'EXPORTS',\n                          'HEX_STRING',\n                          'LOWERCASE_IDENTIFIER',\n                          'MACRO',\n                          'NEGATIVENUMBER',\n                          'NEGATIVENUMBER64',\n                          'NUMBER',\n                          'NUMBER64',\n                          'QUOTED_STRING',\n                          'UPPERCASE_IDENTIFIER',\n                      ] + list(reserved.values())\n                      ))\n\n    states = (\n        ('macro', 'exclusive'),\n        ('choice', 'exclusive'),\n        ('exports', 'exclusive'),\n        ('comment', 'exclusive'),\n    )\n\n    literals = '[]{}():;,-.|'\n\n    t_DOT_DOT = r'\\.\\.'\n    t_COLON_COLON_EQUAL = r'::='\n\n    t_ignore = ' \\t'\n\n    def __init__(self, tempdir=''):\n        self._tempdir = tempdir\n        self.lexer = None\n        self.reset()\n\n    def reset(self):\n        if LEX_VERSION < [3, 0]:\n            self.lexer = lex.lex(module=self,\n                                 reflags=re.DOTALL,\n                                 outputdir=self._tempdir,\n                                 debug=False)\n        else:\n            if debug.logger & debug.flagLexer:\n                logger = debug.logger.getCurrentLogger()\n            else:\n                logger = lex.NullLogger()\n\n            if debug.logger & debug.flagGrammar:\n                debuglogger = debug.logger.getCurrentLogger()\n            else:\n                debuglogger = None\n\n            self.lexer = lex.lex(module=self,\n                                 reflags=re.DOTALL,\n                                 outputdir=self._tempdir,\n                                 debuglog=debuglogger,\n                                 errorlog=logger)\n\n    def t_newline(self, t):\n        r'\\r\\n|\\n|\\r'\n        t.lexer.lineno += 1\n\n    # Skipping MACRO\n    def t_MACRO(self, t):\n        r'MACRO'\n        t.lexer.begin('macro')\n        return t\n\n    def t_macro_newline(self, t):\n        r'\\r\\n|\\n|\\r'\n        t.lexer.lineno += 1\n\n    def t_macro_END(self, t):\n        r'END'\n        t.lexer.begin('INITIAL')\n        return t\n\n    def t_macro_body(self, t):\n        r'.+?(?=END)'\n        pass\n\n    # Skipping EXPORTS\n    def t_EXPORTS(self, t):\n        r'EXPORTS'\n        t.lexer.begin('exports')\n        return t\n\n    def t_exports_newline(self, t):\n        r'\\r\\n|\\n|\\r'\n        t.lexer.lineno += 1\n\n    def t_exports_end(self, t):\n        r';'\n        t.lexer.begin('INITIAL')\n\n    def t_exports_body(self, t):\n        r'[^;]+'\n        pass\n\n    # Skipping CHOICE\n    def t_CHOICE(self, t):\n        r'CHOICE'\n        t.lexer.begin('choice')\n        return t\n\n    def t_choice_newline(self, t):\n        r'\\r\\n|\\n|\\r'\n        t.lexer.lineno += 1\n\n    def t_choice_end(self, t):\n        r'\\}'\n        t.lexer.begin('INITIAL')\n\n    def t_choice_body(self, t):\n        r'[^\\}]+'\n        pass\n\n    # Comment handling\n    def t_begin_comment(self, t):\n        r'--'\n        t.lexer.begin('comment')\n\n    def t_comment_newline(self, t):\n        r'\\r\\n|\\n|\\r'\n        t.lexer.lineno += 1\n        t.lexer.begin('INITIAL')\n\n    #  def t_comment_end(self, t):\n    #    r'--'\n    #    t.lexer.begin('INITIAL')\n\n    def t_comment_body(self, t):\n        r'[^\\r\\n]+'\n        pass\n\n    def t_UPPERCASE_IDENTIFIER(self, t):\n        r'[A-Z][-a-zA-z0-9]*'\n        if t.value in self.forbidden_words:\n            raise error.PySmiLexerError(\"%s is forbidden\" % t.value, lineno=t.lineno)\n\n        if t.value[-1] == '-':\n            raise error.PySmiLexerError(\"Identifier should not end with '-': %s\" % t.value, lineno=t.lineno)\n\n        t.type = self.reserved.get(t.value, 'UPPERCASE_IDENTIFIER')\n\n        return t\n\n    def t_LOWERCASE_IDENTIFIER(self, t):\n        r'[0-9]*[a-z][-a-zA-z0-9]*'\n        if t.value[-1] == '-':\n            raise error.PySmiLexerError(\"Identifier should not end with '-': %s\" % t.value, lineno=t.lineno)\n        return t\n\n    def t_NUMBER(self, t):\n        r'-?[0-9]+'\n        t.value = int(t.value)\n        neg = 0\n        if t.value < 0:\n            neg = 1\n\n        val = abs(t.value)\n\n        if val <= UNSIGNED32_MAX:\n            if neg:\n                t.type = 'NEGATIVENUMBER'\n\n        elif val <= UNSIGNED64_MAX:\n            if neg:\n                t.type = 'NEGATIVENUMBER64'\n            else:\n                t.type = 'NUMBER64'\n\n        else:\n            raise error.PySmiLexerError(\"Number %s is too big\" % t.value, lineno=t.lineno)\n\n        return t\n\n    def t_BIN_STRING(self, t):\n        r'\\'[01]*\\'[bB]'\n        value = t.value[1:-2]\n        while value and value[0] == '0' and len(value) % 8:\n            value = value[1:]\n        # XXX raise in strict mode\n        #    if len(value) % 8:\n        #      raise error.PySmiLexerError(\"Number of 0s and 1s have to divide by 8 in binary string %s\" % t.value, lineno=t.lineno)\n        return t\n\n    def t_HEX_STRING(self, t):\n        r'\\'[0-9a-fA-F]*\\'[hH]'\n        value = t.value[1:-2]\n        while value and value[0] == '0' and len(value) % 2:\n            value = value[1:]\n        # XXX raise in strict mode\n        #    if len(value) % 2:\n        #      raise error.PySmiLexerError(\"Number of symbols have to be even in hex string %s\" % t.value, lineno=t.lineno)\n        return t\n\n    def t_QUOTED_STRING(self, t):\n        r'\\\"[^\\\"]*\\\"'\n        t.lexer.lineno += len(re.findall(r'\\r\\n|\\n|\\r', t.value))\n        return t\n\n    def t_error(self, t):\n        raise error.PySmiLexerError(\n            \"Illegal character '%s', %s characters left unparsed at this stage\" % (t.value[0], len(t.value) - 1),\n            lineno=t.lineno)\n        # t.lexer.skip(1)\n\n\nclass SupportSmiV1Keywords(object):\n    @staticmethod\n    def reserved():\n        reserved_words = [\n            'ACCESS', 'AGENT-CAPABILITIES', 'APPLICATION', 'AUGMENTS', 'BEGIN', 'BITS',\n            'CONTACT-INFO', 'CREATION-REQUIRES', 'Counter', 'Counter32', 'Counter64',\n            'DEFINITIONS', 'DEFVAL', 'DESCRIPTION', 'DISPLAY-HINT', 'END', 'ENTERPRISE',\n            'EXTENDS', 'FROM', 'GROUP', 'Gauge', 'Gauge32', 'IDENTIFIER', 'IMPLICIT',\n            'IMPLIED', 'IMPORTS', 'INCLUDES', 'INDEX', 'INSTALL-ERRORS', 'INTEGER',\n            'Integer32', 'IpAddress', 'LAST-UPDATED', 'MANDATORY-GROUPS',\n            'MAX-ACCESS', 'MIN-ACCESS', 'MODULE', 'MODULE-COMPLIANCE', 'MAX',\n            'MODULE-IDENTITY', 'NetworkAddress', 'NOTIFICATION-GROUP',\n            'NOTIFICATION-TYPE', 'NOTIFICATIONS', 'OBJECT', 'OBJECT-GROUP',\n            'OBJECT-IDENTITY', 'OBJECT-TYPE', 'OBJECTS', 'OCTET', 'OF', 'ORGANIZATION',\n            'Opaque', 'PIB-ACCESS', 'PIB-DEFINITIONS', 'PIB-INDEX', 'PIB-MIN-ACCESS',\n            'PIB-REFERENCES', 'PIB-TAG', 'POLICY-ACCESS', 'PRODUCT-RELEASE',\n            'REFERENCE', 'REVISION', 'SEQUENCE', 'SIZE', 'STATUS', 'STRING',\n            'SUBJECT-CATEGORIES', 'SUPPORTS', 'SYNTAX', 'TEXTUAL-CONVENTION',\n            'TimeTicks', 'TRAP-TYPE', 'UNIQUENESS', 'UNITS', 'UNIVERSAL', 'Unsigned32',\n            'VALUE', 'VARIABLES', 'VARIATION', 'WRITE-SYNTAX'\n        ]\n\n        reserved = {}\n        for w in reserved_words:\n            reserved[w] = w.replace('-', '_').upper()\n            # hack to support SMIv1\n            if w == 'Counter':\n                reserved[w] = 'COUNTER32'\n            elif w == 'Gauge':\n                reserved[w] = 'GAUGE32'\n\n        return reserved\n\n    @staticmethod\n    def forbidden_words():\n        return [\n            'ABSENT', 'ANY', 'BIT', 'BOOLEAN', 'BY', 'COMPONENT', 'COMPONENTS',\n            'DEFAULT', 'DEFINED', 'ENUMERATED', 'EXPLICIT', 'EXTERNAL', 'FALSE',\n            'MIN', 'MINUS-INFINITY', 'NULL', 'OPTIONAL', 'PLUS-INFINITY', 'PRESENT',\n            'PRIVATE', 'REAL', 'SET', 'TAGS', 'TRUE', 'WITH'\n        ]\n\n    @staticmethod\n    def tokens():\n        # Token names required!\n        tokens = [\n            'BIN_STRING',\n            'CHOICE',\n            'COLON_COLON_EQUAL',\n            'DOT_DOT',\n            'EXPORTS',\n            'HEX_STRING',\n            'LOWERCASE_IDENTIFIER',\n            'MACRO',\n            'NEGATIVENUMBER',\n            'NEGATIVENUMBER64',\n            'NUMBER',\n            'NUMBER64',\n            'QUOTED_STRING',\n            'UPPERCASE_IDENTIFIER',\n        ]\n        tokens += list(SupportSmiV1Keywords.reserved().values())\n        return list(set(tokens))\n\n\nrelaxedGrammar = {\n    'supportSmiV1Keywords': [\n        SupportSmiV1Keywords.reserved,\n        SupportSmiV1Keywords.forbidden_words,\n        SupportSmiV1Keywords.tokens\n    ],\n    'supportIndex': [],\n    'commaAtTheEndOfImport': [],\n    'commaAtTheEndOfSequence': [],\n    'mixOfCommasAndSpaces': [],\n    'uppercaseIdentifier': [],\n    'lowcaseIdentifier': [],\n    'curlyBracesAroundEnterpriseInTrap': [],\n    'noCells': []\n}\n\n\ndef lexerFactory(**grammarOptions):\n    classAttr = {}\n\n    for option in grammarOptions:\n        if grammarOptions[option]:\n            if option not in relaxedGrammar:\n                raise error.PySmiError('Unknown lexer relaxation option: %s' % option)\n\n            for func in relaxedGrammar[option]:\n                if sys.version_info[0] > 2:\n                    classAttr[func.__name__] = func()\n                else:\n                    classAttr[func.func_name] = func()\n\n    return type('SmiLexer', (SmiV2Lexer,), classAttr)\n"
  },
  {
    "path": "pysmi/mibinfo.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n\nclass MibInfo(object):\n    #: actual MIB name\n    name = ''\n\n    #: possible alternative to MIB name\n    alias = ''\n\n    #: URL to MIB file\n    path = ''\n\n    #: MIB file name\n    file = ''\n\n    #: MIB file modification time\n    mtime = 0\n\n    #: module OID\n    oid = ''\n\n    #: MIB revision as `datetime`\n    revision = None\n\n    #: all OIDs defined in this module\n    oids = ()\n\n    #: MODULE-IDENTITY OID\n    identity = ''\n\n    #: Enterprise OID\n    enterprise = ()\n\n    #: MODULE-COMPLIANCE OIDs\n    compliance = ()\n\n    #: imported MIB names\n    imported = ()\n\n    def __init__(self, **kwargs):\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n"
  },
  {
    "path": "pysmi/parser/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.parser.smiv1 import SmiV1Parser\nfrom pysmi.parser.smiv1compat import SmiV1CompatParser, SmiStarParser\nfrom pysmi.parser.smiv2 import SmiV2Parser\nfrom pysmi.parser.null import NullParser\n"
  },
  {
    "path": "pysmi/parser/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n\nclass AbstractParser(object):\n    def reset(self):\n        raise NotImplementedError()\n\n    def parse(self, data, **kwargs):\n        raise NotImplementedError()\n"
  },
  {
    "path": "pysmi/parser/dialect.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n#\n# Preconfigured sets of parser options.\n# Individual options could be used in certain combinations.\n#\nsmiV2 = {}\n\nsmiV1 = smiV2.copy()\nsmiV1.update(\n    supportSmiV1Keywords=True,\n    supportIndex=True\n)\n\nsmiV1Relaxed = smiV1.copy()\nsmiV1Relaxed.update(\n    commaAtTheEndOfImport=True,\n    commaAtTheEndOfSequence=True,\n    mixOfCommasAndSpaces=True,\n    uppercaseIdentifier=True,\n    lowcaseIdentifier=True,\n    curlyBracesAroundEnterpriseInTrap=True,\n    noCells=True\n)\n"
  },
  {
    "path": "pysmi/parser/null.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.parser.base import AbstractParser\n\n\nclass NullParser(AbstractParser):\n    def __init__(self, startSym='mibFile', tempdir=''):\n        pass\n\n    def reset(self):\n        pass\n\n    def parse(self, data, **kwargs):\n        return []\n"
  },
  {
    "path": "pysmi/parser/smi.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport ply.yacc as yacc\nfrom pysmi.lexer.smi import lexerFactory\nfrom pysmi.parser.base import AbstractParser\nfrom pysmi import error\nfrom pysmi import debug\n\nYACC_VERSION = [int(x) for x in yacc.__version__.split('.')]\n\n\n# noinspection PyMethodMayBeStatic,PyIncorrectDocstring\nclass SmiV2Parser(AbstractParser):\n    defaultLexer = lexerFactory()\n\n    def __init__(self, startSym='mibFile', tempdir=''):\n        if tempdir:\n            tempdir = os.path.join(tempdir, startSym)\n            try:\n                os.makedirs(tempdir)\n            except OSError:\n                if sys.exc_info()[1].errno != 17:\n                    raise error.PySmiError('Failed to create cache directory %s: %s' % (tempdir, sys.exc_info()[1]))\n\n        self.lexer = self.defaultLexer(tempdir=tempdir)\n\n        # tokens are required for parser\n        self.tokens = self.lexer.tokens\n\n        if YACC_VERSION < [3, 0]:\n            self.parser = yacc.yacc(module=self,\n                                    start=startSym,\n                                    write_tables=bool(tempdir),\n                                    debug=False,\n                                    outputdir=tempdir)\n        else:\n            if debug.logger & debug.flagParser:\n                logger = debug.logger.getCurrentLogger()\n            else:\n                logger = yacc.NullLogger()\n\n            if debug.logger & debug.flagGrammar:\n                debuglogger = debug.logger.getCurrentLogger()\n            else:\n                debuglogger = None\n\n            self.parser = yacc.yacc(module=self,\n                                    start=startSym,\n                                    write_tables=bool(tempdir),\n                                    debug=False,\n                                    outputdir=tempdir,\n                                    debuglog=debuglogger,\n                                    errorlog=logger)\n\n    def reset(self):\n        # Ply requires lexer reinitialization for (at least) resetting lineno\n        self.lexer.reset()\n\n    def parse(self, data, **kwargs):\n        debug.logger & debug.flagParser and debug.logger(\n            'source MIB size is %s characters, first 50 characters are \"%s...\"' % (len(data), data[:50]))\n\n        ast = self.parser.parse(data, lexer=self.lexer.lexer)\n\n        self.reset()\n\n        if ast and ast[0] == 'mibFile' and ast[1]:  # mibfile is not empty\n            return ast[1]\n        else:\n            return []\n\n    #\n    # SMIv2 grammar follows\n    #\n\n    def p_mibFile(self, p):\n        \"\"\"mibFile : modules\n                   | empty\"\"\"\n        p[0] = ('mibFile', p[1])\n\n    def p_modules(self, p):\n        \"\"\"modules : modules module\n                   | module\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1] + [p[2]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_module(self, p):\n        \"\"\"module : moduleName moduleOid DEFINITIONS COLON_COLON_EQUAL BEGIN exportsClause linkagePart declarationPart END\"\"\"\n        p[0] = (p[1],  # name\n                p[2],  # oid\n                p[7],  # linkage (imports)\n                p[8])  # declaration\n\n    def p_moduleOid(self, p):\n        \"\"\"moduleOid : '{' objectIdentifier '}'\n                     | empty\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[2]\n\n    def p_linkagePart(self, p):\n        \"\"\"linkagePart : linkageClause\n                       | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_linkageClause(self, p):\n        \"\"\"linkageClause : IMPORTS importPart ';'\"\"\"\n        p[0] = p[2]\n\n    def p_exportsClause(self, p):\n        \"\"\"exportsClause : EXPORTS\n                         | empty\"\"\"\n\n    def p_importPart(self, p):\n        \"\"\"importPart : imports\n                      | empty\"\"\"\n        # libsmi: TODO: ``IMPORTS ;'' allowed? refer ASN.1!\n        if p[1]:\n            importDict = {}\n            for imp in p[1]:  # don't do just dict() because moduleNames may be repeated\n                fromModule, symbols = imp\n                if fromModule in importDict:\n                    importDict[fromModule] += symbols\n                else:\n                    importDict[fromModule] = symbols\n\n            p[0] = importDict\n\n    def p_imports(self, p):\n        \"\"\"imports : imports import\n                   | import\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1] + [p[2]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_import(self, p):\n        \"\"\"import : importIdentifiers FROM moduleName\"\"\"\n        # libsmi: TODO: multiple clauses with same moduleName allowed?\n        # I guess so. refer ASN.1!\n        p[0] = (p[3],  # moduleName\n                p[1])  # ids\n\n    def p_importIdentifiers(self, p):\n        \"\"\"importIdentifiers : importIdentifiers ',' importIdentifier\n                             | importIdentifier\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    # Note that some named types must not be imported, REF:RFC1902,590\n    def p_importIdentifier(self, p):\n        \"\"\"importIdentifier : LOWERCASE_IDENTIFIER\n                            | UPPERCASE_IDENTIFIER\n                            | importedKeyword\"\"\"\n        p[0] = p[1]\n\n    def p_importedKeyword(self, p):\n        \"\"\"importedKeyword : importedSMIKeyword\n                           | BITS\n                           | INTEGER32\n                           | IPADDRESS\n                           | MANDATORY_GROUPS\n                           | MODULE_COMPLIANCE\n                           | MODULE_IDENTITY\n                           | OBJECT_GROUP\n                           | OBJECT_IDENTITY\n                           | OBJECT_TYPE\n                           | OPAQUE\n                           | TEXTUAL_CONVENTION\n                           | TIMETICKS\n                           | UNSIGNED32\"\"\"\n        p[0] = p[1]\n\n    def p_importedSMIKeyword(self, p):\n        \"\"\"importedSMIKeyword : AGENT_CAPABILITIES\n                              | COUNTER32\n                              | COUNTER64\n                              | GAUGE32\n                              | NOTIFICATION_GROUP\n                              | NOTIFICATION_TYPE\n                              | TRAP_TYPE\"\"\"\n        p[0] = p[1]\n\n    def p_moduleName(self, p):\n        \"\"\"moduleName : UPPERCASE_IDENTIFIER\"\"\"\n        p[0] = p[1]\n\n    def p_declarationPart(self, p):\n        \"\"\"declarationPart : declarations\n                           | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_declarations(self, p):\n        \"\"\"declarations : declarations declaration\n                        | declaration\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1] + [p[2]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_declaration(self, p):\n        \"\"\"declaration : typeDeclaration\n                       | valueDeclaration\n                       | objectIdentityClause\n                       | objectTypeClause\n                       | trapTypeClause\n                       | notificationTypeClause\n                       | moduleIdentityClause\n                       | moduleComplianceClause\n                       | objectGroupClause\n                       | notificationGroupClause\n                       | agentCapabilitiesClause\n                       | macroClause\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_macroClause(self, p):\n        \"\"\"macroClause : macroName MACRO END\"\"\"\n\n    def p_macroName(self, p):\n        \"\"\"macroName : MODULE_IDENTITY\n                     | OBJECT_TYPE\n                     | TRAP_TYPE\n                     | NOTIFICATION_TYPE\n                     | OBJECT_IDENTITY\n                     | TEXTUAL_CONVENTION\n                     | OBJECT_GROUP\n                     | NOTIFICATION_GROUP\n                     | MODULE_COMPLIANCE\n                     | AGENT_CAPABILITIES\"\"\"\n\n    def p_choiceClause(self, p):\n        \"\"\"choiceClause : CHOICE \"\"\"\n\n    # libsmi: The only ASN.1 value declarations are for OIDs, REF:RFC1902,491.\n    def p_fuzzy_lowercase_identifier(self, p):\n        \"\"\"fuzzy_lowercase_identifier : LOWERCASE_IDENTIFIER\n                                      | UPPERCASE_IDENTIFIER\"\"\"\n        p[0] = p[1]\n\n    def p_valueDeclaration(self, p):\n        \"\"\"valueDeclaration : fuzzy_lowercase_identifier OBJECT IDENTIFIER COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('valueDeclaration', p[1],  # id\n                p[6])  # objectIdentifier\n\n    def p_typeDeclaration(self, p):\n        \"\"\"typeDeclaration : typeName COLON_COLON_EQUAL typeDeclarationRHS\"\"\"\n        p[0] = ('typeDeclaration', p[1],  # name\n                p[3])  # declarationRHS\n\n    def p_typeName(self, p):\n        \"\"\"typeName : UPPERCASE_IDENTIFIER\n                    | typeSMI\"\"\"\n        p[0] = p[1]\n\n    def p_typeSMI(self, p):\n        \"\"\"typeSMI : typeSMIandSPPI\n                   | typeSMIonly\"\"\"\n        p[0] = p[1]\n\n    def p_typeSMIandSPPI(self, p):\n        \"\"\"typeSMIandSPPI : IPADDRESS\n                          | TIMETICKS\n                          | OPAQUE\n                          | INTEGER32\n                          | UNSIGNED32\"\"\"\n        p[0] = p[1]\n\n    def p_typeSMIonly(self, p):\n        \"\"\"typeSMIonly : COUNTER32\n                       | GAUGE32\n                       | COUNTER64\"\"\"\n        p[0] = p[1]\n\n    def p_typeDeclarationRHS(self, p):\n        \"\"\"typeDeclarationRHS : Syntax\n                              | TEXTUAL_CONVENTION DisplayPart STATUS Status DESCRIPTION Text ReferPart SYNTAX Syntax\n                              | choiceClause\"\"\"\n        if p[1]:\n            if p[1] == 'TEXTUAL-CONVENTION':\n                p[0] = ('typeDeclarationRHS', p[2],  # display\n                        p[4],  # status\n                        (p[5], p[6]),  # description\n                        p[7],  # reference\n                        p[9])  # syntax\n            else:\n                p[0] = ('typeDeclarationRHS', p[1])\n                # ignore the choiceClause\n\n    def p_conceptualTable(self, p):\n        \"\"\"conceptualTable : SEQUENCE OF row\"\"\"\n        p[0] = ('conceptualTable', p[3])\n\n    def p_row(self, p):\n        \"\"\"row : UPPERCASE_IDENTIFIER\"\"\"\n        # libsmi: TODO: this must be an entryType\n        p[0] = ('row', p[1])\n\n    def p_entryType(self, p):\n        \"\"\"entryType : SEQUENCE '{' sequenceItems '}'\"\"\"\n        p[0] = (p[1], p[3])\n\n    def p_sequenceItems(self, p):\n        \"\"\"sequenceItems : sequenceItems ',' sequenceItem\n                         | sequenceItem\"\"\"\n        # libsmi: TODO: might this list be emtpy?\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_sequenceItem(self, p):\n        \"\"\"sequenceItem : LOWERCASE_IDENTIFIER sequenceSyntax\"\"\"\n        p[0] = (p[1], p[2])\n\n    def p_Syntax(self, p):\n        \"\"\"Syntax : ObjectSyntax\n                  | BITS '{' NamedBits '}'\"\"\"\n        # libsmi: TODO: standalone `BITS' ok? seen in RMON2-MIB\n        # libsmi: -> no, it's only allowed in a SEQUENCE {...}\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 5:\n            p[0] = (p[1], p[3])\n\n    def p_sequenceSyntax(self, p):\n        \"\"\"sequenceSyntax : BITS\n                          | UPPERCASE_IDENTIFIER anySubType\n                          | sequenceObjectSyntax\"\"\"\n        p[0] = p[1]  # no subtype or complex syntax supported\n\n    def p_NamedBits(self, p):\n        \"\"\"NamedBits : NamedBits ',' NamedBit\n                     | NamedBit\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_NamedBit(self, p):\n        \"\"\"NamedBit : LOWERCASE_IDENTIFIER '(' NUMBER ')'\"\"\"\n        p[0] = (p[1], p[3])\n\n    def p_objectIdentityClause(self, p):\n        \"\"\"objectIdentityClause : LOWERCASE_IDENTIFIER OBJECT_IDENTITY STATUS Status DESCRIPTION Text ReferPart COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('objectIdentityClause', p[1],  # id\n                #  p[2], # OBJECT_IDENTITY\n                p[4],  # status\n                (p[5], p[6]),  # description\n                p[7],  # reference\n                p[10])  # objectIdentifier\n\n    def p_objectTypeClause(self, p):\n        \"\"\"objectTypeClause : LOWERCASE_IDENTIFIER OBJECT_TYPE SYNTAX Syntax UnitsPart MaxOrPIBAccessPart STATUS Status descriptionClause ReferPart IndexPart MibIndex DefValPart COLON_COLON_EQUAL '{' ObjectName '}'\"\"\"\n        p[0] = ('objectTypeClause', p[1],  # id\n                #  p[2], # OBJECT_TYPE\n                p[4],  # syntax\n                p[5],  # UnitsPart\n                p[6],  # MaxOrPIBAccessPart\n                p[8],  # status\n                p[9],  # descriptionClause\n                p[10],  # reference\n                p[11],  # augmentions\n                p[12],  # index\n                p[13],  # DefValPart\n                p[16])  # ObjectName\n\n    def p_descriptionClause(self, p):\n        \"\"\"descriptionClause : DESCRIPTION Text\n                             | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_trapTypeClause(self, p):\n        \"\"\"trapTypeClause : fuzzy_lowercase_identifier TRAP_TYPE ENTERPRISE objectIdentifier VarPart DescrPart ReferPart COLON_COLON_EQUAL NUMBER\"\"\"\n        # libsmi: TODO: range of number?\n        p[0] = ('trapTypeClause', p[1],  # fuzzy_lowercase_identifier\n                #  p[2], # TRAP_TYPE\n                p[4],  # objectIdentifier\n                p[5],  # VarPart\n                p[6],  # description\n                p[7],  # reference\n                p[9])  # NUMBER\n\n    def p_VarPart(self, p):\n        \"\"\"VarPart : VARIABLES '{' VarTypes '}'\n                   | empty\"\"\"\n        p[0] = p[1] and p[3] or []\n\n    def p_VarTypes(self, p):\n        \"\"\"VarTypes : VarTypes ',' VarType\n                    | VarType\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('VarTypes', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('VarTypes', [p[1]])\n\n    def p_VarType(self, p):\n        \"\"\"VarType : ObjectName\"\"\"\n        p[0] = p[1][1][0]\n\n    def p_DescrPart(self, p):\n        \"\"\"DescrPart : DESCRIPTION Text\n                     | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_MaxOrPIBAccessPart(self, p):\n        \"\"\"MaxOrPIBAccessPart : MaxAccessPart\n                              | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_MaxAccessPart(self, p):\n        \"\"\"MaxAccessPart : MAX_ACCESS Access\n                         | ACCESS Access\"\"\"\n        p[0] = ('MaxAccessPart', p[2])\n\n    def p_notificationTypeClause(self, p):\n        \"\"\"notificationTypeClause : LOWERCASE_IDENTIFIER NOTIFICATION_TYPE NotificationObjectsPart STATUS Status DESCRIPTION Text ReferPart COLON_COLON_EQUAL '{' NotificationName '}'\"\"\"\n        p[0] = ('notificationTypeClause',\n                p[1],  # id\n                #  p[2], # NOTIFICATION_TYPE\n                p[3],  # NotificationObjectsPart\n                p[5],  # status\n                (p[6], p[7]),  # description\n                p[8],  # reference\n                p[11])  # NotificationName aka objectIdentifier\n\n    def p_moduleIdentityClause(self, p):\n        \"\"\"moduleIdentityClause : LOWERCASE_IDENTIFIER MODULE_IDENTITY SubjectCategoriesPart LAST_UPDATED ExtUTCTime ORGANIZATION Text CONTACT_INFO Text DESCRIPTION Text RevisionPart COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('moduleIdentityClause', p[1],  # id\n                #  p[2], # MODULE_IDENTITY\n                # XXX  p[3], # SubjectCategoriesPart\n                (p[4], p[5]),  # last updated\n                (p[6], p[7]),  # organization\n                (p[8], p[9]),  # contact info\n                (p[10], p[11]),  # description\n                p[12],  # RevisionPart\n                p[15])  # objectIdentifier\n\n    # Subject categories: RFC3159\n\n    def p_SubjectCategoriesPart(self, p):\n        \"\"\"SubjectCategoriesPart : SUBJECT_CATEGORIES '{' SubjectCategories '}'\n                                 | empty\"\"\"\n        # if p[1]:\n        #  p[0] = (p[1], p[3])\n\n    def p_SubjectCategories(self, p):\n        \"\"\"SubjectCategories : CategoryIDs\"\"\"\n        # p[0] = p[1]\n\n    def p_CategoryIDs(self, p):\n        \"\"\"CategoryIDs : CategoryIDs ',' CategoryID\n                       | CategoryID\"\"\"\n        # n = len(p)\n        # if n == 4:\n        #  p[0] = ('CategoryIDs', p[1][1] + [p[3]])\n        # elif n == 2:\n        #  p[0] = ('CategoryIDs', [p[1]])\n\n    def p_CategoryID(self, p):\n        \"\"\"CategoryID : LOWERCASE_IDENTIFIER '(' NUMBER ')'\n                      | LOWERCASE_IDENTIFIER\"\"\"\n        # n = len(p)\n        # if n == 2:\n        #  p[0] = ('CategoryID', p[1])\n        # elif n == 5:\n        #  p[0] = ('CategoryID', p[3])\n\n    # ...subject categories\n\n    def p_ObjectSyntax(self, p):\n        \"\"\"ObjectSyntax : SimpleSyntax\n                        | conceptualTable\n                        | row\n                        | entryType\n                        | ApplicationSyntax\n                        | typeTag SimpleSyntax\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 3:\n            p[0] = p[2]\n\n    def p_typeTag(self, p):\n        \"\"\"typeTag : '[' APPLICATION NUMBER ']' IMPLICIT\n                   | '[' UNIVERSAL NUMBER ']' IMPLICIT\"\"\"\n\n    def p_sequenceObjectSyntax(self, p):\n        \"\"\"sequenceObjectSyntax : sequenceSimpleSyntax\n                                | sequenceApplicationSyntax\"\"\"\n        # libsmi: TO DO: add to this rule conceptualTable, row, entryType\n        p[0] = p[1]\n\n    def p_valueofObjectSyntax(self, p):\n        \"\"\"valueofObjectSyntax : valueofSimpleSyntax\"\"\"\n        p[0] = p[1]\n\n    def p_SimpleSyntax(self, p):\n        \"\"\"SimpleSyntax : INTEGER\n                        | INTEGER integerSubType\n                        | INTEGER enumSpec\n                        | INTEGER32\n                        | INTEGER32 integerSubType\n                        | UPPERCASE_IDENTIFIER enumSpec\n                        | UPPERCASE_IDENTIFIER integerSubType\n                        | OCTET STRING\n                        | OCTET STRING octetStringSubType\n                        | UPPERCASE_IDENTIFIER octetStringSubType\n                        | OBJECT IDENTIFIER anySubType\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = ('SimpleSyntax', p[1])\n\n        elif n == 3:\n            if p[1] == 'OCTET':\n                p[0] = ('SimpleSyntax', p[1] + ' ' + p[2])\n            else:\n                p[0] = ('SimpleSyntax', p[1], p[2])\n\n        elif n == 4:\n            p[0] = ('SimpleSyntax', p[1] + ' ' + p[2], p[3])\n\n    def p_valueofSimpleSyntax(self, p):\n        \"\"\"valueofSimpleSyntax : NUMBER\n                               | NEGATIVENUMBER\n                               | NUMBER64\n                               | NEGATIVENUMBER64\n                               | HEX_STRING\n                               | BIN_STRING\n                               | LOWERCASE_IDENTIFIER\n                               | QUOTED_STRING\n                               | '{' objectIdentifier_defval '}'\"\"\"\n        # libsmi for objectIdentifier_defval:\n        # This is only for some MIBs with invalid numerical\n        # OID notation for DEFVALs. We DO NOT parse them\n        # correctly. We just don't want to produce a\n        # parser error.\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 4:  # XXX\n            pass\n\n    def p_sequenceSimpleSyntax(self, p):\n        \"\"\"sequenceSimpleSyntax : INTEGER anySubType\n                                | INTEGER32 anySubType\n                                | OCTET STRING anySubType\n                                | OBJECT IDENTIFIER anySubType\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1]  # XXX not supporting subtypes here\n        elif n == 4:\n            p[0] = p[1] + ' ' + p[2]  # XXX not supporting subtypes here\n\n    def p_ApplicationSyntax(self, p):\n        \"\"\"ApplicationSyntax : IPADDRESS anySubType\n                             | COUNTER32\n                             | COUNTER32 integerSubType\n                             | GAUGE32\n                             | GAUGE32 integerSubType\n                             | UNSIGNED32\n                             | UNSIGNED32 integerSubType\n                             | TIMETICKS anySubType\n                             | OPAQUE\n                             | OPAQUE octetStringSubType\n                             | COUNTER64\n                             | COUNTER64 integerSubType\"\"\"\n        # COUNTER32 and COUNTER64 was with anySubType in libsmi\n        n = len(p)\n        if n == 2:\n            p[0] = ('ApplicationSyntax', p[1])\n        elif n == 3:\n            p[0] = ('ApplicationSyntax', p[1], p[2])\n\n    def p_sequenceApplicationSyntax(self, p):\n        \"\"\"sequenceApplicationSyntax : IPADDRESS anySubType\n                                     | COUNTER32 anySubType\n                                     | GAUGE32 anySubType\n                                     | UNSIGNED32 anySubType\n                                     | TIMETICKS anySubType\n                                     | OPAQUE\n                                     | COUNTER64 anySubType\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 3:\n            p[0] = p[1]  # XXX not supporting subtypes here\n\n    def p_anySubType(self, p):\n        \"\"\"anySubType : integerSubType\n                      | octetStringSubType\n                      | enumSpec\n                      | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_integerSubType(self, p):\n        \"\"\"integerSubType : '(' ranges ')'\"\"\"\n        p[0] = ('integerSubType', p[2])\n\n    def p_octetStringSubType(self, p):\n        \"\"\"octetStringSubType : '(' SIZE '(' ranges ')' ')'\"\"\"\n        p[0] = ('octetStringSubType', p[4])\n\n    def p_ranges(self, p):\n        \"\"\"ranges : ranges '|' range\n                  | range\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_range(self, p):\n        \"\"\"range : value DOT_DOT value\n                 | value\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = (p[1],)\n        elif n == 4:\n            p[0] = (p[1], p[3])\n\n    def p_value(self, p):\n        \"\"\"value : NEGATIVENUMBER\n                 | NUMBER\n                 | NEGATIVENUMBER64\n                 | NUMBER64\n                 | HEX_STRING\n                 | BIN_STRING\"\"\"\n        p[0] = p[1]\n\n    def p_enumSpec(self, p):\n        \"\"\"enumSpec : '{' enumItems '}'\"\"\"\n        p[0] = ('enumSpec', p[2])\n\n    def p_enumItems(self, p):\n        \"\"\"enumItems : enumItems ',' enumItem\n                     | enumItem\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_enumItem(self, p):\n        \"\"\"enumItem : LOWERCASE_IDENTIFIER '(' enumNumber ')'\"\"\"\n        p[0] = (p[1], p[3])\n\n    def p_enumNumber(self, p):\n        \"\"\"enumNumber : NUMBER\n                      | NEGATIVENUMBER\"\"\"\n        # XXX              | LOWERCASE_IDENTIFIER\"\"\"\n        p[0] = p[1]\n\n    def p_Status(self, p):\n        \"\"\"Status : LOWERCASE_IDENTIFIER\"\"\"\n        p[0] = ('Status', p[1])\n\n    def p_DisplayPart(self, p):\n        \"\"\"DisplayPart : DISPLAY_HINT Text\n                       | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_UnitsPart(self, p):\n        \"\"\"UnitsPart : UNITS Text\n                     | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_Access(self, p):\n        \"\"\"Access : LOWERCASE_IDENTIFIER\"\"\"\n        p[0] = p[1]\n\n    def p_IndexPart(self, p):\n        \"\"\"IndexPart : AUGMENTS '{' Entry '}'\n                     | empty\"\"\"\n        if p[1]:\n            p[0] = p[3]\n\n    def p_MibIndex(self, p):\n        \"\"\"MibIndex : INDEX '{' IndexTypes '}'\n                    | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[3])\n\n    def p_IndexTypes(self, p):\n        \"\"\"IndexTypes : IndexTypes ',' IndexType\n                      | IndexType\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_IndexType(self, p):\n        \"\"\"IndexType : IMPLIED Index\n                     | Index\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = (0, p[1])\n        elif n == 3:\n            p[0] = (1, p[2])  # IMPLIED\n\n    def p_Index(self, p):\n        \"\"\"Index : ObjectName\"\"\"\n        # libsmi: TODO: use the SYNTAX value of the correspondent\n        #               OBJECT-TYPE invocation\n        p[0] = p[1][1][0]  # XXX just name???\n\n    def p_Entry(self, p):\n        \"\"\"Entry : ObjectName\"\"\"\n        p[0] = p[1][1][0]\n\n    def p_DefValPart(self, p):\n        \"\"\"DefValPart : DEFVAL '{' Value '}'\n                      | empty\"\"\"\n        if p[1] and p[3]:\n            p[0] = (p[1], p[3])\n\n    def p_Value(self, p):\n        \"\"\"Value : valueofObjectSyntax\n                 | '{' BitsValue '}'\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 4:\n            p[0] = p[2]\n\n    def p_BitsValue(self, p):\n        \"\"\"BitsValue : BitNames\n                     | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_BitNames(self, p):\n        \"\"\"BitNames : BitNames ',' LOWERCASE_IDENTIFIER\n                    | LOWERCASE_IDENTIFIER\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('BitNames', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('BitNames', [p[1]])\n\n    def p_ObjectName(self, p):\n        \"\"\"ObjectName : objectIdentifier\"\"\"\n        p[0] = p[1]\n\n    def p_NotificationName(self, p):\n        \"\"\"NotificationName : objectIdentifier\"\"\"\n        p[0] = p[1]\n\n    def p_ReferPart(self, p):\n        \"\"\"ReferPart : REFERENCE Text\n                     | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_RevisionPart(self, p):\n        \"\"\"RevisionPart : Revisions\n                        | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_Revisions(self, p):\n        \"\"\"Revisions : Revisions Revision\n                     | Revision\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = ('Revisions', p[1][1] + [p[2]])\n        elif n == 2:\n            p[0] = ('Revisions', [p[1]])\n\n    def p_Revision(self, p):\n        \"\"\"Revision : REVISION ExtUTCTime DESCRIPTION Text\"\"\"\n        p[0] = (p[2],  # revision time\n                (p[3], p[4]))  # description\n\n    def p_NotificationObjectsPart(self, p):\n        \"\"\"NotificationObjectsPart : OBJECTS '{' Objects '}'\n                                   | empty\"\"\"\n        p[0] = p[1] and p[3] or []\n\n    def p_ObjectGroupObjectsPart(self, p):\n        \"\"\"ObjectGroupObjectsPart : OBJECTS '{' Objects '}'\"\"\"\n        p[0] = p[3]\n\n    def p_Objects(self, p):\n        \"\"\"Objects : Objects ',' Object\n                   | Object\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('Objects', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('Objects', [p[1]])\n\n    def p_Object(self, p):\n        \"\"\"Object : ObjectName\"\"\"\n        p[0] = p[1][1][0]\n\n    def p_NotificationsPart(self, p):\n        \"\"\"NotificationsPart : NOTIFICATIONS '{' Notifications '}'\"\"\"\n        p[0] = p[3]\n\n    def p_Notifications(self, p):\n        \"\"\"Notifications : Notifications ',' Notification\n                         | Notification\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('Notifications', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('Notifications', [p[1]])\n\n    def p_Notification(self, p):\n        \"\"\"Notification : NotificationName\"\"\"\n        p[0] = p[1][1][0]\n\n    def p_Text(self, p):\n        \"\"\"Text : QUOTED_STRING\"\"\"\n        p[0] = p[1][1:-1]  # getting rid of quotes\n\n    def p_ExtUTCTime(self, p):\n        \"\"\"ExtUTCTime : QUOTED_STRING\"\"\"\n        p[0] = p[1][1:-1]  # getting rid of quotes\n\n    def p_objectIdentifier(self, p):\n        \"\"\"objectIdentifier : subidentifiers\"\"\"\n        p[0] = ('objectIdentifier', p[1])\n\n    def p_subidentifiers(self, p):\n        \"\"\"subidentifiers : subidentifiers subidentifier\n                          | subidentifier\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1] + [p[2]]\n        elif n == 2:\n            p[0] = [p[1]]\n\n    def p_subidentifier(self, p):\n        \"\"\"subidentifier : fuzzy_lowercase_identifier\n                         | NUMBER\n                         | LOWERCASE_IDENTIFIER '(' NUMBER ')'\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 5:\n            # NOTE: we are not creating new symbol p[1] because formally\n            # it is not defined in *this* MIB\n            p[0] = (p[1], p[3])\n\n    def p_objectIdentifier_defval(self, p):\n        \"\"\"objectIdentifier_defval : subidentifiers_defval\"\"\"\n        p[0] = ('objectIdentifier_defval', p[1])\n\n    def p_subidentifiers_defval(self, p):\n        \"\"\"subidentifiers_defval : subidentifiers_defval subidentifier_defval\n                                 | subidentifier_defval\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = ('subidentifiers_defval', p[1][1] + [p[2]])\n        elif n == 2:\n            p[0] = ('subidentifiers_defval', [p[1]])\n\n    def p_subidentifier_defval(self, p):\n        \"\"\"subidentifier_defval : LOWERCASE_IDENTIFIER '(' NUMBER ')'\n                                | NUMBER\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = ('subidentifier_defval', p[1])\n        elif n == 5:\n            p[0] = ('subidentifier_defval', p[1], p[3])\n\n    def p_objectGroupClause(self, p):\n        \"\"\"objectGroupClause : LOWERCASE_IDENTIFIER OBJECT_GROUP ObjectGroupObjectsPart STATUS Status DESCRIPTION Text ReferPart COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('objectGroupClause',\n                p[1],  # id\n                p[3],  # objects\n                p[5],  # status\n                (p[6], p[7]),  # description\n                p[8],  # reference\n                p[11])  # objectIdentifier\n\n    def p_notificationGroupClause(self, p):\n        \"\"\"notificationGroupClause : LOWERCASE_IDENTIFIER NOTIFICATION_GROUP NotificationsPart STATUS Status DESCRIPTION Text ReferPart COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('notificationGroupClause',\n                p[1],  # id\n                p[3],  # notifications\n                p[5],  # status\n                (p[6], p[7]),  # description\n                p[8],  # reference\n                p[11])  # objectIdentifier\n\n    def p_moduleComplianceClause(self, p):\n        \"\"\"moduleComplianceClause : LOWERCASE_IDENTIFIER MODULE_COMPLIANCE STATUS Status DESCRIPTION Text ReferPart ComplianceModulePart COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('moduleComplianceClause',\n                p[1],  # id\n                #  p[2], # MODULE_COMPLIANCE\n                p[4],  # status\n                (p[5], p[6]),  # description\n                p[7],  # reference\n                p[8],  # ComplianceModules\n                p[11])  # objectIdentifier\n\n    def p_ComplianceModulePart(self, p):\n        \"\"\"ComplianceModulePart : ComplianceModules\"\"\"\n        p[0] = p[1]\n\n    def p_ComplianceModules(self, p):\n        \"\"\"ComplianceModules : ComplianceModules ComplianceModule\n                             | ComplianceModule\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = ('ComplianceModules', p[1][1] + [p[2]])\n        elif n == 2:\n            p[0] = ('ComplianceModules', [p[1]])\n\n    def p_ComplianceModule(self, p):\n        \"\"\"ComplianceModule : MODULE ComplianceModuleName MandatoryPart CompliancePart\"\"\"\n        objects = p[3] and p[3][1] or []\n        objects += p[4] and p[4][1] or []\n        p[0] = (p[2],  # ModuleName\n                objects)  # MandatoryPart + CompliancePart\n\n    def p_ComplianceModuleName(self, p):\n        \"\"\"ComplianceModuleName : UPPERCASE_IDENTIFIER\n                                | empty\"\"\"\n        # XXX                   | UPPERCASE_IDENTIFIER objectIdentifier\n        p[0] = p[1]\n\n    def p_MandatoryPart(self, p):\n        \"\"\"MandatoryPart : MANDATORY_GROUPS '{' MandatoryGroups '}'\n                         | empty\"\"\"\n        if p[1]:\n            p[0] = p[3]\n\n    def p_MandatoryGroups(self, p):\n        \"\"\"MandatoryGroups : MandatoryGroups ',' MandatoryGroup\n                           | MandatoryGroup\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('MandatoryGroups', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('MandatoryGroups', [p[1]])\n\n    def p_MandatoryGroup(self, p):\n        \"\"\"MandatoryGroup : objectIdentifier\"\"\"\n        p[0] = p[1][1][0]  # objectIdentifier? Maybe name?\n\n    def p_CompliancePart(self, p):\n        \"\"\"CompliancePart : Compliances\n                          | empty\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_Compliances(self, p):\n        \"\"\"Compliances : Compliances Compliance\n                       | Compliance\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[1] and p[2] and ('Compliances', p[1][1] + [p[2]]) or p[1]\n        elif n == 2:\n            p[0] = p[1] and ('Compliances', [p[1]]) or None\n\n    def p_Compliance(self, p):\n        \"\"\"Compliance : ComplianceGroup\n                      | ComplianceObject\"\"\"\n        if p[1]:\n            p[0] = p[1]\n\n    def p_ComplianceGroup(self, p):\n        \"\"\"ComplianceGroup : GROUP objectIdentifier DESCRIPTION Text\"\"\"\n        p[0] = p[2][1][0]  # objectIdentifier\n        #        p[1], # GROUP\n        #        (p[3], p[4])) # description\n\n    def p_ComplianceObject(self, p):\n        \"\"\"ComplianceObject : OBJECT ObjectName SyntaxPart WriteSyntaxPart AccessPart DESCRIPTION Text\"\"\"\n        # p[0] = (p[1], # object\n        #        p[2], # name\n        #        p[3], # syntax\n        #        p[4], # write syntax\n        #        p[5], # access\n        #        (p[6], p[7])) # description\n\n    def p_SyntaxPart(self, p):\n        \"\"\"SyntaxPart : SYNTAX Syntax\n                      | empty\"\"\"\n        if p[1]:\n            p[0] = p[2]\n\n    def p_WriteSyntaxPart(self, p):\n        \"\"\"WriteSyntaxPart : WRITE_SYNTAX WriteSyntax\n                           | empty\"\"\"\n        if p[1]:\n            p[0] = p[2]\n\n    def p_WriteSyntax(self, p):\n        \"\"\"WriteSyntax : Syntax\"\"\"\n        p[0] = ('WriteSyntax', p[1])\n\n    def p_AccessPart(self, p):\n        \"\"\"AccessPart : MIN_ACCESS Access\n                      | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[2])\n\n    def p_agentCapabilitiesClause(self, p):\n        \"\"\"agentCapabilitiesClause : LOWERCASE_IDENTIFIER AGENT_CAPABILITIES PRODUCT_RELEASE Text STATUS Status DESCRIPTION Text ReferPart ModulePart_Capabilities COLON_COLON_EQUAL '{' objectIdentifier '}'\"\"\"\n        p[0] = ('agentCapabilitiesClause', p[1],  # id\n                #   p[2], # AGENT_CAPABILITIES\n                (p[3], p[4]),  # product release\n                p[6],  # status\n                (p[7], p[8]),  # description\n                p[9],  # reference\n                #   p[10], # module capabilities\n                p[13])  # objectIdentifier\n\n    def p_ModulePart_Capabilities(self, p):\n        \"\"\"ModulePart_Capabilities : Modules_Capabilities\n                                   | empty\"\"\"\n        # if p[1]:\n        #  p[0] = p[1]\n\n    def p_Modules_Capabilities(self, p):\n        \"\"\"Modules_Capabilities : Modules_Capabilities Module_Capabilities\n                                | Module_Capabilities\"\"\"\n        # n = len(p)\n        # if n == 3:\n        #  p[0] = ('Modules_Capabilities', p[1][1] + [p[2]])\n        # elif n == 2:\n        #  p[0] = ('Modules_Capabilities', [p[1]])\n\n    def p_Module_Capabilities(self, p):\n        \"\"\"Module_Capabilities : SUPPORTS ModuleName_Capabilities INCLUDES '{' CapabilitiesGroups '}' VariationPart\"\"\"\n        # p[0] = ('Module_Capabilities', (p[1], p[2]), # supports\n        #                               (p[3], p[5]), # includes\n        #                               p[7]) # variations\n\n    def p_CapabilitiesGroups(self, p):\n        \"\"\"CapabilitiesGroups : CapabilitiesGroups ',' CapabilitiesGroup\n                              | CapabilitiesGroup\"\"\"\n        # n = len(p)\n        # if n == 4:\n        #  p[0] = ('CapabilitiesGroups', p[1][1] + [p[3]])\n        # elif n == 2:\n        #  p[0] = ('CapabilitiesGroups', [p[1]])\n\n    def p_CapabilitiesGroup(self, p):\n        \"\"\"CapabilitiesGroup : objectIdentifier\"\"\"\n        # p[0] = ('CapabilitiesGroup', p[1])\n\n    def p_ModuleName_Capabilities(self, p):\n        \"\"\"ModuleName_Capabilities : UPPERCASE_IDENTIFIER objectIdentifier\n                                   | UPPERCASE_IDENTIFIER\"\"\"\n        # n = len(p)\n        # if n == 2:\n        #  p[0] = ('ModuleName_Capabilities', p[1])\n        # elif n == 3:\n        #  p[0] = ('ModuleName_Capabilities', p[1], p[2])\n\n    def p_VariationPart(self, p):\n        \"\"\"VariationPart : Variations\n                         | empty\"\"\"\n        # if p[1]:\n        #  p[0] = p[1]\n\n    def p_Variations(self, p):\n        \"\"\"Variations : Variations Variation\n                      | Variation\"\"\"\n        # n = len(p)\n        # if n == 3:\n        #  p[0] = ('Variations', p[1][1] + [p[2]])\n        # elif n == 2:\n        #  p[0] = ('Variations', [p[1]])        pass\n\n    def p_Variation(self, p):\n        \"\"\"Variation : VARIATION ObjectName SyntaxPart WriteSyntaxPart VariationAccessPart CreationPart DefValPart DESCRIPTION Text\"\"\"\n        # p[0] = (p[1], # variation\n        #        p[2], # name\n        #        p[3], # syntax\n        #        p[4], # write syntax\n        #        p[5], # access\n        #        p[6], # creation\n        #        p[7], # defval\n        #        (p[8], p[9])) # description\n\n    def p_VariationAccessPart(self, p):\n        \"\"\"VariationAccessPart : ACCESS VariationAccess\n                               | empty\"\"\"\n        # if p[1]:\n        #  p[0] = (p[1], p[2])\n\n    def p_VariationAccess(self, p):\n        \"\"\"VariationAccess : LOWERCASE_IDENTIFIER\"\"\"\n        # p[0] = p[1]\n\n    def p_CreationPart(self, p):\n        \"\"\"CreationPart : CREATION_REQUIRES '{' Cells '}'\n                        | empty\"\"\"\n        if p[1]:\n            p[0] = (p[1], p[3])\n\n    def p_Cells(self, p):\n        \"\"\"Cells : Cells ',' Cell\n                 | Cell\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = ('Cells', p[1][1] + [p[3]])\n        elif n == 2:\n            p[0] = ('Cells', [p[1]])\n\n    def p_Cell(self, p):\n        \"\"\"Cell : ObjectName\"\"\"\n        p[0] = ('Cell', p[1])\n\n    def p_empty(self, p):\n        \"\"\"empty :\"\"\"\n\n    # Error rule for syntax errors\n    def p_error(self, p):\n        if p:\n            raise error.PySmiParserError(\"Bad grammar near token type %s, value %s\" % (p.type, p.value),\n                                         lineno=p.lineno)\n\n\n#\n# Parser grammar relaxation follows.\n#\n# The classes that follow serve a purpose of encapsulating assorted functions\n# into a namespace. The namespace type is not universally supported across all\n# Python versions we want to run on, thus the hack with `staticmethod` decorator\n# and `self` first parameter.\n#\n\n#\n# SMIv1 grammar\n#\n\n# noinspection PyIncorrectDocstring\nclass SupportSmiV1Keywords(object):\n    # NETWORKADDRESS added\n    @staticmethod\n    def p_importedKeyword(self, p):\n        \"\"\"importedKeyword : importedSMIKeyword\n                           | BITS\n                           | INTEGER32\n                           | IPADDRESS\n                           | NETWORKADDRESS\n                           | MANDATORY_GROUPS\n                           | MODULE_COMPLIANCE\n                           | MODULE_IDENTITY\n                           | OBJECT_GROUP\n                           | OBJECT_IDENTITY\n                           | OBJECT_TYPE\n                           | OPAQUE\n                           | TEXTUAL_CONVENTION\n                           | TIMETICKS\n                           | UNSIGNED32\"\"\"\n        p[0] = p[1]\n\n    # NETWORKADDRESS added\n    @staticmethod\n    def p_typeSMIandSPPI(self, p):\n        \"\"\"typeSMIandSPPI : IPADDRESS\n                          | NETWORKADDRESS\n                          | TIMETICKS\n                          | OPAQUE\n                          | INTEGER32\n                          | UNSIGNED32\"\"\"\n        p[0] = p[1]\n\n    # NETWORKADDRESS added\n    @staticmethod\n    def p_ApplicationSyntax(self, p):\n        \"\"\"ApplicationSyntax : IPADDRESS anySubType\n                             | NETWORKADDRESS anySubType\n                             | COUNTER32\n                             | COUNTER32 integerSubType\n                             | GAUGE32\n                             | GAUGE32 integerSubType\n                             | UNSIGNED32\n                             | UNSIGNED32 integerSubType\n                             | TIMETICKS anySubType\n                             | OPAQUE\n                             | OPAQUE octetStringSubType\n                             | COUNTER64\n                             | COUNTER64 integerSubType\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = ('ApplicationSyntax', p[1])\n        elif n == 3:\n            p[0] = ('ApplicationSyntax', p[1], p[2])\n\n    # NETWORKADDRESS added for SEQUENCE syntax\n    @staticmethod\n    def p_sequenceApplicationSyntax(self, p):\n        \"\"\"sequenceApplicationSyntax : IPADDRESS anySubType\n                                     | NETWORKADDRESS anySubType\n                                     | COUNTER32 anySubType\n                                     | GAUGE32 anySubType\n                                     | UNSIGNED32 anySubType\n                                     | TIMETICKS anySubType\n                                     | OPAQUE\n                                     | COUNTER64 anySubType\"\"\"\n        n = len(p)\n        if n == 2:\n            p[0] = p[1]\n        elif n == 3:\n            p[0] = p[1]  # XXX not supporting subtypes here\n\n\n# noinspection PyIncorrectDocstring\nclass SupportIndex(object):\n    # SMIv1 IndexTypes added\n    @staticmethod\n    def p_Index(self, p):\n        \"\"\"Index : ObjectName\n                 | typeSMIv1\"\"\"\n\n        # libsmi: TODO: use the SYNTAX value of the correspondent\n        #               OBJECT-TYPE invocation\n        p[0] = isinstance(p[1], tuple) and p[1][1][0] or p[1]\n\n    # for Index rule\n    @staticmethod\n    def p_typeSMIv1(self, p):\n        \"\"\"typeSMIv1 : INTEGER\n                     | OCTET STRING\n                     | IPADDRESS\n                     | NETWORKADDRESS\"\"\"\n        n = len(p)\n        indextype = n == 3 and p[1] + ' ' + p[2] or p[1]\n        p[0] = indextype\n\n\n#\n# Some changes in grammar to handle common mistakes in MIBs\n#\n\n# noinspection PyIncorrectDocstring\nclass CommaInImport(object):\n    # comma at the end of import list\n    @staticmethod\n    def p_importIdentifiers(self, p):\n        \"\"\"importIdentifiers : importIdentifiers ',' importIdentifier\n                             | importIdentifier\n                             | importIdentifiers ','\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n        elif n == 3:  # excessive comma case\n            p[0] = p[1]\n\n\n# noinspection PyIncorrectDocstring\nclass CommaInSequence(object):\n    # comma at the end of sequence list\n    @staticmethod\n    def p_sequenceItems(self, p):\n        \"\"\"sequenceItems : sequenceItems ',' sequenceItem\n                         | sequenceItem\n                         | sequenceItems ','\"\"\"\n        # libsmi: TODO: might this list be emtpy?\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n        elif n == 3:  # excessive comma case\n            p[0] = p[1]\n\n\n# noinspection PyIncorrectDocstring\nclass CommaAndSpaces(object):\n    # common typos handled (mix of commas and spaces)\n    @staticmethod\n    def p_enumItems(self, p):\n        \"\"\"enumItems : enumItems ',' enumItem\n                     | enumItem\n                     | enumItems enumItem\n                     | enumItems ','\"\"\"\n        n = len(p)\n        if n == 4:\n            p[0] = p[1] + [p[3]]\n        elif n == 2:\n            p[0] = [p[1]]\n        elif n == 3:  # typo case\n            if p[2] == ',':\n                p[0] = p[1]\n            else:\n                p[0] = p[1] + [p[2]]\n\n\n# noinspection PyIncorrectDocstring\nclass UppercaseIdentifier(object):\n    # common mistake - using UPPERCASE_IDENTIFIER\n    @staticmethod\n    def p_enumItem(self, p):\n        \"\"\"enumItem : LOWERCASE_IDENTIFIER '(' enumNumber ')'\n                    | UPPERCASE_IDENTIFIER '(' enumNumber ')'\"\"\"\n        p[0] = (p[1], p[3])\n\n\n# noinspection PyIncorrectDocstring\nclass LowcaseIdentifier(object):\n    # common mistake - LOWERCASE_IDENTIFIER in symbol's name\n    @staticmethod\n    def p_notificationTypeClause(self, p):\n        \"\"\"notificationTypeClause : fuzzy_lowercase_identifier NOTIFICATION_TYPE NotificationObjectsPart STATUS Status DESCRIPTION Text ReferPart COLON_COLON_EQUAL '{' NotificationName '}'\"\"\"  # some MIBs have uppercase and/or lowercase id\n        p[0] = ('notificationTypeClause', p[1],  # id\n                #  p[2], # NOTIFICATION_TYPE\n                p[3],  # NotificationObjectsPart\n                p[5],  # status\n                (p[6], p[7]),  # description\n                p[8],   # Reference\n                p[11])  # NotificationName aka objectIdentifier\n\n\n# noinspection PyIncorrectDocstring,PyIncorrectDocstring\nclass CurlyBracesInEnterprises(object):\n    # common mistake - curly brackets around enterprise symbol\n    @staticmethod\n    def p_trapTypeClause(self, p):\n        \"\"\"trapTypeClause : fuzzy_lowercase_identifier TRAP_TYPE EnterprisePart VarPart DescrPart ReferPart COLON_COLON_EQUAL NUMBER\"\"\"\n        # libsmi: TODO: range of number?\n        p[0] = ('trapTypeClause', p[1],  # fuzzy_lowercase_identifier\n                #  p[2], # TRAP_TYPE\n                p[3],  # EnterprisePart (objectIdentifier)\n                p[4],  # VarPart\n                p[5],  # description\n                p[6],  # reference\n                p[8])  # NUMBER\n\n    @staticmethod\n    def p_EnterprisePart(self, p):\n        \"\"\"EnterprisePart : ENTERPRISE objectIdentifier\n                          | ENTERPRISE '{' objectIdentifier '}'\"\"\"\n        n = len(p)\n        if n == 3:\n            p[0] = p[2]\n        elif n == 5:  # common mistake case\n            p[0] = p[3]\n\n\n# noinspection PyIncorrectDocstring\nclass NoCells(object):\n    # common mistake - no Cells\n    @staticmethod\n    def p_CreationPart(self, p):\n        \"\"\"CreationPart : CREATION_REQUIRES '{' Cells '}'\n                        | CREATION_REQUIRES '{' '}'\n                        | empty\"\"\"\n        n = len(p)\n        if n == 5:\n            p[0] = (p[1], p[3])\n\n\nrelaxedGrammar = {\n    'supportSmiV1Keywords': [\n        SupportSmiV1Keywords.p_importedKeyword,\n        SupportSmiV1Keywords.p_typeSMIandSPPI,\n        SupportSmiV1Keywords.p_ApplicationSyntax,\n        SupportSmiV1Keywords.p_sequenceApplicationSyntax\n    ],\n    'supportIndex': [\n        SupportIndex.p_Index,\n        SupportIndex.p_typeSMIv1\n    ],\n    'commaAtTheEndOfImport': [CommaInImport.p_importIdentifiers],\n    'commaAtTheEndOfSequence': [CommaInSequence.p_sequenceItems],\n    'mixOfCommasAndSpaces': [CommaAndSpaces.p_enumItems],\n    'uppercaseIdentifier': [UppercaseIdentifier.p_enumItem],\n    'lowcaseIdentifier': [LowcaseIdentifier.p_notificationTypeClause],\n    'curlyBracesAroundEnterpriseInTrap': [\n        CurlyBracesInEnterprises.p_trapTypeClause,\n        CurlyBracesInEnterprises.p_EnterprisePart\n    ],\n    'noCells': [NoCells.p_CreationPart]\n}\n\n\ndef parserFactory(**grammarOptions):\n    \"\"\"Factory function producing custom specializations of base *SmiV2Parser*\n       class.\n\n       Keyword Args:\n           grammarOptions: a list of (bool) typed optional keyword parameters\n                           enabling particular set of SMIv2 grammar relaxations.\n\n       Returns:\n           Specialized copy of *SmiV2Parser* class.\n\n       Notes:\n           The following SMIv2 grammar relaxation parameters are defined:\n\n           * supportSmiV1Keywords - parses SMIv1 grammar\n           * supportIndex - tolerates ASN.1 types in INDEX clause\n           * commaAtTheEndOfImport - tolerates stray comma at the end of IMPORT section\n           * commaAtTheEndOfSequence - tolerates stray comma at the end of sequence of elements in MIB\n           * mixOfCommasAndSpaces - tolerate a mix of comma and spaces in MIB enumerations\n           * uppercaseIdentifier - tolerate uppercased MIB identifiers\n           * lowcaseIdentifier - tolerate lowercase MIB identifiers\n           * curlyBracesAroundEnterpriseInTrap - tolerate curly braces around enterprise ID in TRAP MACRO\n           * noCells - tolerate missing cells (XXX)\n\n       Examples:\n\n       >>> from pysmi.parser import smi\n       >>> SmiV1Parser = smi.parserFactory(supportSmiV1Keywords=True, supportIndex=True)\n\n    \"\"\"\n    classAttr = {}\n\n    for option in grammarOptions:\n        if grammarOptions[option]:\n            if option not in relaxedGrammar:\n                raise error.PySmiError('Unknown parser relaxation option: %s' % option)\n\n            for func in relaxedGrammar[option]:\n                if sys.version_info[0] > 2:\n                    classAttr[func.__name__] = func\n                else:\n                    classAttr[func.func_name] = func\n\n    classAttr['defaultLexer'] = lexerFactory(**grammarOptions)\n\n    return type('SmiParser', (SmiV2Parser,), classAttr)\n"
  },
  {
    "path": "pysmi/parser/smiv1.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.parser.dialect import smiV1\n\n# compatibility stub\nSmiV1Parser = parserFactory(**smiV1)\n"
  },
  {
    "path": "pysmi/parser/smiv1compat.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.parser.dialect import smiV1Relaxed\n\n# compatibility stub\nSmiV1CompatParser = parserFactory(**smiV1Relaxed)\nSmiStarParser = SmiV1CompatParser\n"
  },
  {
    "path": "pysmi/parser/smiv2.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.parser.dialect import smiV2\n\n# compatibility stub\nSmiV2Parser = parserFactory(**smiV2)\n"
  },
  {
    "path": "pysmi/reader/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.reader.callback import CallbackReader\nfrom pysmi.reader.ftpclient import FtpReader\nfrom pysmi.reader.httpclient import HttpReader\nfrom pysmi.reader.zipreader import ZipReader\nfrom pysmi.reader.localfile import FileReader\nfrom pysmi.reader.url import getReadersFromUrls\n"
  },
  {
    "path": "pysmi/reader/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\n\n\nclass AbstractReader(object):\n    maxMibSize = 10000000  # MIBs can't be that large\n    fuzzyMatching = True  # try different file names while searching for MIB\n    originalMatching = uppercaseMatching = lowcaseMatching = True\n    exts = ['',\n            os.path.extsep + 'txt',\n            os.path.extsep + 'mib',\n            os.path.extsep + 'my']\n    exts.extend([x.upper() for x in exts if x])\n\n    def setOptions(self, **kwargs):\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n        return self\n\n    def getMibVariants(self, mibname, **options):\n        filenames = []\n\n        if self.originalMatching:\n            filenames.append(mibname)\n\n        if self.uppercaseMatching:\n            filenames.append(mibname.upper())\n\n        if self.lowcaseMatching:\n            filenames.append(mibname.lower())\n\n        if self.fuzzyMatching:\n            part = filenames[-1].find('-mib')\n            if part != -1:\n                filenames.extend(\n                    [x[:part] for x in filenames]\n                )\n            else:\n                suffixed = mibname + '-mib'\n                filenames.append(suffixed.upper())\n                filenames.append(suffixed.lower())\n\n        return ((x, x + y) for x in filenames\n                for y in options.get('exts', self.exts))\n\n    def getData(self, filename, **options):\n        raise NotImplementedError()\n"
  },
  {
    "path": "pysmi/reader/callback.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport time\nfrom pysmi.reader.base import AbstractReader\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi import error\nfrom pysmi import debug\n\n\nclass CallbackReader(AbstractReader):\n    \"\"\"Fetch ASN.1 MIB text by name by calling user-defined callable.\n\n    *CallbackReader* class instance tries to retrieve ASN.1 MIB files\n    by name and return their contents to caller.\n    \"\"\"\n    def __init__(self, cbFun, cbCtx=None):\n        \"\"\"Create an instance of *CallbackReader* bound to specific URL.\n\n           Args:\n               cbFun (callable): user callable accepting *MIB name* and *cbCtx* objects\n\n           Keyword Args:\n               cbCtx (object): user object that can be used to communicate state information\n                   between user-scope code and the *cbFun* callable scope\n        \"\"\"\n        self._cbFun = cbFun\n        self._cbCtx = cbCtx\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._cbFun)\n\n    def getData(self, mibname, **options):\n        debug.logger & debug.flagReader and debug.logger('calling user callback %s for MIB %s' % (self._cbFun, mibname))\n\n        res = self._cbFun(mibname, self._cbCtx)\n        if res:\n            return MibInfo(path='file:///dev/stdin', file='', name=mibname, mtime=time.time()), res\n\n        raise error.PySmiReaderFileNotFoundError(mibname=mibname, reader=self)\n"
  },
  {
    "path": "pysmi/reader/ftpclient.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport time\nimport ftplib  # nosec\nfrom pysmi.reader.base import AbstractReader\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.compat import decode\nfrom pysmi import error\nfrom pysmi import debug\n\n\nclass FtpReader(AbstractReader):\n    \"\"\"Fetch ASN.1 MIB text by name from FTP server.\n       *FtpReader* class instance tries to download ASN.1 MIB files\n       by name and return their contents to caller.\n    \"\"\"\n\n    def __init__(  # nosec\n            self, host, locationTemplate, timeout=5,\n            ssl=False, port=21, user='anonymous',\n            password='anonymous@'):\n        \"\"\"Create an instance of *FtpReader* bound to specific FTP server\n           directory.\n\n           Args:\n               host (str): domain name or IP address of web server\n               locationTemplate (str): location part of the directory containing @mib@ magic placeholder to be\n                   replaced with MIB name fetch.\n\n           Keyword Args:\n               timeout (int): response timeout\n               ssl (bool): access HTTPS web site\n               port (int): TCP port web server is listening\n               user (str): username at FTP server\n               password (str): password for *username* at FTP server\n        \"\"\"\n        self._host = host\n        self._locationTemplate = locationTemplate\n        self._timeout = timeout\n        self._ssl = ssl\n        self._port = port\n        self._user = user\n        self._password = password\n        if '@mib@' not in locationTemplate:\n            raise error.PySmiError('@mib@ placeholder not specified in location at %s' % self)\n\n    def __str__(self):\n        return '%s{\"ftp://%s%s\"}' % (self.__class__.__name__, self._host, self._locationTemplate)\n\n    def getData(self, mibname, **options):\n        if self._ssl:\n            conn = ftplib.FTP_TLS()  # nosec\n        else:\n            conn = ftplib.FTP()  # nosec\n\n        try:\n            conn.connect(self._host, self._port, self._timeout)\n\n        except ftplib.all_errors:\n            raise error.PySmiReaderFileNotFoundError(\n                'failed to connect to FTP server %s:%s: %s' % (self._host, self._port, sys.exc_info()[1]), reader=self)\n\n        try:\n            conn.login(self._user, self._password)\n\n        except ftplib.all_errors:\n            conn.close()\n            raise error.PySmiReaderFileNotFoundError('failed to log in to FTP server %s:%s as %s/%s: %s' % (self._host, self._port, self._user, self._password, sys.exc_info()[1]), reader=self)\n\n        mibname = decode(mibname)\n\n        debug.logger & debug.flagReader and debug.logger('looking for MIB %s' % mibname)\n\n        for mibalias, mibfile in self.getMibVariants(mibname, **options):\n            location = self._locationTemplate.replace('@mib@', mibfile)\n\n            mtime = time.time()\n\n            debug.logger & debug.flagReader and debug.logger(\n                'trying to fetch MIB %s from %s:%s' % (location, self._host, self._port))\n\n            data = []\n\n            try:\n                try:\n                    response = conn.sendcmd('MDTM %s' % location)\n\n                except ftplib.all_errors:\n                    debug.logger & debug.flagReader and debug.logger(\n                        'server %s:%s does not support MDTM command, fetching file %s' % (\n                        self._host, self._port, location))\n\n                else:\n                    debug.logger & debug.flagReader and debug.logger(\n                        'server %s:%s MDTM response is %s' % (self._host, self._port, response))\n\n                    if response[:3] == 213:\n                        mtime = time.mktime(time.strptime(response[4:], \"%Y%m%d%H%M%S\"))\n\n                debug.logger & debug.flagReader and debug.logger('fetching source MIB %s, mtime %s' % (location, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(mtime))))\n\n                conn.retrlines('RETR %s' % location, lambda x, y=data: y.append(x))\n\n            except ftplib.all_errors:\n                debug.logger & debug.flagReader and debug.logger(\n                    'failed to fetch MIB %s from %s:%s: %s' % (location, self._host, self._port, sys.exc_info()[1]))\n                continue\n\n            data = decode('\\n'.join(data))\n\n            debug.logger & debug.flagReader and debug.logger('fetched %s bytes in %s' % (len(data), location))\n\n            conn.close()\n\n            return MibInfo(path='ftp://%s%s' % (self._host, location), file=mibfile, name=mibalias, mtime=mtime), data\n\n        conn.close()\n\n        raise error.PySmiReaderFileNotFoundError('source MIB %s not found' % mibname, reader=self)\n"
  },
  {
    "path": "pysmi/reader/httpclient.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport socket\nimport sys\nimport time\n\ntry:\n    # noinspection PyUnresolvedReferences\n    from urllib2 import Request, urlopen\nexcept ImportError:\n    # noinspection PyUnresolvedReferences\n    from urllib.request import Request\n    from urllib.request import urlopen\n\nfrom pysmi.reader.base import AbstractReader\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.compat import decode\nfrom pysmi import __version__ as pysmi_version\nfrom pysmi import error\nfrom pysmi import debug\n\n\nclass HttpReader(AbstractReader):\n    \"\"\"Fetch ASN.1 MIB text by name from a web site.\n\n    *HttpReader* class instance tries to download ASN.1 MIB files\n    by name and return their contents to caller.\n    \"\"\"\n    MIB_MAGIC = '@mib@'\n\n    def __init__(self, host, port, locationTemplate, timeout=5, ssl=False):\n        \"\"\"Create an instance of *HttpReader* bound to specific URL.\n\n           Note:\n               The `http_proxy` and `https_proxy` environment variables are\n               respected by the underlying `urllib` stdlib module.\n\n           Args:\n               host (str): domain name or IP address of web server\n               port (int): TCP port web server is listening\n               locationTemplate (str): location part of the URL optionally containing @mib@\n                   magic placeholder to be replaced with MIB name. If @mib@ magic is not present,\n                   MIB name is appended to `locationTemplate`\n\n           Keyword Args:\n               timeout (int): response timeout\n               ssl (bool): access HTTPS web site\n        \"\"\"\n        self._url = '%s://%s:%d%s' % (ssl and 'https' or 'http',\n                                      host, port, decode(locationTemplate))\n\n        socket.setdefaulttimeout(timeout)\n        self._user_agent = 'pysmi-%s; python-%s.%s.%s; %s' % (\n            pysmi_version, sys.version_info[0], sys.version_info[1],\n            sys.version_info[2], sys.platform\n        )\n\n    def __str__(self):\n        return self._url\n\n    def getData(self, mibname, **options):\n        headers = {\n            'Accept': 'text/plain',\n            'User-Agent': self._user_agent\n        }\n\n        mibname = decode(mibname)\n\n        debug.logger & debug.flagReader and debug.logger('looking for MIB %s' % mibname)\n\n        for mibalias, mibfile in self.getMibVariants(mibname, **options):\n            if self.MIB_MAGIC in self._url:\n                url = self._url.replace(self.MIB_MAGIC, mibfile)\n            else:\n                url = self._url + mibfile\n\n            debug.logger & debug.flagReader and debug.logger('trying to fetch MIB from %s' % url)\n\n            try:\n                req = Request(url, headers=headers)\n                response = urlopen(req)  # nosec\n\n            except Exception:\n                debug.logger & debug.flagReader and debug.logger('failed to fetch MIB from %s: %s' % (url, sys.exc_info()[1]))\n                continue\n\n            debug.logger & debug.flagReader and debug.logger('HTTP response %s' % response.code)\n\n            if response.code == 200:\n                try:\n                    mtime = time.mktime(time.strptime(response.getheader('Last-Modified'), \"%a, %d %b %Y %H:%M:%S %Z\"))\n\n                except Exception:\n                    debug.logger & debug.flagReader and debug.logger('malformed HTTP headers: %s' % sys.exc_info()[1])\n                    mtime = time.time()\n\n                debug.logger & debug.flagReader and debug.logger(\n                    'fetching source MIB %s, mtime %s' % (url, response.getheader('Last-Modified')))\n\n                return MibInfo(path=url, file=mibfile, name=mibalias, mtime=mtime), decode(response.read(self.maxMibSize))\n\n        raise error.PySmiReaderFileNotFoundError('source MIB %s not found' % mibname, reader=self)\n"
  },
  {
    "path": "pysmi/reader/localfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport time\nfrom pysmi.reader.base import AbstractReader\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.compat import decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass FileReader(AbstractReader):\n    \"\"\"Fetch ASN.1 MIB text by name from local file.\n\n    *FileReader* class instance tries to locate ASN.1 MIB files\n    by name, fetch and return their contents to caller.\n    \"\"\"\n    useIndexFile = True  # optional .index file mapping MIB to file name\n    indexFile = '.index'\n\n    def __init__(self, path, recursive=True, ignoreErrors=True):\n        \"\"\"Create an instance of *FileReader* serving a directory.\n\n           Args:\n               path (str): directory to search MIB files\n\n           Keyword Args:\n               recursive (bool): whether to include subdirectories\n               ignoreErrors (bool): ignore filesystem access errors\n        \"\"\"\n        self._path = os.path.normpath(path)\n        self._recursive = recursive\n        self._ignoreErrors = ignoreErrors\n        self._indexLoaded = False\n        self._mibIndex = None\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._path)\n\n    def getSubdirs(self, path, recursive=True, ignoreErrors=True):\n        if not recursive:\n            return [path]\n\n        dirs = [path]\n\n        try:\n            subdirs = os.listdir(path)\n\n        except OSError:\n            if ignoreErrors:\n                return dirs\n\n            else:\n                raise error.PySmiError('directory %s access error: %s' % (path, sys.exc_info()[1]))\n\n        for d in subdirs:\n            d = os.path.join(decode(path), decode(d))\n            if os.path.isdir(d):\n                dirs.extend(self.getSubdirs(d, recursive))\n\n        return dirs\n\n    @staticmethod\n    def loadIndex(indexFile):\n        mibIndex = {}\n        if os.path.exists(indexFile):\n            try:\n                f = open(indexFile)\n                mibIndex = dict(\n                    [x.split()[:2] for x in f.readlines()]\n                )\n                f.close()\n                debug.logger & debug.flagReader and debug.logger(\n                    'loaded MIB index map from %s file, %s entries' % (indexFile, len(mibIndex)))\n\n            except IOError:\n                pass\n\n        return mibIndex\n\n    def getMibVariants(self, mibname, **options):\n        if self.useIndexFile:\n            if not self._indexLoaded:\n                self._mibIndex = self.loadIndex(\n                    os.path.join(self._path, self.indexFile)\n                )\n                self._indexLoaded = True\n\n            if mibname in self._mibIndex:\n                debug.logger & debug.flagReader and debug.logger(\n                    'found %s in MIB index: %s' % (mibname, self._mibIndex[mibname]))\n                return [(mibname, self._mibIndex[mibname])]\n\n        return super(FileReader, self).getMibVariants(mibname, **options)\n\n    def getData(self, mibname, **options):\n        debug.logger & debug.flagReader and debug.logger(\n            '%slooking for MIB %s' % (self._recursive and 'recursively ' or '', mibname))\n\n        for path in self.getSubdirs(self._path, self._recursive, self._ignoreErrors):\n\n            for mibalias, mibfile in self.getMibVariants(mibname, **options):\n                f = os.path.join(decode(path), decode(mibfile))\n\n                debug.logger & debug.flagReader and debug.logger('trying MIB %s' % f)\n\n                if os.path.exists(f) and os.path.isfile(f):\n                    try:\n                        mtime = os.stat(f)[8]\n\n                        debug.logger & debug.flagReader and debug.logger(\n                            'source MIB %s mtime is %s, fetching data...' % (\n                                f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(mtime))))\n\n                        fp = open(f, mode='rb')\n                        mibData = fp.read(self.maxMibSize)\n                        fp.close()\n\n                        if len(mibData) == self.maxMibSize:\n                            raise IOError('MIB %s too large' % f)\n\n                        return MibInfo(path='file://%s' % f, file=mibfile, name=mibalias, mtime=mtime), decode(mibData)\n\n                    except (OSError, IOError):\n                        debug.logger & debug.flagReader and debug.logger(\n                            'source file %s open failure: %s' % (f, sys.exc_info()[1]))\n\n                        if not self._ignoreErrors:\n                            raise error.PySmiError('file %s access error: %s' % (f, sys.exc_info()[1]))\n\n                    raise error.PySmiReaderFileNotModifiedError('source MIB %s is older than needed' % f, reader=self)\n\n        raise error.PySmiReaderFileNotFoundError('source MIB %s not found' % mibname, reader=self)\n"
  },
  {
    "path": "pysmi/reader/url.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\n\ntry:\n    # noinspection PyUnresolvedReferences\n    import urlparse\n    from urllib import url2pathname\n\nexcept ImportError:\n    # noinspection PyUnresolvedReferences\n    from urllib import parse as urlparse\n    from urllib.request import url2pathname\n\nfrom pysmi.reader.localfile import FileReader\nfrom pysmi.reader.zipreader import ZipReader\nfrom pysmi.reader.httpclient import HttpReader\nfrom pysmi.reader.ftpclient import FtpReader\nfrom pysmi import error\n\n\ndef getReadersFromUrls(*sourceUrls, **options):\n    readers = []\n    for sourceUrl in sourceUrls:\n        mibSource = urlparse.urlparse(sourceUrl)\n\n        if sys.version_info[0:2] < (2, 5):\n            class ParseResult(tuple):\n                pass\n\n            mibSource = ParseResult(mibSource)\n\n            for k, v in zip(('scheme', 'netloc', 'path', 'params',\n                             'query', 'fragment', 'username', 'password',\n                             'hostname', 'port'), mibSource + ('', '', '', None)):\n                if k == 'scheme':\n                    if not mibSource[0] or mibSource[0] == 'file':\n                        if mibSource[2].endswith('.zip') or mibSource[2].endswith('.ZIP'):\n                            v = 'zip'\n\n                setattr(mibSource, k, v)\n\n        if mibSource.scheme in ('', 'file', 'zip'):\n            scheme = mibSource.scheme\n            filePath = url2pathname(mibSource.path)\n            if scheme != 'file' and (filePath.endswith('.zip') or\n                                     filePath.endswith('.ZIP')):\n                scheme = 'zip'\n\n            else:\n                scheme = 'file'\n\n            if scheme == 'file':\n                readers.append(FileReader(filePath).setOptions(**options))\n            else:\n                readers.append(ZipReader(filePath).setOptions(**options))\n\n        elif mibSource.scheme in ('http', 'https'):\n            readers.append(HttpReader(mibSource.hostname or mibSource.netloc, mibSource.port or 80, mibSource.path,\n                                      ssl=mibSource.scheme == 'https').setOptions(**options))\n\n        elif mibSource.scheme in ('ftp', 'sftp'):\n            readers.append(\n                FtpReader(mibSource.hostname or mibSource.netloc, mibSource.path, ssl=mibSource.scheme == 'sftp',\n                          port=mibSource.port or 21, user=mibSource.username or 'anonymous',\n                          password=mibSource.password or 'anonymous@').setOptions(**options))\n\n        else:\n            raise error.PySmiError('Unsupported URL scheme %s' % sourceUrl)\n\n    return readers\n"
  },
  {
    "path": "pysmi/reader/zipreader.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport time\nimport datetime\nimport zipfile\nfrom pysmi.reader.base import AbstractReader\nfrom pysmi.mibinfo import MibInfo\nfrom pysmi.compat import decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass FileLike(object):\n    \"\"\"Stripped down, binary file mock to work with ZipFile\"\"\"\n    def __init__(self, buf, name):\n        self.name = name\n        self.buf = buf\n        self.null = buf[:0]\n        self.len = len(buf)\n        self.buflist = []\n        self.pos = 0\n        self.closed = False\n        self.softspace = 0\n\n    def close(self):\n        if not self.closed:\n            self.closed = True\n            self.buf = self.null\n            self.pos = 0\n\n    def seek(self, pos, mode = 0):\n        if self.buflist:\n            self.buf += self.null.join(self.buflist)\n            self.buflist = []\n\n        if mode == 1:\n            pos += self.pos\n\n        elif mode == 2:\n            pos += self.len\n\n        self.pos = max(0, pos)\n\n    def tell(self):\n        return self.pos\n\n    def read(self, n=-1):\n        if self.buflist:\n            self.buf += self.null.join(self.buflist)\n            self.buflist = []\n\n        if n < 0:\n            newpos = self.len\n        else:\n            newpos = min(self.pos + n, self.len)\n\n        r = self.buf[self.pos:newpos]\n\n        self.pos = newpos\n\n        return r\n\n\nclass ZipReader(AbstractReader):\n    \"\"\"Fetch ASN.1 MIB text by name from a ZIP archive.\n\n    *ZipReader* class instance tries to locate ASN.1 MIB files\n    by name, fetch and return their contents to caller.\n    \"\"\"\n    useIndexFile = False\n\n    def __init__(self, path, ignoreErrors=True):\n        \"\"\"Create an instance of *ZipReader* serving a ZIP archive.\n\n           Args:\n               path (str): path to ZIP archive containing MIB files\n\n           Keyword Args:\n               ignoreErrors (bool): ignore ZIP archive access errors\n        \"\"\"\n        self._name = path\n        self._members = {}\n        self._pendingError = None\n\n        try:\n            self._members = self._readZipDirectory(fileObj=open(path, 'rb'))\n\n        except Exception:\n            debug.logger & debug.flagReader and debug.logger(\n                'ZIP file %s open failure: %s' % (self._name, sys.exc_info()[1]))\n\n            if not ignoreErrors:\n                self._pendingError = error.PySmiError('file %s access error: %s' % (self._name, sys.exc_info()[1]))\n\n    def _readZipDirectory(self, fileObj):\n\n        archive = zipfile.ZipFile(fileObj)\n\n        if isinstance(fileObj, FileLike):\n            fileObj = None\n\n        members = {}\n\n        for member in archive.infolist():\n\n            filename = os.path.basename(member.filename)\n            if not filename:\n                continue\n\n            if (member.filename.endswith('.zip') or\n                    member.filename.endswith('.ZIP')):\n\n                innerZipBlob = archive.read(member.filename)\n\n                innerMembers = self._readZipDirectory(FileLike(innerZipBlob, member.filename))\n\n                for innerFilename, ref in innerMembers.items():\n\n                    while innerFilename in members:\n                        innerFilename += '+'\n\n                    members[innerFilename] = [[fileObj, member.filename, None]]\n                    members[innerFilename].extend(ref)\n\n            else:\n                mtime = time.mktime(datetime.datetime(*member.date_time[:6]).timetuple())\n\n                members[filename] = [[fileObj, member.filename, mtime]]\n\n        return members\n\n    def _readZipFile(self, refs):\n\n        for fileObj, filename, mtime in refs:\n\n            if not fileObj:\n                fileObj = FileLike(dataObj, name=self._name)\n\n            archive = zipfile.ZipFile(fileObj)\n\n            try:\n                dataObj = archive.read(filename)\n\n            except Exception:\n                debug.logger & debug.flagReader and debug.logger('ZIP read component %s read error: %s' % (fileObj.name, sys.exc_info()[1]))\n                return '', 0\n\n        return dataObj, mtime\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._name)\n\n    def getData(self, mibname, **options):\n        debug.logger & debug.flagReader and debug.logger('looking for MIB %s at %s' % (mibname, self._name))\n\n        if self._pendingError:\n            raise self._pendingError\n\n        if not self._members:\n            raise error.PySmiReaderFileNotFoundError('source MIB %s not found' % mibname, reader=self)\n\n        for mibalias, mibfile in self.getMibVariants(mibname, **options):\n\n            debug.logger & debug.flagReader and debug.logger('trying MIB %s' % mibfile)\n\n            try:\n                refs = self._members[mibfile]\n\n            except KeyError:\n                continue\n\n            mibData, mtime = self._readZipFile(refs)\n\n            if not mibData:\n                continue\n\n            debug.logger & debug.flagReader and debug.logger(\n                'source MIB %s, mtime %s, read from %s/%s' % (mibfile, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(mtime)), self._name, mibfile)\n            )\n\n            if len(mibData) == self.maxMibSize:\n                raise IOError('MIB %s/%s too large' % (self._name, mibfile))\n\n            return MibInfo(path='zip://%s/%s' % (self._name, mibfile),\n                           file=mibfile, name=mibalias, mtime=mtime), decode(mibData)\n\n        raise error.PySmiReaderFileNotFoundError('source MIB %s not found' % mibname, reader=self)\n"
  },
  {
    "path": "pysmi/searcher/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.searcher.pyfile import PyFileSearcher\nfrom pysmi.searcher.pypackage import PyPackageSearcher\nfrom pysmi.searcher.stub import StubSearcher\nfrom pysmi.searcher.anyfile import AnyFileSearcher\n"
  },
  {
    "path": "pysmi/searcher/anyfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport time\nfrom pysmi.searcher.base import AbstractSearcher\nfrom pysmi.compat import decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass AnyFileSearcher(AbstractSearcher):\n    \"\"\"Figures out if given file exists at given location.\n    \"\"\"\n    exts = []\n\n    def __init__(self, path):\n        \"\"\"Create an instance of *AnyFileSearcher* bound to specific directory.\n\n           Args:\n             path (str): path to local directory\n        \"\"\"\n        self._path = os.path.normpath(decode(path))\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._path)\n\n    def fileExists(self, mibname, mtime, rebuild=False):\n        if rebuild:\n            debug.logger & debug.flagSearcher and debug.logger('pretend %s is very old' % mibname)\n            return\n\n        mibname = decode(mibname)\n        basename = os.path.join(self._path, mibname)\n\n        for sfx in self.exts:\n            f = basename + sfx\n            if not os.path.exists(f) or not os.path.isfile(f):\n                debug.logger & debug.flagSearcher and debug.logger('%s not present or not a file' % f)\n                continue\n\n            try:\n                fileTime = os.stat(f)[8]\n\n            except OSError:\n                raise error.PySmiSearcherError('failure opening compiled file %s: %s' % (f, sys.exc_info()[1]),\n                                               searcher=self)\n\n            debug.logger & debug.flagSearcher and debug.logger(\n                'found %s, mtime %s' % (f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(fileTime))))\n\n            if fileTime >= mtime:\n                raise error.PySmiFileNotModifiedError()\n\n        raise error.PySmiFileNotFoundError('no compiled file %s found' % mibname, searcher=self)\n"
  },
  {
    "path": "pysmi/searcher/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\n\nclass AbstractSearcher(object):\n\n    def setOptions(self, **kwargs):\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n        return self\n\n    def fileExists(self, mibname, mtime, rebuild=False):\n        raise NotImplementedError()\n"
  },
  {
    "path": "pysmi/searcher/pyfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport time\nimport struct\ntry:\n    import importlib\n\n    try:\n        PY_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER\n        SOURCE_SUFFIXES = importlib.machinery.SOURCE_SUFFIXES\n        BYTECODE_SUFFIXES = importlib.machinery.BYTECODE_SUFFIXES\n\n    except Exception:\n        raise ImportError()\n\nexcept ImportError:\n    import imp\n\n    PY_MAGIC_NUMBER = imp.get_magic()\n    SOURCE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                       if s[2] == imp.PY_SOURCE]\n    BYTECODE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                         if s[2] == imp.PY_COMPILED]\n\nfrom pysmi.searcher.base import AbstractSearcher\nfrom pysmi.compat import decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass PyFileSearcher(AbstractSearcher):\n    \"\"\"Figures out if given Python file (source or bytecode) exists at given\n       location.\n    \"\"\"\n    def __init__(self, path):\n        \"\"\"Create an instance of *PyFileSearcher* bound to specific directory.\n\n           Args:\n             path (str): path to local directory\n        \"\"\"\n        self._path = os.path.normpath(decode(path))\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._path)\n\n    def fileExists(self, mibname, mtime, rebuild=False):\n        if rebuild:\n            debug.logger & debug.flagSearcher and debug.logger('pretend %s is very old' % mibname)\n            return\n\n        mibname = decode(mibname)\n        pyfile = os.path.join(self._path, mibname)\n\n        for pySfx in BYTECODE_SUFFIXES:\n            f = pyfile + pySfx\n\n            if not os.path.exists(f) or not os.path.isfile(f):\n                debug.logger & debug.flagSearcher and debug.logger('%s not present or not a file' % f)\n                continue\n\n            try:\n                fp = open(f, 'rb')\n                pyData = fp.read(8)\n                fp.close()\n\n            except IOError:\n                raise error.PySmiSearcherError('failure opening compiled file %s: %s' % (f, sys.exc_info()[1]),\n                                               searcher=self)\n            if pyData[:4] == PY_MAGIC_NUMBER:\n                pyData = pyData[4:]\n                pyTime = struct.unpack('<L', pyData[:4])[0]\n                debug.logger & debug.flagSearcher and debug.logger(\n                    'found %s, mtime %s' % (f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(pyTime))))\n                if pyTime >= mtime:\n                    raise error.PySmiFileNotModifiedError()\n\n                else:\n                    raise error.PySmiFileNotFoundError('older file %s exists' % mibname, searcher=self)\n\n            else:\n                debug.logger & debug.flagSearcher and debug.logger('bad magic in %s' % f)\n                continue\n\n        for pySfx in SOURCE_SUFFIXES:\n            f = pyfile + pySfx\n\n            if not os.path.exists(f) or not os.path.isfile(f):\n                debug.logger & debug.flagSearcher and debug.logger('%s not present or not a file' % f)\n                continue\n\n            try:\n                pyTime = os.stat(f)[8]\n\n            except OSError:\n                raise error.PySmiSearcherError('failure opening compiled file %s: %s' % (f, sys.exc_info()[1]),\n                                               searcher=self)\n\n            debug.logger & debug.flagSearcher and debug.logger(\n                'found %s, mtime %s' % (f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(pyTime))))\n\n            if pyTime >= mtime:\n                raise error.PySmiFileNotModifiedError()\n\n        raise error.PySmiFileNotFoundError('no compiled file %s found' % mibname, searcher=self)\n"
  },
  {
    "path": "pysmi/searcher/pypackage.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport time\nimport struct\ntry:\n    import importlib\n\n    try:\n        PY_MAGIC_NUMBER = importlib.util.MAGIC_NUMBER\n        SOURCE_SUFFIXES = importlib.machinery.SOURCE_SUFFIXES\n        BYTECODE_SUFFIXES = importlib.machinery.BYTECODE_SUFFIXES\n\n    except Exception:\n        raise ImportError()\n\nexcept ImportError:\n    import imp\n\n    PY_MAGIC_NUMBER = imp.get_magic()\n    SOURCE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                       if s[2] == imp.PY_SOURCE]\n    BYTECODE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                         if s[2] == imp.PY_COMPILED]\n\nfrom pysmi.searcher.base import AbstractSearcher\nfrom pysmi.searcher.pyfile import PyFileSearcher\nfrom pysmi.compat import decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass PyPackageSearcher(AbstractSearcher):\n    \"\"\"Figures out if given Python module (source or bytecode) exists in given\n       Python package.\n\n       Python package must be importable.\n    \"\"\"\n    def __init__(self, package):\n        \"\"\"Create an instance of *PyPackageSearcher* bound to specific Python\n           package.\n\n           Args:\n               package (str): name of the Python package to look up Python\n                              modules at.\n        \"\"\"\n        self._package = package\n        self.__loader = None\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._package)\n\n    @staticmethod\n    def _parseDosTime(dosdate, dostime):\n        t = (((dosdate >> 9) & 0x7f) + 1980,  # year\n             ((dosdate >> 5) & 0x0f),  # month\n             dosdate & 0x1f,  # mday\n             (dostime >> 11) & 0x1f,  # hour\n             (dostime >> 5) & 0x3f,  # min\n             (dostime & 0x1f) * 2,  # sec\n             -1,  # wday\n             -1,  # yday\n             -1)  # dst\n        return time.mktime(t)\n\n    def fileExists(self, mibname, mtime, rebuild=False):\n        if rebuild:\n            debug.logger & debug.flagSearcher and debug.logger('pretend %s is very old' % mibname)\n            return\n\n        mibname = decode(mibname)\n\n        try:\n            p = __import__(self._package, globals(), locals(), ['__init__'])\n\n            if hasattr(p, '__loader__') and hasattr(p.__loader__, '_files'):\n                self.__loader = p.__loader__\n                self._package = self._package.replace('.', os.sep)\n                debug.logger & debug.flagSearcher and debug.logger(\n                    '%s is an importable egg at %s' % (self._package, os.path.split(p.__file__)[0]))\n\n            elif hasattr(p, '__file__'):\n                debug.logger & debug.flagSearcher and debug.logger(\n                    '%s is not an egg, trying it as a package directory' % self._package)\n                return PyFileSearcher(os.path.split(p.__file__)[0]).fileExists(mibname, mtime, rebuild=rebuild)\n\n            else:\n                raise error.PySmiFileNotFoundError('%s is neither importable nor a file' % self._package, searcher=self)\n\n        except ImportError:\n            raise error.PySmiFileNotFoundError('%s is not importable, trying as a path' % self._package, searcher=self)\n\n        for pySfx in BYTECODE_SUFFIXES:\n            f = os.path.join(self._package, mibname.upper()) + pySfx\n\n            if f not in self.__loader._files:\n                debug.logger & debug.flagSearcher and debug.logger('%s is not in %s' % (f, self._package))\n                continue\n\n            pyData = self.__loader.get_data(f)\n            if pyData[:4] == PY_MAGIC_NUMBER:\n                pyData = pyData[4:]\n                pyTime = struct.unpack('<L', pyData[:4])[0]\n                debug.logger & debug.flagSearcher and debug.logger(\n                    'found %s, mtime %s' % (f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(pyTime))))\n                if pyTime >= mtime:\n                    raise error.PySmiFileNotModifiedError()\n                else:\n                    raise error.PySmiFileNotFoundError('older file %s exists' % mibname, searcher=self)\n\n            else:\n                debug.logger & debug.flagSearcher and debug.logger('bad magic in %s' % f)\n                continue\n\n        for pySfx in SOURCE_SUFFIXES:\n\n            f = os.path.join(self._package, mibname.upper()) + pySfx\n\n            if f not in self.__loader._files:\n                debug.logger & debug.flagSearcher and debug.logger('%s is not in %s' % (f, self._package))\n                continue\n\n            pyTime = self._parseDosTime(\n                self.__loader._files[f][6],\n                self.__loader._files[f][5]\n            )\n\n            debug.logger & debug.flagSearcher and debug.logger(\n                'found %s, mtime %s' % (f, time.strftime(\"%a, %d %b %Y %H:%M:%S GMT\", time.gmtime(pyTime))))\n            if pyTime >= mtime:\n                raise error.PySmiFileNotModifiedError()\n            else:\n                raise error.PySmiFileNotFoundError('older file %s exists' % mibname, searcher=self)\n\n        raise error.PySmiFileNotFoundError('no file %s found' % mibname, searcher=self)\n"
  },
  {
    "path": "pysmi/searcher/stub.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.searcher.base import AbstractSearcher\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass StubSearcher(AbstractSearcher):\n    \"\"\"Figures out if given MIB module is present in a fixed list of modules.\n    \"\"\"\n\n    def __init__(self, *mibnames):\n        \"\"\"Create an instance of *StubSearcher* initialized with a fixed list\n           or MIB modules names.\n\n           Args:\n               mibnames (str): blacklisted MIB names\n        \"\"\"\n        self._mibnames = mibnames\n\n    def __str__(self):\n        return '%s' % self.__class__.__name__\n\n    def fileExists(self, mibname, mtime, rebuild=False):\n        if mibname in self._mibnames:\n            debug.logger & debug.flagSearcher and debug.logger('pretend compiled %s exists and is very new' % mibname)\n            raise error.PySmiFileNotModifiedError('compiled file %s is among %s' % (mibname, ', '.join(self._mibnames)),\n                                                  searcher=self)\n\n        raise error.PySmiFileNotFoundError('no compiled file %s found among %s' % (mibname, ', '.join(self._mibnames)),\n                                           searcher=self)\n"
  },
  {
    "path": "pysmi/writer/__init__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nfrom pysmi.writer.localfile import FileWriter\nfrom pysmi.writer.pyfile import PyFileWriter\nfrom pysmi.writer.callback import CallbackWriter\n"
  },
  {
    "path": "pysmi/writer/base.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\nclass AbstractWriter(object):\n    def setOptions(self, **kwargs):\n        for k in kwargs:\n            setattr(self, k, kwargs[k])\n        return self\n\n    def putData(self, mibname, data, comments=(), dryRun=False):\n        raise NotImplementedError()\n\n    def getData(self, filename):\n        raise NotImplementedError()\n"
  },
  {
    "path": "pysmi/writer/callback.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nfrom pysmi.writer.base import AbstractWriter\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass CallbackWriter(AbstractWriter):\n    \"\"\"Invokes user-specified callable and passes transformed\n       MIB module to it.\n\n       Note: user callable object signature must be as follows\n\n       .. function:: cbFun(mibname, contents, cbCtx)\n\n    \"\"\"\n\n    def __init__(self, cbFun, cbCtx=None):\n        \"\"\"Creates an instance of *CallbackWriter* class.\n\n        Args:\n            cbFun (callable): user-supplied callable\n        Keyword Args:\n            cbCtx: user-supplied object passed intact to user callback\n        \"\"\"\n        self._cbFun = cbFun\n        self._cbCtx = cbCtx\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._cbFun)\n\n    def putData(self, mibname, data, comments=(), dryRun=False):\n        if dryRun:\n            debug.logger & debug.flagWriter and debug.logger('dry run mode')\n            return\n\n        try:\n            self._cbFun(mibname, data, self._cbCtx)\n\n        except Exception:\n            raise error.PySmiWriterError(\n                'user callback %s failure writing %s: %s' % (self._cbFun, mibname, sys.exc_info()[1]), writer=self)\n\n        debug.logger & debug.flagWriter and debug.logger('user callback for %s succeeded' % mibname)\n\n    def getData(self, filename):\n        return ''\n"
  },
  {
    "path": "pysmi/writer/localfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport tempfile\nfrom pysmi.writer.base import AbstractWriter\nfrom pysmi.compat import encode, decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass FileWriter(AbstractWriter):\n    \"\"\"Stores transformed MIB modules in files at specified location.\n\n       User is expected to pass *FileReader* class instance to\n       *MibCompiler* on instantiation. The rest is internal to *MibCompiler*.\n    \"\"\"\n    suffix = ''\n\n    def __init__(self, path):\n        \"\"\"Creates an instance of *FileReader* class.\n\n           Args:\n               path: writable directory to store created files\n        \"\"\"\n        self._path = decode(os.path.normpath(path))\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._path)\n\n    def getData(self, mibname, dryRun=False):\n        filename = os.path.join(self._path, decode(mibname)) + self.suffix\n\n        f = None\n\n        try:\n            f = open(filename)\n            data = f.read()\n            f.close()\n            return data\n\n        except (OSError, IOError, UnicodeEncodeError):\n            if f:\n                f.close()\n            return ''\n\n    def putData(self, mibname, data, comments=(), dryRun=False):\n        if dryRun:\n            debug.logger & debug.flagWriter and debug.logger('dry run mode')\n            return\n\n        if not os.path.exists(self._path):\n            try:\n                os.makedirs(self._path)\n\n            except OSError:\n                raise error.PySmiWriterError(\n                    'failure creating destination directory %s: %s' % (self._path, sys.exc_info()[1]), writer=self)\n\n        if comments:\n            data = '#\\n' + ''.join(['# %s\\n' % x for x in comments]) + '#\\n' + data\n\n        filename = os.path.join(self._path, decode(mibname)) + self.suffix\n\n        tfile = None\n\n        try:\n            fd, tfile = tempfile.mkstemp(dir=self._path)\n            os.write(fd, encode(data))\n            os.close(fd)\n            os.rename(tfile, filename)\n\n        except (OSError, IOError, UnicodeEncodeError):\n            exc = sys.exc_info()\n            if tfile:\n                try:\n                    os.unlink(tfile)\n\n                except OSError:\n                    pass\n\n            raise error.PySmiWriterError('failure writing file %s: %s' % (filename, exc[1]), file=filename, writer=self)\n\n        debug.logger & debug.flagWriter and debug.logger('%s stored in %s' % (mibname, filename))\n"
  },
  {
    "path": "pysmi/writer/pyfile.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport os\nimport sys\nimport tempfile\nimport py_compile\n\ntry:\n    import importlib\n\n    try:\n        SOURCE_SUFFIXES = importlib.machinery.SOURCE_SUFFIXES\n\n    except Exception:\n        raise ImportError()\n\nexcept ImportError:\n    import imp\n\n    SOURCE_SUFFIXES = [s[0] for s in imp.get_suffixes()\n                       if s[2] == imp.PY_SOURCE]\n\nfrom pysmi.writer.base import AbstractWriter\nfrom pysmi.compat import encode, decode\nfrom pysmi import debug\nfrom pysmi import error\n\n\nclass PyFileWriter(AbstractWriter):\n    \"\"\"Stores transformed MIB modules as Python files at specified location.\n\n       User is expected to pass *PyFileWriter* class instance to\n       *MibCompiler* on instantiation. The rest is internal to *MibCompiler*.\n    \"\"\"\n    pyCompile = True\n    pyOptimizationLevel = -1\n\n    def __init__(self, path):\n        \"\"\"Creates an instance of *PyFileWriter* class.\n\n           Args:\n               path: writable directory to store Python modules\n        \"\"\"\n        self._path = decode(os.path.normpath(path))\n\n    def __str__(self):\n        return '%s{\"%s\"}' % (self.__class__.__name__, self._path)\n\n    def putData(self, mibname, data, comments=(), dryRun=False):\n        if dryRun:\n            debug.logger & debug.flagWriter and debug.logger('dry run mode')\n            return\n\n        if not os.path.exists(self._path):\n            try:\n                os.makedirs(self._path)\n\n            except OSError:\n                raise error.PySmiWriterError(\n                    'failure creating destination directory %s: %s' % (self._path, sys.exc_info()[1]), writer=self)\n\n        if comments:\n            data = '#\\n' + ''.join(['# %s\\n' % x for x in comments]) + '#\\n' + data\n\n        pyfile = os.path.join(self._path, decode(mibname))\n        pyfile += SOURCE_SUFFIXES[0]\n\n        tfile = None\n\n        try:\n            fd, tfile = tempfile.mkstemp(dir=self._path)\n            os.write(fd, encode(data))\n            os.close(fd)\n            os.rename(tfile, pyfile)\n\n        except (OSError, IOError, UnicodeEncodeError):\n            exc = sys.exc_info()\n            if tfile and os.access(tfile, os.F_OK):\n                os.unlink(tfile)\n\n            raise error.PySmiWriterError('failure writing file %s: %s' % (pyfile, exc[1]), file=pyfile, writer=self)\n\n        debug.logger & debug.flagWriter and debug.logger('created file %s' % pyfile)\n\n        if self.pyCompile:\n            try:\n                if sys.version_info[0:2] > (3, 1):\n                    # noinspection PyArgumentList\n                    py_compile.compile(pyfile, doraise=True, optimize=self.pyOptimizationLevel)\n\n                else:\n                    py_compile.compile(pyfile, doraise=True)\n\n            except (SyntaxError, py_compile.PyCompileError):\n                pass  # XXX\n\n            except Exception:\n                if pyfile and os.access(pyfile, os.F_OK):\n                    os.unlink(pyfile)\n\n                raise error.PySmiWriterError('failure compiling %s: %s' % (pyfile, sys.exc_info()[1]), file=mibname, writer=self)\n\n        debug.logger & debug.flagWriter and debug.logger('%s stored' % mibname)\n\n    def getData(self, filename):\n        return ''\n\n"
  },
  {
    "path": "requirements.txt",
    "content": "ply==3.4; python_version < '2.6'\nply; python_version >= '2.6'\nordereddict; python_version < '2.7'\nsimplejson; python_version < '2.6'\n# TODO: older Jinja does not support the options we use...\njinja2<=2.6; python_version < '2.6'\njinja2>=2.10.1; python_version >= '2.6'\n"
  },
  {
    "path": "scripts/mibcopy.py",
    "content": "#!/usr/bin/env python\n#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n# SNMP SMI/MIB copying tool\n#\nimport os\nimport sys\nimport getopt\nimport shutil\nfrom datetime import datetime\nfrom pysmi.reader import FileReader, getReadersFromUrls\nfrom pysmi.writer import CallbackWriter\nfrom pysmi.parser import SmiV1CompatParser\nfrom pysmi.codegen import JsonCodeGen\nfrom pysmi.compiler import MibCompiler\nfrom pysmi import debug\nfrom pysmi import error\n\n# sysexits.h\nEX_OK = 0\nEX_USAGE = 64\nEX_SOFTWARE = 70\n\n# Defaults\nquietFlag = False\nverboseFlag = False\nmibSources = []\ndstDirectory = None\ncacheDirectory = ''\ndryrunFlag = False\nignoreErrorsFlag = False\n\nhelpMessage = \"\"\"\\\nUsage: %s [--help]\n      [--version]\n      [--verbose]\n      [--quiet]\n      [--debug=<%s>]\n      [--mib-source=<URI>]\n      [--cache-directory=<DIRECTORY>]\n      [--ignore-errors]\n      [--dry-run]\n      <SOURCE [SOURCE...]> <DESTINATION>\nWhere:\n    URI      - file, zip, http, https, ftp, sftp schemes are supported.\n               Use @mib@ placeholder token in URI to refer directly to\n               the required MIB module when source does not support\n               directory listing (e.g. HTTP).\n\"\"\" % (\n    sys.argv[0],\n    '|'.join([x for x in sorted(debug.flagMap)])\n)\n\n# TODO(etingof): add the option to copy MIBs into enterprise-indexed subdirs\n\ntry:\n    opts, inputMibs = getopt.getopt(\n        sys.argv[1:], 'hv',\n        ['help', 'version', 'verbose', 'quiet', 'debug=',\n         'mib-source=', 'mib-stub=',\n         'cache-directory=', 'ignore-errors', 'dry-run']\n    )\n\nexcept getopt.GetoptError:\n    sys.exit(EX_USAGE)\n\nfor opt in opts:\n    if opt[0] == '-h' or opt[0] == '--help':\n        sys.stderr.write(\"\"\"\\\nSynopsis:\n  SNMP SMI/MIB files copying tool. When given MIB file(s) or directory(ies)\n  on input and a destination directory, the tool parses MIBs to figure out\n  their canonical MIB module name and the latest revision date, then\n  copies MIB module on input into the destination directory under its\n  MIB module name *if* there is no such file already or its revision date\n  is older.\n\nDocumentation:\n  http://snmplabs.com/pysmi\n%s\n\"\"\" % helpMessage)\n        sys.exit(EX_OK)\n\n    if opt[0] == '-v' or opt[0] == '--version':\n        from pysmi import __version__\n\n        sys.stderr.write(\"\"\"\\\nSNMP SMI/MIB library version %s, written by Ilya Etingof <etingof@gmail.com>\nPython interpreter: %s\nSoftware documentation and support at http://snmplabs.com/pysmi\n%s\n\"\"\" % (__version__, sys.version, helpMessage))\n        sys.exit(EX_OK)\n\n    if opt[0] == '--quiet':\n        quietFlag = True\n\n    if opt[0] == '--verbose':\n        verboseFlag = True\n\n    if opt[0] == '--debug':\n        debug.setLogger(debug.Debug(*opt[1].split(',')))\n\n    if opt[0] == '--mib-source':\n        mibSources.append(opt[1])\n\n    if opt[0] == '--cache-directory':\n        cacheDirectory = opt[1]\n\n    if opt[0] == '--ignore-errors':\n        ignoreErrorsFlag = True\n\nif not mibSources:\n    mibSources = ['file:///usr/share/snmp/mibs',\n                  'http://mibs.snmplabs.com/asn1/@mib@']\n\nif len(inputMibs) < 2:\n    sys.stderr.write('ERROR: MIB source and/or destination arguments not given\\r\\n%s\\r\\n' % helpMessage)\n    sys.exit(EX_USAGE)\n\ndstDirectory = inputMibs.pop()\n\nif os.path.exists(dstDirectory) and not os.path.isdir(dstDirectory):\n    sys.stderr.write('ERROR: given destination is not a directory\\r\\n%s\\r\\n' % helpMessage)\n    sys.exit(EX_USAGE)\n\ntry:\n    os.makedirs(dstDirectory, mode=0o755)\n\nexcept OSError:\n    pass\n\n# Compiler infrastructure\n\ncodeGenerator = JsonCodeGen()\n\nmibParser = SmiV1CompatParser(tempdir=cacheDirectory)\n\nfileWriter = CallbackWriter(lambda *x: None)\n\n\ndef getMibRevision(mibDir, mibFile):\n\n    mibCompiler = MibCompiler(\n        mibParser,\n        codeGenerator,\n        fileWriter\n    )\n\n    mibCompiler.addSources(\n        FileReader(mibDir, recursive=False, ignoreErrors=ignoreErrorsFlag),\n        *getReadersFromUrls(*mibSources)\n    )\n\n    try:\n        processed = mibCompiler.compile(\n            mibFile, **dict(noDeps=True, rebuild=True, fuzzyMatching=False, ignoreErrors=ignoreErrorsFlag)\n        )\n\n    except error.PySmiError:\n        sys.stderr.write('ERROR: %s\\r\\n' % sys.exc_info()[1])\n        sys.exit(EX_SOFTWARE)\n\n    for canonicalMibName in processed:\n        if (processed[canonicalMibName] == 'compiled' and\n                processed[canonicalMibName].path == 'file://' + os.path.join(mibDir, mibFile)):\n\n            try:\n                revision = datetime.strptime(processed[canonicalMibName].revision, '%Y-%m-%d %H:%M')\n\n            except Exception:\n                revision = datetime.fromtimestamp(0)\n\n            return canonicalMibName, revision\n\n    raise error.PySmiError('Can\\'t read or parse MIB \"%s\"' % os.path.join(mibDir, mibFile))\n\n\ndef shortenPath(path, maxLength=45):\n    if len(path) > maxLength:\n        return '...' + path[-maxLength:]\n    else:\n        return path\n\nmibsSeen = mibsCopied = mibsFailed = 0\n\nmibsRevisions = {}\n\nfor srcDirectory in inputMibs:\n\n    if verboseFlag:\n        sys.stderr.write('Reading \"%s\"...\\r\\n' % srcDirectory)\n\n    if os.path.isfile(srcDirectory):\n        mibFiles = [(os.path.abspath(os.path.dirname(srcDirectory)), os.path.basename(srcDirectory))]\n\n    else:\n        mibFiles = [(os.path.abspath(dirName), mibFile)\n                    for dirName, _, mibFiles in os.walk(srcDirectory)\n                    for mibFile in mibFiles]\n\n    for srcDirectory, mibFile in mibFiles:\n\n        mibsSeen += 1\n\n        # TODO(etingof): also check module OID to make sure there is no name collision\n\n        try:\n            mibName, srcMibRevision = getMibRevision(srcDirectory, mibFile)\n\n        except error.PySmiError as ex:\n            if verboseFlag:\n                sys.stderr.write('Failed to read source MIB \"%s\": %s\\r\\n' % (os.path.join(srcDirectory, mibFile), ex))\n\n            if not quietFlag:\n                sys.stderr.write('FAILED %s\\r\\n' % shortenPath(os.path.join(srcDirectory, mibFile)))\n\n            mibsFailed +=1\n\n            continue\n\n        if mibName in mibsRevisions:\n            dstMibRevision = mibsRevisions[mibName]\n\n        else:\n            try:\n                _, dstMibRevision = getMibRevision(dstDirectory, mibName)\n\n            except error.PySmiError as ex:\n                if verboseFlag:\n                    sys.stderr.write('MIB \"%s\" is not available at the '\n                                     'destination directory \"%s\": %s\\r\\n' % (os.path.join(srcDirectory, mibFile),\n                                                                             dstDirectory, ex))\n\n                dstMibRevision = datetime.fromtimestamp(0)\n\n            mibsRevisions[mibName] = dstMibRevision\n\n        if dstMibRevision >= srcMibRevision:\n            if verboseFlag:\n                sys.stderr.write('Destination MIB \"%s\" has the same or newer revision as the '\n                                 'source MIB \"%s\"\\r\\n' % (os.path.join(dstDirectory, mibName),\n                                                          os.path.join(srcDirectory, mibFile)))\n            if not quietFlag:\n                sys.stderr.write('NOT COPIED %s (%s)\\r\\n' % (\n                    shortenPath(os.path.join(srcDirectory, mibFile)), mibName))\n\n            continue\n\n        mibsRevisions[mibName] = srcMibRevision\n\n        if verboseFlag:\n            sys.stderr.write('Copying \"%s\" (revision \"%s\") -> \"%s\" (revision \"%s\")\\r\\n' % (\n                os.path.join(srcDirectory, mibFile), srcMibRevision,\n                os.path.join(dstDirectory, mibName), dstMibRevision))\n\n        try:\n            shutil.copy(os.path.join(srcDirectory, mibFile), os.path.join(dstDirectory, mibName))\n\n        except Exception as ex:\n            if verboseFlag:\n                sys.stderr.write('Failed to copy MIB \"%s\" -> \"%s\" (%s): \"%s\"\\r\\n' % (\n                    os.path.join(srcDirectory, mibFile), os.path.join(dstDirectory, mibName), mibName, ex))\n\n            if not quietFlag:\n                sys.stderr.write('FAILED %s (%s)\\r\\n' % (\n                    shortenPath(os.path.join(srcDirectory, mibFile)), mibName))\n\n            mibsFailed += 1\n\n        else:\n            if not quietFlag:\n                sys.stderr.write('COPIED %s (%s)\\r\\n' % (\n                    shortenPath(os.path.join(srcDirectory, mibFile)), mibName))\n\n            mibsCopied +=1\n\nif not quietFlag:\n    sys.stderr.write(\"MIBs seen: %d, copied: %d, failed: %d\\r\\n\" % (mibsSeen, mibsCopied, mibsFailed))\n\nsys.exit(EX_OK)\n"
  },
  {
    "path": "scripts/mibdump.py",
    "content": "#!/usr/bin/env python\n#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n# SNMP SMI/MIB data management tool\n#\nimport os\nimport sys\nimport getopt\nfrom pysmi.reader import getReadersFromUrls\nfrom pysmi.searcher import AnyFileSearcher, PyFileSearcher, PyPackageSearcher, StubSearcher\nfrom pysmi.borrower import AnyFileBorrower, PyFileBorrower\nfrom pysmi.writer import PyFileWriter, FileWriter, CallbackWriter\nfrom pysmi.parser import SmiV1CompatParser\nfrom pysmi.codegen import PySnmpCodeGen, JsonCodeGen, NullCodeGen\nfrom pysmi.compiler import MibCompiler\nfrom pysmi import debug\nfrom pysmi import error\n\n# sysexits.h\nEX_OK = 0\nEX_USAGE = 64\nEX_SOFTWARE = 70\nEX_MIB_MISSING = 79\nEX_MIB_FAILED = 79\n\n# Defaults\nverboseFlag = True\nmibSources = []\ndoFuzzyMatchingFlag = True\nmibSearchers = []\nmibStubs = []\nmibBorrowers = []\ndstFormat = None\ndstTemplate = None\ndstDirectory = None\ncacheDirectory = ''\nnodepsFlag = False\nrebuildFlag = False\ndryrunFlag = False\ngenMibTextsFlag = False\nkeepTextsLayout = False\npyCompileFlag = True\npyOptimizationLevel = 0\nignoreErrorsFlag = False\nbuildIndexFlag = False\nwriteMibsFlag = True\n\nhelpMessage = \"\"\"\\\nUsage: %s [--help]\n      [--version]\n      [--quiet]\n      [--debug=<%s>]\n      [--mib-source=<URI>]\n      [--mib-searcher=<PATH|PACKAGE>]\n      [--mib-stub=<MIB-NAME>]\n      [--mib-borrower=<PATH>]\n      [--destination-format=<FORMAT>]\n      [--destination-template=<PATH>]\n      [--destination-directory=<DIRECTORY>]\n      [--cache-directory=<DIRECTORY>]\n      [--disable-fuzzy-source]\n      [--no-dependencies]\n      [--no-python-compile]\n      [--python-optimization-level]\n      [--ignore-errors]\n      [--build-index]\n      [--rebuild]\n      [--dry-run]\n      [--no-mib-writes]\n      [--generate-mib-texts]\n      [--keep-texts-layout]\n      <MIB-NAME> [MIB-NAME [...]]]\nWhere:\n    URI      - file, zip, http, https, ftp, sftp schemes are supported. \n               Use @mib@ placeholder token in URI to refer directly to\n               the required MIB module when source does not support\n               directory listing (e.g. HTTP).\n    FORMAT   - pysnmp, json, null\n    TEMPLATE - path to a Jinja2 template extending the base one (see\n               documentation for details)\"\"\" % (\n    sys.argv[0],\n    '|'.join([x for x in sorted(debug.flagMap)])\n)\n\ntry:\n    opts, inputMibs = getopt.getopt(\n        sys.argv[1:], 'hv',\n        ['help', 'version', 'quiet', 'debug=',\n         'mib-source=', 'mib-searcher=', 'mib-stub=', 'mib-borrower=',\n         'destination-format=', 'destination-template=',\n         'destination-directory=', 'cache-directory=', 'no-dependencies',\n         'no-python-compile', 'python-optimization-level=', 'ignore-errors',\n         'build-index', 'rebuild', 'dry-run', 'no-mib-writes',\n         'generate-mib-texts', 'disable-fuzzy-source', 'keep-texts-layout']\n    )\n\nexcept getopt.GetoptError:\n    if verboseFlag:\n        sys.stderr.write('ERROR: %s\\r\\n%s\\r\\n' % (sys.exc_info()[1], helpMessage))\n\n    sys.exit(EX_USAGE)\n\nfor opt in opts:\n    if opt[0] == '-h' or opt[0] == '--help':\n        sys.stderr.write(\"\"\"\\\nSynopsis:\n  SNMP SMI/MIB files conversion tool\nDocumentation:\n  http://snmplabs.com/pysmi\n%s\n\"\"\" % helpMessage)\n        sys.exit(EX_OK)\n\n    if opt[0] == '-v' or opt[0] == '--version':\n        from pysmi import __version__\n\n        sys.stderr.write(\"\"\"\\\nSNMP SMI/MIB library version %s, written by Ilya Etingof <etingof@gmail.com>\nPython interpreter: %s\nSoftware documentation and support at http://snmplabs.com/pysmi\n%s\n\"\"\" % (__version__, sys.version, helpMessage))\n        sys.exit(EX_OK)\n\n    if opt[0] == '--quiet':\n        verboseFlag = False\n\n    if opt[0] == '--debug':\n        debug.setLogger(debug.Debug(*opt[1].split(',')))\n\n    if opt[0] == '--mib-source':\n        mibSources.append(opt[1])\n\n    if opt[0] == '--mib-searcher':\n        mibSearchers.append(opt[1])\n\n    if opt[0] == '--mib-stub':\n        mibStubs.append(opt[1])\n\n    if opt[0] == '--mib-borrower':\n        mibBorrowers.append((opt[1], genMibTextsFlag))\n\n    if opt[0] == '--destination-format':\n        dstFormat = opt[1]\n\n    if opt[0] == '--destination-template':\n        dstTemplate = opt[1]\n\n    if opt[0] == '--destination-directory':\n        dstDirectory = opt[1]\n\n    if opt[0] == '--cache-directory':\n        cacheDirectory = opt[1]\n\n    if opt[0] == '--no-dependencies':\n        nodepsFlag = True\n\n    if opt[0] == '--no-python-compile':\n        pyCompileFlag = False\n\n    if opt[0] == '--python-optimization-level':\n        try:\n            pyOptimizationLevel = int(opt[1])\n\n        except ValueError:\n            sys.stderr.write('ERROR: known Python optimization levels: -1, 0, 1, 2\\r\\n%s\\r\\n' % helpMessage)\n            sys.exit(EX_USAGE)\n\n    if opt[0] == '--ignore-errors':\n        ignoreErrorsFlag = True\n\n    if opt[0] == '--build-index':\n        buildIndexFlag = True\n\n    if opt[0] == '--rebuild':\n        rebuildFlag = True\n\n    if opt[0] == '--dry-run':\n        dryrunFlag = True\n\n    if opt[0] == '--no-mib-writes':\n        writeMibsFlag = False\n\n    if opt[0] == '--generate-mib-texts':\n        genMibTextsFlag = True\n\n    if opt[0] == '--disable-fuzzy-source':\n        doFuzzyMatchingFlag = False\n\n    if opt[0] == '--keep-texts-layout':\n        keepTextsLayout = True\n\nif not mibSources:\n    mibSources = ['file:///usr/share/snmp/mibs',\n                  'http://mibs.snmplabs.com/asn1/@mib@']\n\nif inputMibs:\n    mibSources = sorted(\n        set([os.path.abspath(os.path.dirname(x))\n            for x in inputMibs\n            if os.path.sep in x])\n    ) + mibSources\n\n    inputMibs = [os.path.basename(os.path.splitext(x)[0]) for x in inputMibs]\n\nif not inputMibs:\n    sys.stderr.write('ERROR: MIB modules names not specified\\r\\n%s\\r\\n' % helpMessage)\n    sys.exit(EX_USAGE)\n\nif not dstFormat:\n    dstFormat = 'pysnmp'\n\nif dstFormat == 'pysnmp':\n    if not mibSearchers:\n        mibSearchers = PySnmpCodeGen.defaultMibPackages\n\n    if not mibStubs:\n        mibStubs = [x for x in PySnmpCodeGen.baseMibs if x not in PySnmpCodeGen.fakeMibs]\n\n    if not mibBorrowers:\n        mibBorrowers = [('http://mibs.snmplabs.com/pysnmp/notexts/@mib@', False),\n                        ('http://mibs.snmplabs.com/pysnmp/fulltexts/@mib@', True)]\n\n    if not dstDirectory:\n        dstDirectory = os.path.expanduser(\"~\")\n        if sys.platform[:3] == 'win':\n            dstDirectory = os.path.join(dstDirectory, 'PySNMP Configuration', 'mibs')\n        else:\n            dstDirectory = os.path.join(dstDirectory, '.pysnmp', 'mibs')\n\n    # Compiler infrastructure\n\n    borrowers = [PyFileBorrower(x[1], genTexts=mibBorrowers[x[0]][1])\n                 for x in enumerate(getReadersFromUrls(*[m[0] for m in mibBorrowers], **dict(lowcaseMatching=False)))]\n\n    searchers = [PyFileSearcher(dstDirectory)]\n\n    for mibSearcher in mibSearchers:\n        searchers.append(PyPackageSearcher(mibSearcher))\n\n    searchers.append(StubSearcher(*mibStubs))\n\n    codeGenerator = PySnmpCodeGen()\n\n    fileWriter = PyFileWriter(dstDirectory).setOptions(pyCompile=pyCompileFlag,\n                                                       pyOptimizationLevel=pyOptimizationLevel)\n\nelif dstFormat == 'json':\n    if not mibStubs:\n        mibStubs = JsonCodeGen.baseMibs\n\n    if not mibBorrowers:\n        mibBorrowers = [('http://mibs.snmplabs.com/json/notexts/@mib@', False),\n                        ('http://mibs.snmplabs.com/json/fulltexts/@mib@', True)]\n\n    if not dstDirectory:\n        dstDirectory = os.path.join('.')\n\n    # Compiler infrastructure\n\n    borrowers = [AnyFileBorrower(x[1], genTexts=mibBorrowers[x[0]][1]).setOptions(exts=['.json'])\n                 for x in enumerate(getReadersFromUrls(*[m[0] for m in mibBorrowers], **dict(lowcaseMatching=False)))]\n\n    searchers = [AnyFileSearcher(dstDirectory).setOptions(exts=['.json']), StubSearcher(*mibStubs)]\n\n    codeGenerator = JsonCodeGen()\n\n    fileWriter = FileWriter(dstDirectory).setOptions(suffix='.json')\n\nelif dstFormat == 'null':\n    if not mibStubs:\n        mibStubs = NullCodeGen.baseMibs\n\n    if not mibBorrowers:\n        mibBorrowers = [('http://mibs.snmplabs.com/null/notexts/@mib@', False),\n                        ('http://mibs.snmplabs.com/null/fulltexts/@mib@', True)]\n\n    if not dstDirectory:\n        dstDirectory = ''\n\n    # Compiler infrastructure\n\n    codeGenerator = NullCodeGen()\n\n    searchers = [StubSearcher(*mibStubs)]\n\n    borrowers = [AnyFileBorrower(x[1], genTexts=mibBorrowers[x[0]][1])\n                 for x in enumerate(getReadersFromUrls(*[m[0] for m in mibBorrowers], **dict(lowcaseMatching=False)))]\n\n    fileWriter = CallbackWriter(lambda *x: None)\n\nelse:\n    sys.stderr.write('ERROR: unknown destination format: %s\\r\\n%s\\r\\n' % (dstFormat, helpMessage))\n    sys.exit(EX_USAGE)\n\nif verboseFlag:\n    sys.stderr.write(\"\"\"Source MIB repositories: %s\nBorrow missing/failed MIBs from: %s\nExisting/compiled MIB locations: %s\nCompiled MIBs destination directory: %s\nMIBs excluded from code generation: %s\nMIBs to compile: %s\nDestination format: %s\nCustom destination template: %s\nParser grammar cache directory: %s\nAlso compile all relevant MIBs: %s\nRebuild MIBs regardless of age: %s\nDry run mode: %s\nCreate/update MIBs: %s\nByte-compile Python modules: %s (optimization level %s)\nIgnore compilation errors: %s\nGenerate OID->MIB index: %s\nGenerate texts in MIBs: %s\nKeep original texts layout: %s\nTry various file names while searching for MIB module: %s\n\"\"\" % (', '.join(mibSources),\n       ', '.join([x[0] for x in mibBorrowers if x[1] == genMibTextsFlag]),\n       ', '.join(mibSearchers),\n       dstDirectory,\n       ', '.join(sorted(mibStubs)),\n       ', '.join(inputMibs),\n       dstFormat,\n       dstTemplate,\n       cacheDirectory or 'not used',\n       nodepsFlag and 'no' or 'yes',\n       rebuildFlag and 'yes' or 'no',\n       dryrunFlag and 'yes' or 'no',\n       writeMibsFlag and 'yes' or 'no',\n       dstFormat == 'pysnmp' and pyCompileFlag and 'yes' or 'no',\n       dstFormat == 'pysnmp' and pyOptimizationLevel and 'yes' or 'no',\n       ignoreErrorsFlag and 'yes' or 'no',\n       buildIndexFlag and 'yes' or 'no',\n       genMibTextsFlag and 'yes' or 'no',\n       keepTextsLayout and 'yes' or 'no',\n       doFuzzyMatchingFlag and 'yes' or 'no'))\n\n# Initialize compiler infrastructure\n\nmibCompiler = MibCompiler(\n    SmiV1CompatParser(tempdir=cacheDirectory),\n    codeGenerator,\n    fileWriter\n)\n\ntry:\n    mibCompiler.addSources(\n        *getReadersFromUrls(\n            *mibSources, **dict(fuzzyMatching=doFuzzyMatchingFlag)\n        )\n    )\n\n    mibCompiler.addSearchers(*searchers)\n\n    mibCompiler.addBorrowers(*borrowers)\n\n    processed = mibCompiler.compile(\n        *inputMibs, **dict(noDeps=nodepsFlag,\n                           rebuild=rebuildFlag,\n                           dryRun=dryrunFlag,\n                           dstTemplate=dstTemplate,\n                           genTexts=genMibTextsFlag,\n                           textFilter=keepTextsLayout and (lambda symbol, text: text) or None,\n                           writeMibs=writeMibsFlag,\n                           ignoreErrors=ignoreErrorsFlag)\n    )\n\n    if buildIndexFlag:\n        mibCompiler.buildIndex(\n            processed,\n            dryRun=dryrunFlag,\n            ignoreErrors=ignoreErrorsFlag\n        )\n\nexcept error.PySmiError:\n    sys.stderr.write('ERROR: %s\\r\\n' % sys.exc_info()[1])\n    sys.exit(EX_SOFTWARE)\n\nelse:\n    if verboseFlag:\n        sys.stderr.write('%sreated/updated MIBs: %s\\r\\n' % (dryrunFlag and 'Would be c' or 'C', ', '.join(\n            ['%s%s' % (x, x != processed[x].alias and ' (%s)' % processed[x].alias or '') for x in sorted(processed) if processed[x] == 'compiled'])))\n\n        sys.stderr.write('Pre-compiled MIBs %sborrowed: %s\\r\\n' % (dryrunFlag and 'Would be ' or '', ', '.join(\n            ['%s (%s)' % (x, processed[x].path) for x in sorted(processed) if processed[x] == 'borrowed'])))\n\n        sys.stderr.write(\n            'Up to date MIBs: %s\\r\\n' % ', '.join(['%s' % x for x in sorted(processed) if processed[x] == 'untouched']))\n\n        sys.stderr.write('Missing source MIBs: %s\\r\\n' % ', '.join(\n            ['%s' % x for x in sorted(processed) if processed[x] == 'missing']))\n\n        sys.stderr.write(\n            'Ignored MIBs: %s\\r\\n' % ', '.join(['%s' % x for x in sorted(processed) if processed[x] == 'unprocessed']))\n\n        sys.stderr.write('Failed MIBs: %s\\r\\n' % ', '.join(\n            ['%s (%s)' % (x, processed[x].error) for x in sorted(processed) if processed[x] == 'failed']))\n\n    exitCode = EX_OK\n\n    if any(x for x in processed.values() if x == 'missing'):\n        exitCode = EX_MIB_MISSING\n\n    if any(x for x in processed.values() if x == 'failed'):\n        exitCode = EX_MIB_FAILED\n\n    sys.exit(exitCode)\n"
  },
  {
    "path": "setup.cfg",
    "content": "[bdist_wheel]\nuniversal = 1\n\n[metadata]\nlicense_file = LICENSE.rst\n"
  },
  {
    "path": "setup.py",
    "content": "#!/usr/bin/env python\n#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\n\"\"\"SNMP SMI/MIB Parser\n\nA pure-Python implementation of SNMP/SMI MIB parsing and\nconversion library.\n\"\"\"\n\nimport os\nimport sys\n\nclassifiers = \"\"\"\\\nDevelopment Status :: 5 - Production/Stable\nEnvironment :: Console\nIntended Audience :: Developers\nIntended Audience :: Education\nIntended Audience :: Information Technology\nIntended Audience :: System Administrators\nIntended Audience :: Telecommunications Industry\nLicense :: OSI Approved :: BSD License\nNatural Language :: English\nOperating System :: OS Independent\nProgramming Language :: Python :: 2\nProgramming Language :: Python :: 2.4\nProgramming Language :: Python :: 2.5\nProgramming Language :: Python :: 2.6\nProgramming Language :: Python :: 2.7\nProgramming Language :: Python :: 3\nProgramming Language :: Python :: 3.2\nProgramming Language :: Python :: 3.3\nProgramming Language :: Python :: 3.4\nProgramming Language :: Python :: 3.5\nProgramming Language :: Python :: 3.6\nProgramming Language :: Python :: 3.7\nTopic :: Communications\nTopic :: System :: Monitoring\nTopic :: System :: Networking :: Monitoring\nTopic :: Software Development :: Libraries :: Python Modules\n\"\"\"\n\n\ndef howto_install_setuptools():\n    print(\"\"\"\n   Error: You need setuptools Python package!\n\n   It's very easy to install it, just type:\n\n   wget https://bootstrap.pypa.io/ez_setup.py\n   python ez_setup.py\n\n   Then you could make eggs from this package.\n\"\"\")\n\n\nif sys.version_info[:2] < (2, 4):\n    print(\"ERROR: this package requires Python 2.4 or later!\")\n    sys.exit(1)\n\n\ntry:\n    from setuptools import setup, Command\n\n    params = {'zip_safe': True}\n\nexcept ImportError:\n    for arg in sys.argv:\n        if 'egg' in arg:\n            howto_install_setuptools()\n            sys.exit(1)\n\n    from distutils.core import setup, Command\n\n    params = {}\n\n    if sys.version_info[:2] < (2, 6):\n        params['requires'] = ['ply(==3.4)', 'simplejson(==2.1)', 'jinja2(<=2.6)']\n    else:\n        params['requires'] = ['ply', 'jinja2(>=2.10.1)']\n\n    if sys.version_info[:2] < (2, 7):\n        params['requires'].append('ordereddict')\nelse:\n    if sys.version_info[:2] < (2, 6):\n        params['install_requires'] = ['ply==3.4', 'simplejson==2.1', 'jinja2<=2.6']\n    else:\n        params['install_requires'] = ['ply', 'jinja2>=2.10.1']\n\n    if sys.version_info[:2] < (2, 7):\n        params['install_requires'].append('ordereddict')\n\ndoclines = [x.strip() for x in (__doc__ or '').split('\\n') if x]\n\nparams.update({\n    'name': 'pysmi',\n    'version': open(os.path.join('pysmi', '__init__.py')).read().split('\\'')[1],\n    'description': doclines[0],\n    'long_description': ' '.join(doclines[1:]),\n    'maintainer': 'Ilya Etingof <etingof@gmail.com>',\n    'author': 'Ilya Etingof',\n    'author_email': 'etingof@gmail.com',\n    'url': 'https://github.com/etingof/pysmi',\n    'platforms': ['any'],\n    'classifiers': [x for x in classifiers.split('\\n') if x],\n    'license': 'BSD',\n    'packages': [\n        'pysmi',\n        'pysmi.reader',\n        'pysmi.searcher',\n        'pysmi.lexer',\n        'pysmi.parser',\n        'pysmi.codegen',\n        'pysmi.borrower',\n        'pysmi.writer'\n    ],\n    'package_data': {\n        'pysmi.codegen': [\n            'templates/*.j2',\n            'templates/*/*.j2',\n            'templates/*/*/*.j2'\n        ],\n    },\n    'scripts': [os.path.join('scripts', 'mibdump.py'),\n                os.path.join('scripts', 'mibcopy.py')]\n})\n\n# handle unittest discovery feature\nif sys.version_info[0:2] < (2, 7) or \\\n                sys.version_info[0:2] in ((3, 0), (3, 1)):\n    try:\n        import unittest2 as unittest\n    except ImportError:\n        unittest = None\nelse:\n    import unittest\n\nif unittest:\n    class PyTest(Command):\n        user_options = []\n\n        def initialize_options(self): pass\n\n        def finalize_options(self): pass\n\n        def run(self):\n            suite = unittest.defaultTestLoader.discover('tests')\n            unittest.TextTestRunner(verbosity=2).run(suite)\n\n\n    params['cmdclass'] = {'test': PyTest}\n\nsetup(**params)\n"
  },
  {
    "path": "test-requirements.txt",
    "content": "pysnmp>=4.3.10\n"
  },
  {
    "path": "tests/__init__.py",
    "content": "# This file is necessary to make this directory a package.\n"
  },
  {
    "path": "tests/__main__.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nsuite = unittest.TestLoader().loadTestsFromNames(\n    ['test_zipreader',\n     'test_agentcapabilities_smiv2_pysnmp',\n     'test_imports_smiv2_pysnmp',\n     'test_modulecompliance_smiv2_pysnmp',\n     'test_moduleidentity_smiv2_pysnmp',\n     'test_notificationgroup_smiv2_pysnmp',\n     'test_notificationtype_smiv2_pysnmp',\n     'test_objectgroup_smiv2_pysnmp',\n     'test_objectidentity_smiv2_pysnmp',\n     'test_objecttype_smiv2_pysnmp',\n     'test_smiv1_smiv2_pysnmp',\n     'test_traptype_smiv2_pysnmp',\n     'test_typedeclaration_smiv1_pysnmp',\n     'test_typedeclaration_smiv2_pysnmp',\n     'test_valuedeclaration_smiv2_pysnmp']\n)\n\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_agentcapabilities_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass AgentCapabilitiesTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n    MODULE-IDENTITY\n        FROM SNMPv2-SMI\n    AGENT-CAPABILITIES\n        FROM SNMPv2-CONF;\n\ntestCapability AGENT-CAPABILITIES\n    PRODUCT-RELEASE \"Test produce\"\n    STATUS          current\n    DESCRIPTION\n        \"test capabilities\"\n\n    SUPPORTS        TEST-MIB\n    INCLUDES        {\n                        testSystemGroup,\n                        testNotificationObjectGroup,\n                        testNotificationGroup\n                    }\n    VARIATION       testSysLevelType\n    ACCESS          read-only\n    DESCRIPTION\n        \"Not supported.\"\n\n    VARIATION       testSysLevelType\n    ACCESS          read-only\n    DESCRIPTION\n        \"Supported.\"\n\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testAgentCapabilitiesSymbol(self):\n        self.assertTrue(\n            'testCapability' in self.ctx,\n            'symbol not present'\n        )\n\n    def testAgentCapabilitiesName(self):\n        self.assertEqual(\n            self.ctx['testCapability'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testAgentCapabilitiesDescription(self):\n        self.assertEqual(\n            self.ctx['testCapability'].getDescription(),\n            'test capabilities\\n',\n            'bad DESCRIPTION'\n        )\n\n    # XXX SUPPORTS/INCLUDES/VARIATION/ACCESS not supported by pysnmp\n\n    def testAgentCapabilitiesClass(self):\n        self.assertEqual(\n            self.ctx['testCapability'].__class__.__name__,\n            'AgentCapabilities',\n            'bad SYNTAX class'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_imports_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ImportClauseTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n MODULE-IDENTITY, OBJECT-TYPE, Unsigned32, mib-2\n    FROM SNMPv2-SMI\n SnmpAdminString\n    FROM SNMP-FRAMEWORK-MIB;\n\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testModuleImportsRequiredMibs(self):\n        self.assertEqual(\n            self.mibInfo.imported,\n            ('SNMP-FRAMEWORK-MIB', 'SNMPv2-CONF', 'SNMPv2-SMI', 'SNMPv2-TC'),\n            'imported MIBs not reported'\n        )\n\n    def testModuleCheckImportedSymbol(self):\n        self.assertTrue(\n            'SnmpAdminString' in self.ctx,\n            'imported symbol not present'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_modulecompliance_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ModuleComplianceTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  MODULE-COMPLIANCE\n    FROM SNMPv2-CONF;\n\ntestCompliance MODULE-COMPLIANCE\n STATUS      current\n DESCRIPTION  \"This is the MIB compliance statement\"\n MODULE\n  MANDATORY-GROUPS {\n   testComplianceInfoGroup,\n   testNotificationInfoGroup\n  }\n  GROUP     testNotificationGroup\n  DESCRIPTION\n        \"Support for these notifications is optional.\"\n  ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testModuleComplianceSymbol(self):\n        self.assertTrue(\n            'testCompliance' in self.ctx,\n            'symbol not present'\n        )\n\n    def testModuleComplianceName(self):\n        self.assertEqual(\n            self.ctx['testCompliance'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testModuleComplianceDescription(self):\n        self.assertEqual(\n            self.ctx['testCompliance'].getDescription(),\n            'This is the MIB compliance statement\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testModuleComplianceClass(self):\n        self.assertEqual(\n            self.ctx['testCompliance'].__class__.__name__,\n            'ModuleCompliance',\n            'bad SYNTAX class'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_moduleidentity_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ModuleIdentityTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n MODULE-IDENTITY\n    FROM SNMPv2-SMI;\n\ntestModule MODULE-IDENTITY\n LAST-UPDATED \"200001100000Z\" -- Midnight 10 January 2000\n ORGANIZATION \"AgentX Working Group\"\n CONTACT-INFO \"WG-email:   agentx@dorothy.bmc.com\"\n DESCRIPTION  \"This is the MIB module for the SNMP\"\n REVISION     \"200001100000Z\" -- Midnight 10 January 2000\n DESCRIPTION  \"Initial version published as RFC 2742.\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testModuleIdentitySymbol(self):\n        self.assertTrue(\n            'testModule' in self.ctx,\n            'symbol not present'\n        )\n\n    def testModuleIdentityName(self):\n        self.assertEqual(\n            self.ctx['testModule'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testModuleIdentityLastUpdated(self):\n        self.assertEqual(\n            self.ctx['testModule'].getLastUpdated(),\n            '200001100000Z',\n            'bad LAST-UPDATED'\n        )\n\n    def testModuleIdentityOrganization(self):\n        self.assertEqual(\n            self.ctx['testModule'].getOrganization(),\n            'AgentX Working Group\\n',\n            'bad ORGANIZATION'\n        )\n\n    def testModuleIdentityRevisions(self):\n        self.assertEqual(\n            self.ctx['testModule'].getRevisions(),\n            ('2000-01-10 00:00',),\n            'bad REVISIONS'\n        )\n# TODO: pysnmp does not implement .getRevisionsDescriptions()\n#        self.assertEqual(\n#            self.ctx['testModule'].getRevisionsDescriptions(),\n#            ('Initial version published as RFC 2742.',),\n#            'bad REVISIONS'\n#        )\n\n    def testModuleIdentityContactInfo(self):\n        self.assertEqual(\n            self.ctx['testModule'].getContactInfo(),\n            'WG-email: agentx@dorothy.bmc.com\\n',\n            'bad CONTACT-INFO'\n        )\n\n    def testModuleIdentityDescription(self):\n        self.assertEqual(\n            self.ctx['testModule'].getDescription(),\n            'This is the MIB module for the SNMP\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testModuleIdentityClass(self):\n        self.assertEqual(\n            self.ctx['testModule'].__class__.__name__,\n            'ModuleIdentity',\n            'bad SYNTAX class'\n        )\n\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_notificationgroup_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass NotificationGroupTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  NOTIFICATION-GROUP\n    FROM SNMPv2-CONF;\n\ntestNotificationGroup NOTIFICATION-GROUP\n   NOTIFICATIONS    {\n                        testStatusChangeNotify,\n                        testClassEventNotify,\n                        testThresholdBelowNotify\n                    }\n    STATUS          current\n    DESCRIPTION\n        \"A collection of test notifications.\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testNotificationGroupSymbol(self):\n        self.assertTrue(\n            'testNotificationGroup' in self.ctx,\n            'symbol not present'\n        )\n\n    def testNotificationGroupName(self):\n        self.assertEqual(\n            self.ctx['testNotificationGroup'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testNotificationGroupDescription(self):\n        self.assertEqual(\n            self.ctx['testNotificationGroup'].getDescription(),\n            'A collection of test notifications.\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testNotificationGroupClass(self):\n        self.assertEqual(\n            self.ctx['testNotificationGroup'].__class__.__name__,\n            'NotificationGroup',\n            'bad SYNTAX class'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_notificationtype_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass NotificationTypeTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  NOTIFICATION-TYPE\n    FROM SNMPv2-SMI;\n\ntestNotificationType NOTIFICATION-TYPE\n   OBJECTS         {\n                        testChangeConfigType,\n                        testChangeConfigValue\n                    }\n    STATUS          current\n    DESCRIPTION\n        \"A collection of test notification types.\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testNotificationTypeSymbol(self):\n        self.assertTrue(\n            'testNotificationType' in self.ctx,\n            'symbol not present'\n        )\n\n    def testNotificationTypeName(self):\n        self.assertEqual(\n            self.ctx['testNotificationType'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testNotificationTypeDescription(self):\n        self.assertEqual(\n            self.ctx['testNotificationType'].getDescription(),\n            'A collection of test notification types.\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testNotificationTypeClass(self):\n        self.assertEqual(\n            self.ctx['testNotificationType'].__class__.__name__,\n            'NotificationType',\n            'bad SYNTAX class'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_objectgroup_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.parser.dialect import smiV2\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ObjectGroupTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-GROUP\n    FROM SNMPv2-CONF;\n\ntestObjectGroup OBJECT-GROUP\n    OBJECTS         {\n                        testStorageType,\n                        testRowStatus\n                    }\n    STATUS          current\n    DESCRIPTION\n        \"A collection of test objects.\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory(**smiV2)().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectGroupSymbol(self):\n        self.assertTrue(\n            'testObjectGroup' in self.ctx,\n            'symbol not present'\n        )\n\n    def testObjectGroupName(self):\n        self.assertEqual(\n            self.ctx['testObjectGroup'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testObjectGroupDescription(self):\n        self.assertEqual(\n            self.ctx['testObjectGroup'].getDescription(),\n            'A collection of test objects.\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testObjectGroupObjects(self):\n        self.assertEqual(\n            self.ctx['testObjectGroup'].getObjects(),\n            (('TEST-MIB', 'testStorageType'), ('TEST-MIB', 'testRowStatus')),\n            'bad OBJECTS'\n        )\n\n    def testObjectGroupClass(self):\n        self.assertEqual(\n            self.ctx['testObjectGroup'].__class__.__name__,\n            'ObjectGroup',\n            'bad SYNTAX class'\n        )\n\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_objectidentity_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ObjectIdentityTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n    OBJECT-IDENTITY\nFROM SNMPv2-SMI;\n\ntestObject OBJECT-IDENTITY\n    STATUS          current\n    DESCRIPTION     \"Initial version\"\n    REFERENCE       \"ABC\"\n\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectIdentitySymbol(self):\n        self.assertTrue(\n            'testObject' in self.ctx,\n            'symbol not present'\n        )\n\n    def testObjectIdentityName(self):\n        self.assertEqual(\n            self.ctx['testObject'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testObjectIdentityDescription(self):\n        self.assertEqual(\n            self.ctx['testObject'].getDescription(),\n            'Initial version\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testObjectIdentityReference(self):\n        self.assertEqual(\n            self.ctx['testObject'].getReference(),\n            'ABC\\n',\n            'bad REFERENCE'\n        )\n\n    def testObjectIdentityClass(self):\n        self.assertEqual(\n            self.ctx['testObject'].__class__.__name__,\n            'ObjectIdentity',\n            'bad SYNTAX class'\n        )\n\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_objecttype_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pyasn1.compat.octets import str2octs\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ObjectTypeBasicTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          Integer32\n    UNITS           \"seconds\"\n    MAX-ACCESS      accessible-for-notify\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n    REFERENCE       \"ABC\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSymbol(self):\n        self.assertTrue(\n            'testObjectType' in self.ctx,\n            'symbol not present'\n        )\n\n    def testObjectTypeName(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testObjectTypeDescription(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getDescription(),\n            'Test object\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testObjectTypeStatus(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getStatus(),\n            'current',\n            'bad STATUS'\n        )\n\n# TODO:revisit\n#    def testObjectTypeReference(self):\n#        self.assertEqual(\n#            self.ctx['testObjectType'].getReference(), str2octs('ABC'),\n#            'bad REFERENCE'\n#        )\n\n    def testObjectTypeMaxAccess(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getMaxAccess(),\n            'accessible-for-notify',\n            'bad MAX-ACCESS'\n        )\n\n    def testObjectTypeUnits(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getUnits(),\n            'seconds',\n            'bad UNITS'\n        )\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax().clone(123),\n            123,\n            'bad SYNTAX'\n        )\n\n    def testObjectTypeClass(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].__class__.__name__,\n            'MibScalar',\n            'bad SYNTAX'\n        )\n\n\nclass ObjectTypeIntegerDefaultTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE,\n  Integer32\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          Integer32\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n    DEFVAL          { 123456 }\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax(),\n            123456,\n            'bad DEFVAL'\n        )\n\n\nclass ObjectTypeEnumDefaultTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          INTEGER  {\n                        enable(1),\n                        disable(2)\n                    }\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n    DEFVAL          { enable }\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax(),\n            1,\n            'bad DEFVAL'\n        )\n\n\nclass ObjectTypeStringDefaultTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          OCTET STRING\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n    DEFVAL          { \"test value\" }\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    # TODO: pyasn1 does not like OctetString.defaultValue\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax(), str2octs('test value'),\n            'bad DEFVAL'\n        )\n\n\nclass ObjectTypeWithIntegerConstraintTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE,\n  Unsigned32\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          Unsigned32 (0..4294967295)\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n    DEFVAL          { 0 } \n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax().clone(123),\n            123,\n            'bad integer range constrained SYNTAX'\n        )\n\n\nclass ObjectTypeWithIntegerSetConstraintTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE,\n  Unsigned32\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          Unsigned32 (0|2|44)\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax().clone(44),\n            44,\n            'bad multiple integer constrained SYNTAX'\n        )\n\n\nclass ObjectTypeWithStringSizeConstraintTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE,\n  Unsigned32\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          OCTET STRING (SIZE (0..512))\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax().clone(''), str2octs(''),\n            'bad size constrained SYNTAX'\n        )\n\n\nclass ObjectTypeBitsTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE,\n  Unsigned32\n    FROM SNMPv2-SMI;\n\ntestObjectType OBJECT-TYPE\n    SYNTAX          BITS { notification(0), set(1) }\n    MAX-ACCESS      read-only\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeSyntax(self):\n        self.assertEqual(\n            self.ctx['testObjectType'].getSyntax().clone(('set',)), str2octs('@'),\n            'bad BITS SYNTAX'\n        )\n\n\nclass ObjectTypeMibTableTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\n  testTable OBJECT-TYPE\n    SYNTAX          SEQUENCE OF TestEntry \n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test table\"\n  ::= { 1 3 }\n\n  testEntry OBJECT-TYPE\n    SYNTAX          TestEntry\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test row\"\n    INDEX           { testIndex } \n  ::= { testTable 1 }\n\n  TestEntry ::= SEQUENCE {\n        testIndex   INTEGER,\n        testValue   OCTET STRING\n  }\n\n  testIndex OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 1 }\n\n  testValue OBJECT-TYPE\n    SYNTAX          OCTET STRING\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 2 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeTableClass(self):\n        self.assertEqual(\n            self.ctx['testTable'].__class__.__name__,\n            'MibTable',\n            'bad table class'\n        )\n\n    def testObjectTypeTableRowClass(self):\n        self.assertEqual(\n            self.ctx['testEntry'].__class__.__name__,\n            'MibTableRow',\n            'bad table row class'\n        )\n\n    def testObjectTypeTableColumnClass(self):\n        self.assertEqual(\n            self.ctx['testIndex'].__class__.__name__,\n            'MibTableColumn',\n            'bad table column class'\n        )\n\n    def testObjectTypeTableRowIndex(self):\n        self.assertEqual(\n            self.ctx['testEntry'].getIndexNames(),\n            ((0, 'TEST-MIB', 'testIndex'),),\n            'bad table index'\n        )\n\n\nclass ObjectTypeMibTableImpliedIndexTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\n  testTable OBJECT-TYPE\n    SYNTAX          SEQUENCE OF TestEntry \n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test table\"\n  ::= { 1 3 }\n\n  testEntry OBJECT-TYPE\n    SYNTAX          TestEntry\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test row\"\n    INDEX           { IMPLIED testIndex } \n  ::= { testTable 3 }\n\n  TestEntry ::= SEQUENCE {\n        testIndex   INTEGER\n  }\n\n  testIndex OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 1 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeTableRowIndex(self):\n        self.assertEqual(\n            self.ctx['testEntry'].getIndexNames(),\n            ((1, 'TEST-MIB', 'testIndex'),),\n            'bad IMPLIED table index'\n        )\n\n\nclass ObjectTypeMibTableMultipleIndicesTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\n  testTable OBJECT-TYPE\n    SYNTAX          SEQUENCE OF TestEntry \n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test table\"\n  ::= { 1 3 }\n\n  testEntry OBJECT-TYPE\n    SYNTAX          TestEntry\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test row\"\n    INDEX           { testIndex, testValue } \n  ::= { testTable 3 }\n\n  TestEntry ::= SEQUENCE {\n        testIndex   INTEGER,\n        testValue   OCTET STRING\n  }\n\n  testIndex OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 1 }\n\n  testValue OBJECT-TYPE\n    SYNTAX          OCTET STRING\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 2 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeTableRowIndex(self):\n        self.assertEqual(\n            self.ctx['testEntry'].getIndexNames(),\n            ((0, 'TEST-MIB', 'testIndex'), (0, 'TEST-MIB', 'testValue')),\n            'bad multiple table indices'\n        )\n\n\nclass ObjectTypeAurmentingMibTableTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\n  testTable OBJECT-TYPE\n    SYNTAX          SEQUENCE OF TestEntry \n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test table\"\n  ::= { 1 3 }\n\n  testEntry OBJECT-TYPE\n    SYNTAX          TestEntry\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test row\"\n    INDEX           { testIndex } \n  ::= { testTable 3 }\n\n  TestEntry ::= SEQUENCE {\n        testIndex   INTEGER\n  }\n\n  testIndex OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntry 1 }\n\n  testTableExt OBJECT-TYPE\n    SYNTAX          SEQUENCE OF TestEntryExt\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test table\"\n  ::= { 1 4 }\n\n  testEntryExt OBJECT-TYPE\n    SYNTAX          TestEntryExt\n    MAX-ACCESS      not-accessible\n    STATUS          current\n    DESCRIPTION     \"Test row\"\n    AUGMENTS        { testEntry }\n  ::= { testTableExt 3 }\n\n  TestEntryExt ::= SEQUENCE {\n        testIndexExt   INTEGER\n  }\n\n  testIndexExt OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      read-create\n    STATUS          current\n    DESCRIPTION     \"Test column\"\n  ::= { testEntryExt 1 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        self.ctx = {'mibBuilder': MibBuilder()}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testObjectTypeTableRowAugmention(self):\n        # TODO: provide getAugmentation() method\n        try:\n            augmentingRows = self.ctx['testEntry'].augmentingRows\n\n        except AttributeError:\n            augmentingRows = self.ctx['testEntry']._augmentingRows\n\n        self.assertEqual(\n            list(augmentingRows)[0],\n            ('TEST-MIB', 'testEntryExt'),\n            'bad AUGMENTS table clause'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_smiv1_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass SmiV1TestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\n\nIMPORTS\n    Counter, IpAddress, TimeTicks\n        FROM RFC1155-SMI\n    DisplayString, mib-2\n        FROM RFC1213-MIB\n    OBJECT-TYPE\n        FROM RFC-1212\n\n    NOTIFICATION-GROUP\n        FROM SNMPv2-CONF;\n\ntestSmiV1 NOTIFICATION-GROUP\n   NOTIFICATIONS    {\n                        testStatusChangeNotify,\n                        testClassEventNotify,\n                        testThresholdBelowNotify\n                    }\n    STATUS          current\n    DESCRIPTION\n        \"A collection of test notifications.\"\n ::= { 1 3 }\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testSmiV1Symbol(self):\n        self.assertTrue(\n            'testSmiV1' in self.ctx,\n            'symbol not present'\n        )\n\n    def testSmiV1Name(self):\n        self.assertEqual(\n            self.ctx['testSmiV1'].getName(),\n            (1, 3),\n            'bad name'\n        )\n\n    def testSmiV1Description(self):\n        self.assertEqual(\n            self.ctx['testSmiV1'].getDescription(),\n            'A collection of test notifications.\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testSmiV1Class(self):\n        self.assertEqual(\n            self.ctx['testSmiV1'].__class__.__name__,\n            'NotificationGroup',\n            'bad SYNTAX class'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_traptype_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass TrapTypeTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n  TRAP-TYPE\n    FROM RFC-1215\n\n  OBJECT-TYPE\n    FROM RFC1155-SMI;\n\ntestId  OBJECT IDENTIFIER ::= { 1 3 }\n\ntestObject OBJECT-TYPE\n    SYNTAX          INTEGER\n    MAX-ACCESS      accessible-for-notify\n    STATUS          current\n    DESCRIPTION     \"Test object\"\n ::= { 1 3 }\n\ntestTrap     TRAP-TYPE\n        ENTERPRISE  testId\n        VARIABLES { testObject }\n        DESCRIPTION\n                \"Test trap\"\n  ::= 1\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testTrapTypeSymbol(self):\n        self.assertTrue(\n            'testTrap' in self.ctx,\n            'symbol not present'\n        )\n\n    def testTrapTypeName(self):\n        self.assertEqual(\n            self.ctx['testTrap'].getName(),\n            (1, 3, 0, 1),\n            'bad name'\n        )\n\n    def testTrapTypeDescription(self):\n        self.assertEqual(\n            self.ctx['testTrap'].getDescription(),\n            'Test trap\\n',\n            'bad DESCRIPTION'\n        )\n\n    def testTrapTypeClass(self):\n        self.assertEqual(\n            self.ctx['testTrap'].__class__.__name__,\n            'NotificationType',\n            'bad SYNTAX class'\n        )\n\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_typedeclaration_smiv1_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.parser.dialect import smiV1Relaxed\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass TypeDeclarationTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n\n  NetworkAddress,\n  IpAddress,\n  Counter,\n  Gauge,\n  TimeTicks,\n  Opaque\n    FROM RFC1155-SMI;\n\n-- simple types\nTestTypeInteger ::= INTEGER\nTestTypeOctetString ::= OCTET STRING\nTestTypeObjectIdentifier ::= OBJECT IDENTIFIER\n\n-- application types\nTestTypeNetworkAddress::= NetworkAddress\nTestTypeIpAddress ::= IpAddress\nTestTypeCounter ::= Counter\nTestTypeGauge ::= Gauge\nTestTypeTimeTicks ::= TimeTicks\nTestTypeOpaque ::= Opaque\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory(**smiV1Relaxed)().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def protoTestSymbol(self, symbol, klass):\n        self.assertTrue(\n            symbol in self.ctx, 'symbol %s not present' % symbol\n        )\n\n    def protoTestClass(self, symbol, klass):\n        self.assertEqual(\n            self.ctx[symbol].__bases__[0].__name__, klass,\n            'expected class %s, got %s at %s' % (klass, self.ctx[symbol].__bases__[0].__name__, symbol)\n        )\n\n\n# populate test case class with per-type methods\n\ntypesMap = (\n    ('TestTypeInteger', 'Integer32'),\n    ('TestTypeOctetString', 'OctetString'),\n    ('TestTypeObjectIdentifier', 'ObjectIdentifier'),\n    ('TestTypeNetworkAddress', 'IpAddress'),\n    ('TestTypeIpAddress', 'IpAddress'),\n    ('TestTypeCounter', 'Counter32'),\n    ('TestTypeGauge', 'Gauge32'),\n    ('TestTypeTimeTicks', 'TimeTicks'),\n    ('TestTypeOpaque', 'Opaque')\n)\n\n\ndef decor(func, symbol, klass):\n    def inner(self):\n        func(self, symbol, klass)\n\n    return inner\n\n\nfor s, k in typesMap:\n    setattr(TypeDeclarationTestCase, 'testTypeDeclaration' + k + 'SymbolTestCase',\n            decor(TypeDeclarationTestCase.protoTestSymbol, s, k))\n    setattr(TypeDeclarationTestCase, 'testTypeDeclaration' + k + 'ClassTestCase',\n            decor(TypeDeclarationTestCase.protoTestClass, s, k))\n\n# XXX constraints flavor not checked\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_typedeclaration_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass TypeDeclarationTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n\n  IpAddress,\n  Counter32,\n  Gauge32,\n  TimeTicks,\n  Opaque,\n  Integer32,\n  Unsigned32,\n  Counter64\n    FROM SNMPv2-SMI\n\n  TEXTUAL-CONVENTION\n    FROM SNMPv2-TC;\n\n-- simple types\nTestTypeInteger ::= INTEGER\nTestTypeOctetString ::= OCTET STRING\nTestTypeObjectIdentifier ::= OBJECT IDENTIFIER\n\n-- application types\nTestTypeIpAddress ::= IpAddress\nTestTypeInteger32 ::= Integer32\nTestTypeCounter32 ::= Counter32\nTestTypeGauge32 ::= Gauge32\nTestTypeTimeTicks ::= TimeTicks\nTestTypeOpaque ::= Opaque\nTestTypeCounter64 ::= Counter64\nTestTypeUnsigned32 ::= Unsigned32\n\n-- constrained subtypes\n\nTestTypeEnum ::= INTEGER {\n                    noResponse(-1),\n                    noError(0),\n                    tooBig(1)\n                }\nTestTypeSizeRangeConstraint ::= OCTET STRING (SIZE (0..255))\nTestTypeSizeConstraint ::= OCTET STRING (SIZE (8 | 11))\nTestTypeRangeConstraint ::= INTEGER (0..2)\nTestTypeSingleValueConstraint ::= INTEGER (0|2|4)\n\nTestTypeBits ::= BITS {\n                    sunday(0),\n                    monday(1),\n                    tuesday(2),\n                    wednesday(3),\n                    thursday(4),\n                    friday(5),\n                    saturday(6)\n                }\n\n\nTestTextualConvention ::= TEXTUAL-CONVENTION\n    DISPLAY-HINT \"1x:\"\n    STATUS       current\n    DESCRIPTION\n            \"Test TC\"\n    REFERENCE\n            \"Test reference\"\n    SYNTAX       OCTET STRING\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def protoTestSymbol(self, symbol, klass):\n        self.assertTrue(\n            symbol in self.ctx, 'symbol %s not present' % symbol\n        )\n\n    def protoTestClass(self, symbol, klass):\n        self.assertEqual(\n            self.ctx[symbol].__bases__[0].__name__, klass,\n            'expected class %s, got %s at %s' % (klass, self.ctx[symbol].__bases__[0].__name__, symbol)\n        )\n\n    def TestTextualConventionSymbol(self):\n        self.assertTrue(\n            'TestTextualConvention' in self.ctx,\n            'symbol not present'\n        )\n\n    def TestTextualConventionDisplayHint(self):\n        self.assertEqual(\n            self.ctx['TestTextualConvention'].getDisplayHint(),\n            '1x:',\n            'bad DISPLAY-HINT'\n        )\n\n    def TestTextualConventionStatus(self):\n        self.assertEqual(\n            self.ctx['TestTextualConvention'].getStatus(),\n            'current',\n            'bad STATUS'\n        )\n\n    def TestTextualConventionDescription(self):\n        self.assertEqual(\n            self.ctx['TestTextualConvention'].getDescription(),\n            'Test TC\\n',\n            'bad DESCRIPTION'\n        )\n\n    def TestTextualConventionReference(self):\n        self.assertEqual(\n            self.ctx['TestTextualConvention'].getReference(),\n            'Test reference',\n            'bad REFERENCE'\n        )\n\n    def TestTextualConventionClass(self):\n        self.assertEqual(\n            self.ctx['TestTextualConvention'].__class__.__name__,\n            'TextualConvention',\n            'bad SYNTAX class'\n        )\n\n\n# populate test case class with per-type methods\n\ntypesMap = (\n    # TODO: Integer/Integer32?\n    ('TestTypeInteger', 'Integer32'),\n    ('TestTypeOctetString', 'OctetString'),\n    ('TestTypeObjectIdentifier', 'ObjectIdentifier'),\n    ('TestTypeIpAddress', 'IpAddress'),\n    ('TestTypeInteger32', 'Integer32'),\n    ('TestTypeCounter32', 'Counter32'),\n    ('TestTypeGauge32', 'Gauge32'),\n    ('TestTypeTimeTicks', 'TimeTicks'),\n    ('TestTypeOpaque', 'Opaque'),\n    ('TestTypeCounter64', 'Counter64'),\n    ('TestTypeUnsigned32', 'Unsigned32'),\n    ('TestTypeTestTypeEnum', 'Integer32'),\n    ('TestTypeSizeRangeConstraint', 'OctetString'),\n    ('TestTypeSizeConstraint', 'OctetString'),\n    ('TestTypeRangeConstraint', 'Integer32'),\n    ('TestTypeSingleValueConstraint', 'Integer32')\n)\n\n\ndef decor(func, symbol, klass):\n    def inner(self):\n        func(self, symbol, klass)\n\n    return inner\n\n\nfor s, k in typesMap:\n    setattr(TypeDeclarationTestCase, 'testTypeDeclaration' + k + 'SymbolTestCase',\n            decor(TypeDeclarationTestCase.protoTestSymbol, s, k))\n    setattr(TypeDeclarationTestCase, 'testTypeDeclaration' + k + 'ClassTestCase',\n            decor(TypeDeclarationTestCase.protoTestClass, s, k))\n\n# XXX constraints flavor not checked\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_valuedeclaration_smiv2_pysnmp.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\nfrom pysmi.parser.smi import parserFactory\nfrom pysmi.codegen.pysnmp import PySnmpCodeGen\nfrom pysmi.codegen.symtable import SymtableCodeGen\nfrom pysnmp.smi.builder import MibBuilder\n\n\nclass ValueDeclarationTestCase(unittest.TestCase):\n    \"\"\"\nTEST-MIB DEFINITIONS ::= BEGIN\nIMPORTS\n\n  OBJECT-TYPE\n    FROM SNMPv2-SMI;\n\n-- simple values\n\ntestValue1  OBJECT IDENTIFIER ::= { 1 }\ntestValue2  OBJECT IDENTIFIER ::= { testValue1 3 }\ntestValue3  OBJECT IDENTIFIER ::= { 1 3 6 1 2 }\n\n-- testValue01  INTEGER ::= 123\n-- testValue02  INTEGER ::= -123\n-- testValue04  OCTET STRING ::= h'test string'\n-- testValue05  INTEGER ::= testValue01\n-- testValue06  OCTET STRING ::= \"test string\"\n-- testValue07  OCTET STRING ::= b'010101'\n\n-- application syntax\n\n-- testValue03  Integer32 ::= 123\n-- testValue03  Counter32 ::= 123\n-- testValue03  Gauge32 ::= 123\n-- testValue03  Unsigned32 ::= 123\n-- testValue03  TimeTicks ::= 123\n-- testValue03  Opaque ::= \"0123\"\n-- testValue03  Counter64 ::= 123456789123456789\n-- testValue03  IpAddress ::= \"127.0.0.1\"\n\nEND\n \"\"\"\n\n    def setUp(self):\n        ast = parserFactory()().parse(self.__class__.__doc__)[0]\n        mibInfo, symtable = SymtableCodeGen().genCode(ast, {}, genTexts=True)\n        self.mibInfo, pycode = PySnmpCodeGen().genCode(ast, {mibInfo.name: symtable}, genTexts=True)\n        codeobj = compile(pycode, 'test', 'exec')\n\n        mibBuilder = MibBuilder()\n        mibBuilder.loadTexts = True\n\n        self.ctx = {'mibBuilder': mibBuilder}\n\n        exec(codeobj, self.ctx, self.ctx)\n\n    def testValueDeclarationSymbol(self):\n        self.assertTrue(\n            'testValue1' in self.ctx and\n            'testValue2' in self.ctx and\n            'testValue3' in self.ctx,\n            'symbol not present'\n        )\n\n    def testValueDeclarationName1(self):\n        self.assertEqual(\n            self.ctx['testValue1'].getName(),\n            (1,),\n            'bad value'\n        )\n\n    def testValueDeclarationName2(self):\n        self.assertEqual(\n            self.ctx['testValue2'].getName(),\n            (1, 3),\n            'bad value'\n        )\n\n    def testValueDeclarationName3(self):\n        self.assertEqual(\n            self.ctx['testValue3'].getName(),\n            (1, 3, 6, 1, 2),\n            'bad value'\n        )\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tests/test_zipreader.py",
    "content": "#\n# This file is part of pysmi software.\n#\n# Copyright (c) 2015-2020, Ilya Etingof <etingof@gmail.com>\n# License: http://snmplabs.com/pysmi/license.html\n#\nimport sys\nimport os\nimport tempfile\n\ntry:\n    import unittest2 as unittest\n\nexcept ImportError:\n    import unittest\n\ntry:\n    import StringIO\n\nexcept ImportError:\n    from io import StringIO\n\nfrom pysmi.reader.zipreader import ZipReader\n\n\nclass ZipReaderTestCase(unittest.TestCase):\n\n    zipArchive = [\n        80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 8, 135, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 5, 0, 28, 0, 116, 101, 115, 116, 47, 85, 84, 9, 0, 3, 16, 211, 195, 89,\n        25, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80,\n        75, 3, 4, 10, 0, 0, 0, 0, 0, 230, 134, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 12, 0, 28, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47,\n        85, 84, 9, 0, 3, 207, 210, 195, 89, 3, 211, 195, 89, 117, 120, 11, 0, 1, 4,\n        140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 230, 134,\n        53, 75, 102, 214, 67, 99, 2, 0, 0, 0, 2, 0, 0, 0, 17, 0, 28, 0, 116, 101, 115,\n        116, 47, 115, 117, 98, 100, 105, 114, 47, 116, 101, 115, 116, 65, 85, 84, 9,\n        0, 3, 207, 210, 195, 89, 3, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0,\n        0, 4, 140, 102, 0, 0, 66, 10, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 2, 135, 53, 75,\n        162, 170, 2, 92, 138, 7, 0, 0, 138, 7, 0, 0, 13, 0, 28, 0, 116, 101, 115, 116,\n        47, 116, 101, 115, 116, 46, 122, 105, 112, 85, 84, 9, 0, 3, 3, 211, 195, 89,\n        3, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80,\n        75, 3, 4, 10, 0, 0, 0, 0, 0, 253, 134, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 5, 0, 28, 0, 116, 101, 115, 116, 47, 85, 84, 9, 0, 3, 253, 210, 195, 89, 3,\n        211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75,\n        3, 4, 10, 0, 0, 0, 0, 0, 230, 134, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        12, 0, 28, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47, 85, 84,\n        9, 0, 3, 207, 210, 195, 89, 3, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102,\n        0, 0, 4, 140, 102, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 130, 131, 53, 75,\n        227, 250, 30, 37, 12, 0, 0, 0, 12, 0, 0, 0, 21, 0, 28, 0, 116, 101, 115, 116,\n        47, 115, 117, 98, 100, 105, 114, 47, 116, 101, 115, 116, 65, 46, 116, 120,\n        116, 85, 84, 9, 0, 3, 116, 204, 195, 89, 134, 204, 195, 89, 117, 120, 11, 0,\n        1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 115, 117, 98, 100, 105, 114, 116,\n        101, 115, 116, 65, 10, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 109, 131, 53, 75, 237,\n        78, 102, 83, 6, 0, 0, 0, 6, 0, 0, 0, 14, 0, 28, 0, 116, 101, 115, 116, 47,\n        116, 101, 115, 116, 65, 46, 116, 120, 116, 85, 84, 9, 0, 3, 78, 204, 195, 89,\n        134, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0,\n        116, 101, 115, 116, 65, 10, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 144, 131, 53,\n        75, 204, 176, 61, 249, 144, 2, 0, 0, 144, 2, 0, 0, 13, 0, 28, 0, 116, 101,\n        115, 116, 47, 116, 101, 115, 116, 46, 122, 105, 112, 85, 84, 9, 0, 3, 143,\n        204, 195, 89, 143, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4,\n        140, 102, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 117, 131, 53, 75, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 28, 0, 116, 101, 115, 116, 47, 85, 84, 9, 0,\n        3, 94, 204, 195, 89, 98, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0,\n        4, 140, 102, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 130, 131, 53, 75, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 28, 0, 116, 101, 115, 116, 47, 115, 117,\n        98, 100, 105, 114, 47, 85, 84, 9, 0, 3, 116, 204, 195, 89, 134, 204, 195,\n        89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 3, 4,\n        10, 0, 0, 0, 0, 0, 130, 131, 53, 75, 227, 250, 30, 37, 12, 0, 0, 0, 12, 0, 0,\n        0, 21, 0, 28, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47, 116,\n        101, 115, 116, 65, 46, 116, 120, 116, 85, 84, 9, 0, 3, 116, 204, 195, 89, 116,\n        204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 115,\n        117, 98, 100, 105, 114, 116, 101, 115, 116, 65, 10, 80, 75, 3, 4, 10, 0, 0, 0,\n        0, 0, 109, 131, 53, 75, 237, 78, 102, 83, 6, 0, 0, 0, 6, 0, 0, 0, 14, 0, 28,\n        0, 116, 101, 115, 116, 47, 116, 101, 115, 116, 65, 46, 116, 120, 116, 85, 84,\n        9, 0, 3, 78, 204, 195, 89, 78, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102,\n        0, 0, 4, 140, 102, 0, 0, 116, 101, 115, 116, 65, 10, 80, 75, 1, 2, 30, 3, 10,\n        0, 0, 0, 0, 0, 117, 131, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 24,\n        0, 0, 0, 0, 0, 0, 0, 16, 0, 253, 65, 0, 0, 0, 0, 116, 101, 115, 116, 47, 85,\n        84, 5, 0, 3, 94, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140,\n        102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 130, 131, 53, 75, 0, 0, 0,\n        0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 253, 65, 63,\n        0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47, 85, 84, 5,\n        0, 3, 116, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102,\n        0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 130, 131, 53, 75, 227, 250, 30,\n        37, 12, 0, 0, 0, 12, 0, 0, 0, 21, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 180, 129,\n        133, 0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47, 116,\n        101, 115, 116, 65, 46, 116, 120, 116, 85, 84, 5, 0, 3, 116, 204, 195, 89, 117,\n        120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10,\n        0, 0, 0, 0, 0, 109, 131, 53, 75, 237, 78, 102, 83, 6, 0, 0, 0, 6, 0, 0, 0, 14,\n        0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 180, 129, 224, 0, 0, 0, 116, 101, 115, 116,\n        47, 116, 101, 115, 116, 65, 46, 116, 120, 116, 85, 84, 5, 0, 3, 78, 204, 195,\n        89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 5, 6, 0,\n        0, 0, 0, 4, 0, 4, 0, 76, 1, 0, 0, 46, 1, 0, 0, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0,\n        0, 0, 230, 134, 53, 75, 102, 214, 67, 99, 2, 0, 0, 0, 2, 0, 0, 0, 17, 0, 28, 0,\n        116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114, 47, 116, 101, 115, 116,\n        65, 85, 84, 9, 0, 3, 207, 210, 195, 89, 207, 210, 195, 89, 117, 120, 11, 0, 1,\n        4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 66, 10, 80, 75, 3, 4, 10, 0, 0, 0, 0,\n        0, 253, 134, 53, 75, 39, 231, 88, 122, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 28, 0,\n        116, 101, 115, 116, 47, 116, 101, 115, 116, 67, 85, 84, 9, 0, 3, 253, 210,\n        195, 89, 253, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140,\n        102, 0, 0, 67, 10, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 211, 134, 53, 75, 165,\n        133, 110, 72, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 28, 0, 116, 101, 115, 116, 47,\n        116, 101, 115, 116, 65, 85, 84, 9, 0, 3, 173, 210, 195, 89, 173, 210, 195, 89,\n        117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 65, 10, 80, 75, 1,\n        2, 30, 3, 10, 0, 0, 0, 0, 0, 253, 134, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 5, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 253, 65, 0, 0, 0, 0, 116, 101, 115,\n        116, 47, 85, 84, 5, 0, 3, 253, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102,\n        0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 230, 134, 53,\n        75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16,\n        0, 253, 65, 63, 0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114,\n        47, 85, 84, 5, 0, 3, 207, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0,\n        0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 130, 131, 53,\n        75, 227, 250, 30, 37, 12, 0, 0, 0, 12, 0, 0, 0, 21, 0, 24, 0, 0, 0, 0, 0, 1,\n        0, 0, 0, 180, 129, 133, 0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100,\n        105, 114, 47, 116, 101, 115, 116, 65, 46, 116, 120, 116, 85, 84, 5, 0, 3, 116,\n        204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80,\n        75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 109, 131, 53, 75, 237, 78, 102, 83, 6, 0,\n        0, 0, 6, 0, 0, 0, 14, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 180, 129, 224, 0, 0,\n        0, 116, 101, 115, 116, 47, 116, 101, 115, 116, 65, 46, 116, 120, 116, 85, 84,\n        5, 0, 3, 78, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102,\n        0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 144, 131, 53, 75, 204, 176, 61,\n        249, 144, 2, 0, 0, 144, 2, 0, 0, 13, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180,\n        129, 46, 1, 0, 0, 116, 101, 115, 116, 47, 116, 101, 115, 116, 46, 122, 105,\n        112, 85, 84, 5, 0, 3, 143, 204, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0,\n        0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 230, 134, 53, 75,\n        102, 214, 67, 99, 2, 0, 0, 0, 2, 0, 0, 0, 17, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0,\n        0, 180, 129, 5, 4, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100, 105, 114,\n        47, 116, 101, 115, 116, 65, 85, 84, 5, 0, 3, 207, 210, 195, 89, 117, 120, 11,\n        0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0,\n        0, 0, 253, 134, 53, 75, 39, 231, 88, 122, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 24,\n        0, 0, 0, 0, 0, 1, 0, 0, 0, 180, 129, 82, 4, 0, 0, 116, 101, 115, 116, 47, 116,\n        101, 115, 116, 67, 85, 84, 5, 0, 3, 253, 210, 195, 89, 117, 120, 11, 0, 1, 4,\n        140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0,\n        211, 134, 53, 75, 165, 133, 110, 72, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 24, 0, 0,\n        0, 0, 0, 1, 0, 0, 0, 180, 129, 152, 4, 0, 0, 116, 101, 115, 116, 47, 116, 101,\n        115, 116, 65, 85, 84, 5, 0, 3, 173, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140,\n        102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 8, 0, 8, 0, 150, 2,\n        0, 0, 222, 4, 0, 0, 0, 0, 80, 75, 3, 4, 10, 0, 0, 0, 0, 0, 211, 134, 53, 75,\n        165, 133, 110, 72, 2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 28, 0, 116, 101, 115, 116,\n        47, 116, 101, 115, 116, 65, 85, 84, 9, 0, 3, 173, 210, 195, 89, 3, 211, 195,\n        89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 65, 10, 80, 75,\n        1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 8, 135, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n        0, 0, 5, 0, 24, 0, 0, 0, 0, 0, 0, 0, 16, 0, 253, 65, 0, 0, 0, 0, 116, 101,\n        115, 116, 47, 85, 84, 5, 0, 3, 16, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140,\n        102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 230,\n        134, 53, 75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 24, 0, 0, 0, 0, 0, 0,\n        0, 16, 0, 253, 65, 63, 0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98, 100,\n        105, 114, 47, 85, 84, 5, 0, 3, 207, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140,\n        102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 230,\n        134, 53, 75, 102, 214, 67, 99, 2, 0, 0, 0, 2, 0, 0, 0, 17, 0, 24, 0, 0, 0, 0,\n        0, 1, 0, 0, 0, 180, 129, 133, 0, 0, 0, 116, 101, 115, 116, 47, 115, 117, 98,\n        100, 105, 114, 47, 116, 101, 115, 116, 65, 85, 84, 5, 0, 3, 207, 210, 195,\n        89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0, 80, 75, 1, 2,\n        30, 3, 10, 0, 0, 0, 0, 0, 2, 135, 53, 75, 162, 170, 2, 92, 138, 7, 0, 0, 138,\n        7, 0, 0, 13, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180, 129, 210, 0, 0, 0, 116,\n        101, 115, 116, 47, 116, 101, 115, 116, 46, 122, 105, 112, 85, 84, 5, 0, 3,\n        3, 211, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0,\n        80, 75, 1, 2, 30, 3, 10, 0, 0, 0, 0, 0, 211, 134, 53, 75, 165, 133, 110, 72,\n        2, 0, 0, 0, 2, 0, 0, 0, 10, 0, 24, 0, 0, 0, 0, 0, 1, 0, 0, 0, 180, 129, 163,\n        8, 0, 0, 116, 101, 115, 116, 47, 116, 101, 115, 116, 65, 85, 84, 5, 0, 3,\n        173, 210, 195, 89, 117, 120, 11, 0, 1, 4, 140, 102, 0, 0, 4, 140, 102, 0, 0,\n        80, 75, 5, 6, 0, 0, 0, 0, 5, 0, 5, 0, 151, 1, 0, 0, 233, 8, 0, 0, 0, 0]\n\n\n    if sys.version_info[0] < 3:\n        zipContents = ''.join([chr(x) for x in zipArchive])\n    else:\n        zipContents = bytes(zipArchive)\n\n    def testGetDataFromFile(self):\n\n        filename = None\n\n        try:\n            fd, filename = tempfile.mkstemp()\n            os.write(fd, self.zipContents)\n            os.close(fd)\n\n            zipReader = ZipReader(filename)\n\n            mibinfo, data = zipReader.getData('testA')\n\n            assert data == 'A\\n'\n\n        except Exception:\n            pass\n\n        if filename:\n            try:\n                os.remove(filename)\n\n            except Exception:\n                pass\n\n    def testGetInnerZipData(self):\n        filename = None\n\n        try:\n            fd, filename = tempfile.mkstemp()\n            os.write(fd, self.zipContents)\n            os.close(fd)\n\n            zipReader = ZipReader(filename)\n\n            mibinfo, data = zipReader.getData('testC')\n\n            assert data == 'C\\n'\n\n        except Exception:\n            pass\n\n        if filename:\n            try:\n                os.remove(filename)\n\n            except Exception:\n                pass\n\nsuite = unittest.TestLoader().loadTestsFromModule(sys.modules[__name__])\n\nif __name__ == '__main__':\n    unittest.TextTestRunner(verbosity=2).run(suite)\n"
  },
  {
    "path": "tox.ini",
    "content": "[tox]\nminversion = 3.4.0\nskip_missing_interpreters = true\nenvlist =\n    {py27, py35, py36, py37, py38}-{unittest},\n    cover, docs, bandit, build\n\n[testenv]\nusedevelop = True\nsetenv =\n   VIRTUAL_ENV={envdir}\n   PYTHONWARNINGS=default::DeprecationWarning\ndeps = pip >= 19.3.1\ninstall_command =\n    pip install {opts} {packages}\n\n[testenv:unittest]\ndeps =\n    discover\n    {[testenv]deps}\n    -r{toxinidir}/devel-requirements.txt\n    -r{toxinidir}/requirements.txt\ncommands =\n    discover -s tests\n\n[testenv:py27-unittest]\ndeps = {[testenv:unittest]deps}\ncommands = {[testenv:unittest]commands}\n\n[testenv:py35-unittest]\ndeps = {[testenv:unittest]deps}\ncommands = {[testenv:unittest]commands}\n\n[testenv:py36-unittest]\ndeps = {[testenv:unittest]deps}\ncommands = {[testenv:unittest]commands}\n\n[testenv:py37-unittest]\ndeps = {[testenv:unittest]deps}\ncommands = {[testenv:unittest]commands}\n\n[testenv:py38-unittest]\ndeps = {[testenv:unittest]deps}\ncommands = {[testenv:unittest]commands}\n\n[testenv:flake8]\nbasepython=python3\nskip_install = true\ndeps =\n    flake8\n#    flake8-bugbear\n#    flake8-colors\n#    flake8-docstrings\n    flake8-import-order\n#    flake8-typing-imports\n#    pep8-naming\ncommands =\n    flake8 --config .flake8.ini --count --import-order-style pep8 --application-import-names pysmi pysmi tests {posargs}\n\n[testenv:pylint]\nbasepython=python3\ndeps =\n    pyflakes\n    pylint\n  -r{toxinidir}/requirements.txt\ncommands =\n    pylint pysmi\n\n[testenv:cover]\nbasepython=python3\nsetenv =\n   {[testenv]setenv}\n   PYTHON=coverage run --parallel-mode\ndeps =\n    {[testenv:unittest]deps}\n    coverage\n    discover\ncommands = coverage erase\n           coverage run --source pysmi -m unittest discover {posargs}\n           coverage report --fail-under 50\n\n[testenv:bandit]\nbasepython=python3\nskip_install = true\ndeps =\n    bandit\ncommands =\n    bandit -r pysmi -c .bandit.yml\n\n[testenv:docs]\nbasepython=python3\nskip_install = true\nwhitelist_externals = make\ncommands = make -C docs html\n\n[testenv:build]\nbasepython=python3\nskip_install = true\ndeps =\n    wheel\n    setuptools\ncommands =\n    python setup.py -q sdist bdist_wheel\n"
  }
]