Repository: datacenter/ACI (language: python)

Issue:
arya should be in its own repo
Arya is a standalone application that can be imported as a module.  It should be its own repository on github and published to pypi.



Discussion / hints:

Fix patch:
diff --git a/arya/LICENSE.txt b/arya/LICENSE.txt
deleted file mode 100644
index f2628c2..0000000
--- a/arya/LICENSE.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-APIC Rest Python Adapter (arya)
-
-Paul Lesiak - palesiak@cisco.com
-
-Copyright (C) 2014 Cisco Systems Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/arya/Manifest.in b/arya/Manifest.in
deleted file mode 100644
index 0c73842..0000000
--- a/arya/Manifest.in
+++ /dev/null
@@ -1,1 +0,0 @@
-include README.rst LICENSE
diff --git a/arya/README.rst b/arya/README.rst
index 2bca682..e69de29 100644
--- a/arya/README.rst
+++ b/arya/README.rst
@@ -1,111 +0,0 @@
-# APIC Rest Python Adapter (arya)
-
-Original Author: Paul Lesiak - [palesiak@cisco.com](palesiak@cisco.com)  
-Co-author: Mike Timm - [mtimm@cisco.com](mtimm@cisco.com)
-Solution Validation Services contact: Tim Garner - [tigarner@cisco.com](tigarner@cisco.com)
-
-
-# Description
-
-arya is a tool that will convert APIC object documents from their XML or JSON
-form into the equivalent Python code leveraging the Cobra SDK.
-
-arya supports  input in a number of formats, including XML, JSON, a directory containing
-multiple xml or json documents, as well as standard input. The standard input
-option is very useful for use as a filter in most text editors, where one
-can copy the JSON or XML extracted from APIC Visore or API inspector, and quickly
-generate the Python source code framework, which can then be modified, tokenized
-and rapidly turned into functional prototypes.
-
-Note that arya is a very useful tool for the heavy lifting of converting object
-model into source code, however it does not validate configuration, perform
-advanced lookup logic or implement a number of best practices that should be
-followed, such as performing lookups to validate targets, referencing object
-attributes instead of hardcoding Dns and names, and other proper coding practices
-
-It is strongly recommended that for advanced use cases, getting expert advice
-and validating your code, you reach out to Cisco Advanced Services for support.
-For more information, visit http://www.cisco.com/go/aci
-
-If you run into issues with arya, please open an issue on github
-
-
-# Installation
-
-## Environment
-Required
-
-* Python 2.7+
-
-Recommended:
-
-* Git
-
-## Downloading
-Option A:
-
-If you have git installed clone the repository
-
-    git clone https://github.com/datacenter/ACI.git
-
-Option B:
-
-If you don't have git [download a zip copy of the repository](https://github.com/datacenter/ACI/archive/master.zip) and extract.  
-
-## Installing
-Change directory to the cloned/extracted repo
-
-    cd ACI/arya
-
-Run the setup script
-
-    python setup.py install
-
-Check that arya can be run from the command line
-
-    $ arya.py
-
-
-# Usage
-
-Once installed arya will place the file `arya.py` in your path, so you should be able to call `arya.py` from any prompt.
-
-Usage is as such:
-
-    $ arya.py
-
-    usage: Code generator for APIC cobra SDK [-h] [-f FILE] [-s] [-d SOURCEDIR]
-                                             [-t TARGETDIR] [-i IP] [-p PASSWORD]
-
-    optional arguments:
-      -h, --help            show this help message and exit
-      -f FILE, --file FILE  Document containing post to be sent to REST API
-      -s, --stdin           Parse input from stdin, for use as a filter, e.g., cat
-                            doc.xml | arya.py -s
-      -d SOURCEDIR, --sourcedir SOURCEDIR
-                            Specify a source directory containing ACI object files
-                            you want to convert to python.
-      -t TARGETDIR, --targetdir TARGETDIR
-                            Where to write the .py files that come from the -d
-                            directory. If none is specified, it will default to
-                            SOURCEDIR
-      -i IP, --ip IP        IP address of APIC
-      -p PASSWORD, --password PASSWORD
-                            Password for admin account on APIC
-
-
-# License
-
-Copyright (C) 2014 Cisco Systems Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
diff --git a/arya/arya/__init__.py b/arya/arya/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/arya/arya/apicxmljson.py b/arya/arya/apicxmljson.py
deleted file mode 100755
index 7220287..0000000
--- a/arya/arya/apicxmljson.py
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/usr/bin/env python
-'''
-APIC XML <-> JSON Converter
-
-palesiak@cisco.com
-
-Copyright (C) 2014 Cisco Systems Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-Convert APIC encoded JSON to XML or XML to APIC encoded JSON
-'''
-import sys
-from os.path import basename
-import xml.etree.ElementTree as ET
-import json
-import StringIO
-from argparse import ArgumentParser
-
-
-class converter(object):
-
-    def __init__(self):
-        pass
-
-    def buildJSON(self, elem):
-        jsondict = {elem.tag: {'attributes': elem.attrib}}
-        for e in elem:
-            if 'children' not in jsondict[elem.tag]:
-                jsondict[elem.tag]['children'] = []
-            jsondict[elem.tag]['children'].append(self.buildJSON(e))
-        return jsondict
-
-    def recurseXMLTree(self, elem):
-        return json.dumps(self.buildJSON(elem))
-
-    def buildXML(self, jsondict):
-        elem = ET.Element(jsondict.keys()[0])
-        elem.attrib = jsondict[jsondict.keys()[0]]['attributes']
-
-        if 'children' in jsondict[jsondict.keys()[0]]:
-            for j in jsondict[jsondict.keys()[0]]['children']:
-                elem.append(self.buildXML(j))
-
-        return elem
-
-    def recurseJSONDict(self, jsondict):
-        return ET.tostring(self.buildXML(jsondict))
-
-
-def isXMLorJSON(docStr):
-
-    isXML = False
-    isJSON = False
-
-    try:
-        json.loads(docStr)
-        isJSON = True
-    except:
-        isJSON = False
-
-    try:
-        ET.ElementTree(ET.fromstring(docStr))
-        isXML = True
-    except:
-        isXML = False
-
-    if isJSON and isXML:
-        raise ValueError(
-            'This file appears to be both XML and JSON. I am confused. ' +
-            'Goodbye')
-
-    if isJSON:
-        return 'json'
-    elif isXML:
-        return 'xml'
-    else:
-        return None
-
-
-def main():
-    parser = ArgumentParser('Convert APIC encoded JSON to XML to JSON')
-    parser.add_argument('-s', '--stdin', help='Parse input from stdin, for ' +
-                        'use as a filter, e.g., cat doc.xml | %s -s' %
-                        str(basename(sys.argv[0])), action='store_true',
-                        default=False, required=False)
-    parser.add_argument(
-        '-f', '--file', help='File containing XML or JSON', required=False)
-    args = parser.parse_args()
-
-    if not args.file and not args.stdin:
-        print('ERROR: You must specify at least -s or -f')
-        print('')
-        parser.print_help()
-        sys.exit(1)
-
-    if args.stdin:
-        inputStr = sys.stdin.read()
-        inputFileH = StringIO.StringIO(inputStr)
-
-    if args.file:
-        with file(args.file, 'r') as inputFileH:
-            inputStr = inputFileH.read()
-            inputFileH = StringIO.StringIO(inputStr)
-
-    format = isXMLorJSON(inputStr)
-
-    if format == 'xml':
-        tree = ET.ElementTree(ET.fromstring(inputStr))
-        print converter().recurseXMLTree(tree.getroot())
-    elif format == 'json':
-        jsondict = json.loads(inputStr)
-        print converter().recurseJSONDict(jsondict)
-    else:
-        raise IOError(
-            'Unsupported format passed as input. Please check that input is' +
-            ' formatted correctly in JSON or XML syntax')
-        sys.exit(1)
-    sys.exit(0)
-
-if __name__ == '__main__':
-    main()
diff --git a/arya/arya/arya.py b/arya/arya/arya.py
deleted file mode 100755
index 172319b..0000000
--- a/arya/arya/arya.py
+++ /dev/null
@@ -1,453 +0,0 @@
-#!/usr/bin/env python
-'''
-APIC Rest Python Adapter (arya)
-
-Paul Lesiak - palesiak@cisco.com
-
-Copyright (C) 2014 Cisco Systems Inc.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-Converts blocks of APIC XML/JSON into the equivalent cobra code to construct
-the objects.
-'''
-
-import os
-import sys
-import xml.etree.cElementTree as ETree
-import json
-import keyword
-import StringIO
-from argparse import ArgumentParser
-from string import Template
-from collections import OrderedDict
-
-class arya:
-
-    # attributes that should be excluded from autogenerated code, even if they
-    # are provided
-    EXCLUDEATTR = ['configIssues', 'stateQual', 'replTs', 'modTs', 'lcC',
-                   'childAction',  'monPolDn',  'state',  'lcOwn', 'rn',
-                   'triggerSt',    'configSt',  'status', 'scope', 'uid',
-                   'dn']
-
-    # Sort the list of APIC package names by reverse length so we can do a
-    # longest prefix match on the moname
-    # If the object model has changed considerable you may need to update this list
-    # import os, cobra.model;
-    # l = [k.split('.')[0] for k in \
-    # os.listdir(os.path.normpath(cobra.model.__path__[0])) if k.endswith(
-    # '.py') and not k.startswith('_')]
-    # print l
-    APICPACKAGES = sorted(
-        ['testinfralab', 'policer', 'rtpfx', 'task', 'file', 'geo',
-         'eqptcapacity', 'monitor', 'rtmap', 'span', 'eqpt', 'fsm',
-         'traceroutep',  'lldptlv', 'rtflt', 'snmp', 'draw', 'epm',
-         'traceroute',   'isistlv', 'rtcom', 'satm', 'dhcp', 'dns',
-         'lldptlvpol',   'eqptcap', 'pcons', 'rule', 'copp', 'dbg',
-         'imginstall',   'dhcptlv', 'mcast', 'rmon', 'coop', 'ctx',
-         'dhcptlvpol',   'uribv4',  'maint', 'repl', 'comp', 'cnw',
-         'synthetic',    'tunnel',  'leqpt', 'reln', 'comm', 'cdp',
-         'statstore',    'sysmgr',  'l3ext', 'rbqm', 'vpc',  'cap',
-         'igmpsnoop',    'syslog',  'l3cap', 'qosp', 'vns',  'bgp',
-         'eqptdiagp',    'rtleak',  'l2ext', 'qosm', 'vmm',  'arp',
-         'condition',    'rtctrl',  'l2cap', 'proc', 'top',  'aib',
-         'stormctrl',    'opflex',  'l1cap', 'pres', 'tlv',  'aaa',
-         'topoctrl',     'naming',  'infra', 'pool', 'tag',  'vz',
-         'sysdebug',     'memory',  'ident', 'ping', 'svi',  'pc',
-         'rtregcom',     'icmpv6',  'glean', 'phys', 'sts',  'os',
-         'rtextcom',     'icmpv4',  'fault', 'ospf', 'stp',  'nw',
-         'observer',     'health',  'extnw', 'mock', 'rpm',  'nd',
-         'firmware',     'fvtopo',  'event', 'mgmt', 'rib',  'mo',
-         'eqptdiag',     'fmcast',  'ethpm', 'lldp', 'res',  'l4',
-         'datetime',     'frmwrk',  'eptrk', 'lacp', 'qos',  'l3',
-         'callhome',     'fabric',  'dbgac', 'l3vm', 'psu',  'l2',
-         'actrlcap',     'dbgexp',  'ctrlr', 'isis', 'pol',  'l1',
-         'vlanmgr',      'config',  'adcom', 'ipv6', 'pki',  'ip',
-         'sysmgrp',      'compat',  'actrl', 'ipv4', 'oam',  'im',
-         'syshist',      'action',  'vsvc',  'igmp', 'mon',  'ha',
-         'sysfile',      'vxlan',   'vlan',  'icmp', 'mcp',  'fv',
-         'svccore',      'stats',   'trig',  'fvns', 'lbp',  'ac',
-         'regress',      'rtsum',   'test',  'vtap', 'hvs'],
-        key=lambda l: 100 * 1 / len(l))
-
-    POLUNICONTAINED = ['configBackupStatusCont', 'dbgDebugP',
-                       'vnsScriptHandlerState',  'aaaUserEp',
-                       'rbqmUseCaseGroup',       'l3extDomP',
-                       'tagAliasDef',            'l2extDomP',
-                       'faultCounts',            'fvTenant',
-                       'infraInfra',             'physDomP',
-                       'fabricInst',             'fvCtxDef',
-                       'healthInst',             'vmmProvP',
-                       'aaaRbacEp',              'fvBDDef',
-                       'fvEpPCont',              'vnsVDev',
-                       'ctrlrInst',              'tagDef']
-
-    def __init__(self):
-        """
-        Class constructor
-        Define some of the python modules we will always be importing
-        """
-        self.objectcounter = 0
-        self.importlist = [
-            'cobra.mit.access', 'cobra.mit.session', 'cobra.mit.request']
-        self.varnames = OrderedDict()
-
-    def resolvemoname(self, moname):
-        """
-        This method does a longest prefix match on the name of an mo, e.g.,
-        fvTenant and then finds the APIC package name that this class belongs
-        to. If it's unable to find a matching package name, it means something
-        in the input XML/JSON is screwy and that we should raise an exception
-        returns: packageName, className, e.g., fv, Tenant
-        """
-        for c in self.APICPACKAGES:
-            if moname.startswith(c):
-                package = c
-                name = moname[len(c):len(moname)]
-                break
-        else:
-            raise LookupError(
-                'Unable to find class %s in package list' % moname)
-        return package, name
-
-    def getvarname(self, objname):
-        """
-        This method helps track variable names that are in use so in case of
-        nested and/or duplicate variable names the code has to auto generate
-        we can easily differentiate between them. it's simply an occurence
-        counter, that returns the name of the object with its occurence count
-        appended to the end
-        """
-        if objname in self.varnames:
-            self.varnames[objname] += 1
-            return '%s%d' % (objname, self.varnames[objname])
-        else:
-            self.varnames[objname] = 1
-            return '{0}'.format(objname)
-
-    def buildattributestring(self, attr):
-        """
-        Builds the attribute string for the object creation
-
-        attr is a dict containing name value pairs of the attribute and value
-        """
-        if not isinstance(attr, dict):
-            attr = dict()
-
-        parmlist = []
-        for k, v in attr.items():
-            if k not in self.EXCLUDEATTR:
-                # any properly formed xml/json should have keywords already
-                # escaped however this is just a sanity check. also, it
-                # misses 'to' which is not a keyword in python, but is
-                # treated as such in pymeta oh well
-                if keyword.iskeyword(k):
-                    k += '_'
-
-                v = repr(v)
-                parmlist.append('%s=%s' % (k, v))
-
-        attribstr = ', '.join(parmlist)
-
-        return attribstr
-
-    def buildcommand(self, mofullname, moparent, attr):
-        """
-        This is the build ol' chunk of code that accepts the mo, it's parent
-        and attributes and then creates the equivalent cobra calls
-        This method should be pretty meta format agnostic -- I was able to use
-        this same method for both JSON and XML with no changes
-
-        mofullname - complete MO name, extracted from the JSON key/XML tag name
-        moparent - parent object variable name
-        attr - dict (key/value pair) containing attributes for this MO
-        """
-
-        cmd = ''
-        objectvarname = None
-
-        mopackagename, moclassname = self.resolvemoname(mofullname)
-
-        if moclassname.startswith('Rt'):
-            # skipping object that is a relationship target (Rt), since they are
-            # not going to contain any useful configuration we need to copy
-            pass
-        else:
-            attribstr = self.buildattributestring(attr)
-
-            cobrapackagename = 'cobra.model.%s' % mopackagename
-            if cobrapackagename not in self.importlist:
-                self.importlist.append(cobrapackagename)
-
-            objectvarname = self.getvarname(mofullname)
-            if mofullname == 'polUni':
-                return '', moparent
-
-            parms = [moparent]
-            if attribstr != '':
-                parms.append(attribstr)
-
-            cmd += '%s = cobra.model.%s.%s(%s)\n' % (
-                objectvarname, mopackagename, moclassname, ', '.join(parms))
-            if attr.get('status', '') == 'deleted':
-                cmd += '%s.delete()\n' % objectvarname
-
-            self.objectcounter += 1
-        return cmd, objectvarname
-
-    def recursexmltree(self, elem, parentname):
-        pycode, objectname = self.buildcommand(
-            elem.tag, parentname, elem.attrib)
-        for e in elem:
-            pycode += self.recursexmltree(e, objectname)
-
-        return pycode
-
-    def recursejsondict(self, jsondict, parentname):
-        pycode, objectname = self.buildcommand(
-            jsondict.keys()[0], parentname,
-            jsondict[jsondict.keys()[0]].get('attributes', {}))
-
-        if 'children' in jsondict[jsondict.keys()[0]]:
-            for j in jsondict[jsondict.keys()[0]]['children']:
-                pycode += self.recursejsondict(j, objectname)
-
-        return pycode
-
-    def getpython(self, xmlstr=None, jsonstr=None, apicip='1.1.1.1',
-                  apicpassword='password', apicuser='admin', nocommit=False):
-
-        pycodetemplate = Template("""#!/usr/bin/env python
-'''
-Autogenerated code using $myFileName
-Original Object Document Input: 
-$sourceDoc
-'''
-$raisecheckwarning
-
-# list of packages that should be imported for this code to work
-$imports
-from cobra.internal.codec.xmlcodec import toXMLStr
-
-# log into an APIC and create a directory object
-ls = cobra.mit.session.LoginSession('https://$apicHost', '$apicUser', '$apicPassword')
-md = cobra.mit.access.MoDirectory(ls)
-md.login()
-
-# the top level object on which operations will be made
-$lookupCode
-
-# build the request using cobra syntax
-$objStructureCode
-
-# commit the generated code to APIC
-print toXMLStr($topMo)
-$commitCode""")
-
-        vals = {}
-        topobjectvar = 'topMo'
-        topdn = None
-
-        if nocommit:
-            vals['raisecheckwarning'] = ''
-        else:
-            vals['raisecheckwarning'] = """raise RuntimeError('Please review the auto generated code before ' +
-                    'executing the output. Some placeholders will ' +
-                    'need to be changed')"""
-
-        if xmlstr and jsonstr:
-            raise ValueError('Both xmlfile and jsonfile provided. Which one ' +
-                             'do I listen to? I am so confused!')
-
-        toptag = None
-        if xmlstr:
-            tree = ETree.ElementTree(ETree.fromstring(xmlstr))
-            root = tree.getroot()
-            if root.tag == 'imdata':
-                root = list(root)[0]
-            toptag = root.tag
-            topdn = root.attrib.get('dn', None)
-            vals['objStructureCode'] = self.recursexmltree(root, topobjectvar)
-
-        if jsonstr:
-            j = json.loads(jsonstr)
-            if j.keys()[0] == 'imdata':
-                j = j['imdata'][0]
-            toptag = j.keys()[0]
-            topdn = j[j.keys()[0]].get('attributes', {}).get('dn', None)
-            vals['objStructureCode'] = self.recursejsondict(j, topobjectvar)
-
-        if (toptag in self.POLUNICONTAINED):
-            self.importlist.append('cobra.model.pol')
-            lookupcodestr = 'topMo = cobra.model.pol.Uni(\'\')\n'
-            vals['lookupCode'] = lookupcodestr
-        elif toptag == 'polUni':
-            vals['lookupCode'] = '{0} = cobra.model.pol.Uni(\'\')'.format(
-                topobjectvar)
-        else:
-            # varnameindex = 0
-            if topdn:
-                self.importlist.append('cobra.mit.naming')
-                lookupcodestr = '# Confirm the dn below is for your top dn\n'
-                lookupcodestr += 'topDn = cobra.mit.naming.'
-                lookupcodestr += 'Dn.fromString(\'{0}\')\n'.format(topdn)
-                lookupcodestr += 'topParentDn = topDn.getParent()\n'
-                lookupcodestr += '{0} = md.lookupByDn(topParentDn)'.format(
-                    topobjectvar)
-            else:
-                lookupcodestr = '# Replace the text below with the dn of your '
-                lookupcodestr += 'top object\n'
-                lookupcodestr += '{0} = md.lookupByDn(\'REPLACEME\')'.format(
-                    topobjectvar)
-            vals['lookupCode'] = lookupcodestr
-
-        vals['apicHost'] = apicip
-        vals['apicUser'] = apicuser
-        vals['apicPassword'] = apicpassword
-        vals['sourceDoc'] = xmlstr or jsonstr
-        vals['myFileName'] = os.path.basename(str(sys.argv[0]))
-        vals['imports'] = '\n'.join(['import %s' % i for i in self.importlist])
-        vals['topMo'] = topobjectvar
-        commitcodestr = 'c = cobra.mit.request.ConfigRequest()\n'
-        commitcodestr += 'c.addMo(topMo)\n'
-        if not nocommit:
-            commitcodestr += 'md.commit(c)\n'
-        vals['commitCode'] = commitcodestr
-        return pycodetemplate.substitute(vals)
-
-
-def isxmlorjson(s):
-    try:
-        json.loads(s)
-        isjson = True
-    except ValueError:
-        isjson = False
-
-    try:
-        ETree.ElementTree(ETree.fromstring(s))
-        isxml = True
-    except ETree.ParseError:
-        isxml = False
-
-    if isjson and isxml:
-        raise ValueError('This file appears to be both XML and JSON. I am ' +
-                         'confused. Goodbye')
-
-    if isjson:
-        return 'json'
-    elif isxml:
-        return 'xml'
-    else:
-        return None
-
-
-def runfromcli(args):
-
-    def processinputstr(inputstr, args):
-        format = isxmlorjson(inputstr)
-
-        if format == 'xml':
-            return arya().getpython(xmlstr=inputstr, apicip=args.ip,
-                                    apicpassword=args.password,
-                                    nocommit=args.nocommit)
-        elif format == 'json':
-            return arya().getpython(jsonstr=inputstr, apicip=args.ip,
-                                    apicpassword=args.password,
-                                    nocommit=args.nocommit)
-        else:
-            raise IOError('Unsupported format passed as input. Please check ' +
-                          'that input is formatted correctly in JSON or XML syntax')
-
-    if args.filein or args.stdin:
-        if args.stdin:
-            inputstr = sys.stdin.read()
-        elif args.filein:
-            with file(args.filein, 'r') as inputfilehandle:
-                inputstr = inputfilehandle.read()
-        print processinputstr(inputstr, args)
-
-    elif args.sourcedir:
-        sourcedir = os.path.realpath(args.sourcedir)
-        if args.targetdir:
-            targetdir = os.path.realpath(args.targetdir)
-        else:
-            targetdir = sourcedir
-
-        print 'Reading from %s and writing to %s' % (sourcedir, targetdir)
-        os.chdir(args.sourcedir)
-        for files in os.listdir('.'):
-            if (files.lower().endswith('.xml') or
-                    files.lower().endswith('.json')):
-                outfilename = os.path.join(
-                    targetdir, os.path.basename(files).split('.')[-2] + '.py')
-                if os.path.isfile(outfilename):
-                    raise IOError(
-                        'Output file: %s already exists' % outfilename)
-                print '%s -> %s' % (files, outfilename)
-
-                p = None
-                try:
-                    with file(files, 'r') as f:
-                        p = processinputstr(f.read(), args)
-                except ETree.ParseError:
-                    print 'XML parser error %s' % files
-                else:
-                    with open(outfilename, 'w') as f:
-                        f.write(p)
-
-    return True
-
-def main():
-    parser = ArgumentParser('Code generator for APIC cobra SDK')
-    parser.add_argument(
-        '-f', '--filein', help='Document containing post to be sent to ' +
-                             'REST API', required=False)
-    parser.add_argument(
-        '-s', '--stdin', help='Parse input from stdin, for use as a filter, ' +
-                              'e.g., cat doc.xml | {0} -s'.format(
-                              os.path.basename(sys.argv[0])),
-        action='store_true', default=False, required=False)
-    parser.add_argument(
-        '-d', '--sourcedir', help='Specify a source directory containing ' +
-                                  'ACI object files you want to convert to python. ',
-        required=False)
-    parser.add_argument(
-        '-t', '--targetdir', help='Where to write the .py files that come ' +
-                                  'from the -d directory. If none is ' +
-                                  'specified, it will default to SOURCEDIR',
-        required=False)
-    parser.add_argument('-i', '--ip', help='IP address of APIC to be ' +
-        ' pre-populated', required=False, default='1.1.1.1')
-    parser.add_argument('-u', '--username', help='Username for APIC account ' +
-        'to be pre-populated in generated code', required=False, 
-        default='admin')
-    parser.add_argument('-p', '--password', help='Password for APIC account ' +
-        ' to be pre-populated in generated code', required=False, 
-        default='password')
-    parser.add_argument('-nc', '--nocommit',
-                        help='Generate code without final commit to changes', 
-                        required=False,
-                        default=False, action='store_true')
-    args = parser.parse_args()
-
-    if not args.filein and not args.sourcedir and not args.stdin:
-        print('ERROR: You must specify at least -d, -f, or -s ')
-        print('')
-        parser.print_help()
-        sys.exit(1)
-
-    runfromcli(args)
-
-if __name__ == '__main__':
-    main()
diff --git a/arya/arya/getconfigfromapic.py b/arya/arya/getconfigfromapic.py
deleted file mode 100755
index 16bad97..0000000
--- a/arya/arya/getconfigfromapic.py
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/env python
-
-from argparse import ArgumentParser
-import httplib
-import logging
-
-from arya import arya
-
-try:
-    import cobra.mit.access
-    import cobra.mit.session
-    import cobra.mit.request
-    from cobra.internal.codec.xmlcodec import toXMLStr
-except ImportError:
-    print("*"*60)
-    print("This requires the ACI Python SDK")
-    print ("*"*60)
-    print
-    raise
-
-
-def lookupSubtreeByDn(md, dn, propFilter=None):
-    dnq = cobra.mit.request.DnQuery(dn)
-    dnq.subtree = 'full'
-    dnq.propInclude = 'config-only'
-    if propFilter:
-        dnq.propFilter = propFilter
-    try:
-        return md.query(dnq)[0]
-    except:
-        return None
-
-
-def main():
-    parser = ArgumentParser('Generate cobra SDK code from APIC')
-    parser.add_argument('-a', '--apic', help='Target APIC', required=True)
-    parser.add_argument('-e', '--endpoint', help='Use old EndPoint object',
-                        default=False)
-    parser.add_argument('-p', '--port', help='APIC Port', default=80)
-    parser.add_argument('-u', '--user', help='APIC Username', default='admin')
-    parser.add_argument(
-        '-s', '--secure', help='Verify certificate', default=False)
-    parser.add_argument(
-        '-pw', '--password', help='APIC Password', required=True)
-    parser.add_argument('-d', '--dn', help='DN to query', required=True)
-    parser.add_argument(
-        '-v', '--verbose', help='Enable debugging', default=False)
-    args = parser.parse_args()
-
-    if args.verbose:
-        httplib.HTTPConnection.debuglevel = 1
-        logging.basicConfig(level=logging.DEBUG)
-
-    if args.endpoint:
-        ep = cobra.mit.access.EndPoint(
-            args.apic, secure=False if args.port == 80 else True, port=args.port)
-        ls = cobra.mit.session.LoginSession(args.user, args.password)
-        md = cobra.mit.access.MoDirectory(ep, ls)
-    else:
-        if args.apic.startswith(('http://', 'https://')):
-            if args.apic.endswith('/'):
-                args.apic = args.apic[:-1]
-            args.apic = str(args.apic) + ":" + str(args.port) + "/"
-            ls = cobra.mit.session.LoginSession(
-                args.apic, args.user, args.password, secure=args.secure)
-            md = cobra.mit.access.MoDirectory(ls)
-    md.login()
-
-    mo = lookupSubtreeByDn(md, args.dn)
-    if mo:
-        xmlstr = toXMLStr(mo, includeAllProps=True, prettyPrint=True)
-        print arya().getpython(xmlstr=xmlstr, apicip=args.apic, apicuser=args.user, apicpassword=args.password)
-    else:
-        print 'Nothing found for DN {0}'.format(args.dn)
-
-if __name__ == '__main__':
-    main()
diff --git a/arya/arya/version.py b/arya/arya/version.py
deleted file mode 100644
index a615591..0000000
--- a/arya/arya/version.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# Set this to the version of arya for the distribution.
-__version__ = '1.1.0'
diff --git a/arya/setup.py b/arya/setup.py
deleted file mode 100644
index 4337429..0000000
--- a/arya/setup.py
+++ /dev/null
@@ -1,65 +0,0 @@
-import sys
-import os
-
-try:
-    from setuptools import setup
-    from setuptools.command.test import test as TestCommand
-except ImportError:
-    from distutils.core import setup
-    from distutils.core import Command as TestCommand
-
-class PyTest(TestCommand):
-
-    def finalize_options(self):
-        TestCommand.finalize_options(self)
-        self.test_args = []
-        self.test_suite = True
-
-    def run_tests(self):
-        import pytest
-        errno = pytest.main(self.test_args)
-        sys.exit(errno)
-
-
-with open('LICENSE.txt') as f:
-    license = f.read()
-
-exec(open(os.path.join('arya', 'version.py')).read())
-
-PKGNAME = 'arya'
-URL = 'https://github.com/datacenter/ACI/' + PKGNAME
-DOWNLOADURL = URL + '/releases/tag/' + str(__version__)
-
-setup(
-    name=PKGNAME,
-    version=__version__,
-    description='APIC Rest to pYthon Adapter',
-    long_description=open('README.rst').read(),
-    packages=[PKGNAME],
-    url='https://github.com/datacenter/ACI/arya',
-    download_url=DOWNLOADURL,
-    license=license,
-    author='Paul Lesiak',
-    author_email='palesiak@cisco.com',
-    zip_safe=False,
-    classifiers=(
-        'Development Status :: 4 - Beta',
-        'Intended Audience :: Developers',
-        'Natural Language :: English',
-        'License :: OSI Approved :: Apache Software License',
-        'Programming Language :: Python',
-        'Programming Language :: Python :: 2.7',
-    ),
-    scripts=[os.path.join('arya', 'arya.py'),
-             os.path.join('arya', 'getconfigfromapic.py'),
-             os.path.join('arya', 'apicxmljson.py')],
-    entry_points={
-        "console_scripts": [
-            "arya=arya:main",
-            "getconfigfromapic=getconfigfromapic:main",
-            "apicxmljson=apicxmljson:main",
-        ],
-    },
-    tests_require = ['pytest'],
-    cmdclass = {'test': PyTest},
-)


Test patch:
diff --git a/arya/conftest.py b/arya/conftest.py
deleted file mode 100644
index 1f5c0e6..0000000
--- a/arya/conftest.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import pytest
-import sys
-import os
-
-
-def pytest_addoption(parser):
-    filedir = os.path.abspath(os.path.dirname(os.path.realpath(__file__)))
-    parser.addoption('--apic', nargs=4, action='append',
-                     metavar=('url', 'user', 'passwd', 'secure'),
-                     help='The URL to the APIC or switch, username, ' +
-                     'password, secure (True/False)')
-    parser.addoption(
-        '--sourcedir', action='store', metavar='sourcedir',
-        default='{0}'.format(os.path.join(filedir, 'tests', 'samples')))
-    parser.addoption(
-        '--targetdir', action='store', metavar='targetdir',
-        default='{0}'.format(os.path.join(filedir, 'tests', 'testout')))
-
-
-def pytest_runtest_setup(item):
-    if 'needapic' in item.keywords and not item.config.getoption(
-            'apic', default=None):
-        pytest.skip('Test needs APIC target to test against')
diff --git a/arya/tests/.gitignore b/arya/tests/.gitignore
deleted file mode 100644
index 549d46d..0000000
--- a/arya/tests/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-testout/*
-samples/*
diff --git a/arya/tests/__init__.py b/arya/tests/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/arya/tests/test_arya.py b/arya/tests/test_arya.py
deleted file mode 100644
index ae2fe46..0000000
--- a/arya/tests/test_arya.py
+++ /dev/null
@@ -1,151 +0,0 @@
-#!/usr/bin/env python
-import os
-import pytest
-import sys
-import logging
-import inspect
-import pkgutil
-import httplib
-import subprocess
-from argparse import Namespace
-
-import cobra.model
-import cobra.mit.access
-import cobra.mit.session
-import cobra.mit.request
-
-from cobra.internal.codec.xmlcodec import toXMLStr
-from cobra.internal.codec.jsoncodec import toJSONStr
-
-import sys
-import os
-from arya import arya
-
-needapic = pytest.mark.needapic
-
-httplib.HTTPConnection.debuglevel = 1
-logging.basicConfig(level=logging.DEBUG)
-
-
-@pytest.fixture(params=pytest.config.getvalue('apic'))
-def moDir(request):
-    url, user, password, secure = request.param
-    secure = False if secure == 'False' else True
-    session = cobra.mit.session.LoginSession(url, user, password,
-                                             secure=secure)
-    md = cobra.mit.access.MoDirectory(session)
-    md.login()
-    return md
-
-
-def lookupSubtreeByDn(md, dn, propFilter=None):
-    dnq = cobra.mit.request.DnQuery(dn)
-    dnq.subtree = 'full'
-    dnq.propInclude = 'config-only'
-    if propFilter:
-        dnq.propFilter = propFilter
-    try:
-        return md.query(dnq)[0]
-    except:
-        return None
-
-
-def pytest_generate_tests(metafunc):
-
-    derefpath = lambda path: os.path.realpath(
-        os.path.expanduser(os.path.expandvars(path)))
-
-    if 'apic' in metafunc.fixturenames:
-        if metafunc.config.getvalue('apic') != []:
-            apics = [x for x in metafunc.config.getvalue('apic')]
-            metafunc.parametrize('apic', apics)
-
-    if 'testfiles' in metafunc.fixturenames:
-
-        sourcedir = derefpath(metafunc.config.getvalue('sourcedir'))
-        targetdir = derefpath(metafunc.config.getvalue('targetdir'))
-        files = []
-        os.chdir(sourcedir)
-        for fil in os.listdir('.'):
-            fil = os.path.abspath(fil)
-            if fil.lower().endswith('.xml') or fil.lower().endswith('.json'):
-                outfilename = os.path.abspath(
-                    os.path.join(targetdir,
-                                 os.path.basename(fil).split('.')[-2] + '.py'))
-                files.append((fil, outfilename))
-        metafunc.parametrize('testfiles', files)
-
-    if 'sourcedir' in metafunc.fixturenames:
-        sourcedir = derefpath(pytest.config.getvalue('sourcedir'))
-        metafunc.parametrize('sourcedir', [sourcedir])
-
-    if 'targetdir' in metafunc.fixturenames:
-        targetdir = derefpath(pytest.config.getvalue('targetdir'))
-        metafunc.parametrize('targetdir', [targetdir])
-
-    if 'dn' in metafunc.fixturenames:
-        metafunc.parametrize(
-            'dn', ['uni/tn-mgmt', 'uni/controller/nodeidentpol'])
-
-    if 'codec' in metafunc.fixturenames:
-        metafunc.parametrize('codec', ['xml', 'json'])
-
-
-@pytest.mark.arya_unit_func_test
-class Test_arya:
-
-    @needapic
-    def test_generate_from_apic(self, moDir, dn, codec):
-        mo = lookupSubtreeByDn(moDir, dn)
-        assert mo
-        if codec == 'xml':
-            instr = toXMLStr(mo, includeAllProps=True)
-            print instr
-            pycode = arya.arya().getpython(xmlstr=instr)
-        elif codec == 'json':
-            instr = toJSONStr(mo, includeAllProps=True)
-            print instr
-            pycode = arya.arya().getpython(jsonstr=instr)
-
-        assert pycode
-
-    def test_generate_by_files(self, testfiles):
-        apic = pytest.config.getoption('apic')
-        if not apic:
-            apic = [['http://mock', 'admin', 'password', False]]
-        apic = apic[0]
-        url, user, password, secure = apic
-        url = str(url).split('//')[1]
-        args = Namespace(
-            stdin=None, filein=testfiles[0], ip=url, password=password,
-            nocommit=True)
-        assert arya.runfromcli(args)
-
-    def test_clean_output(self, targetdir):
-        try:
-            os.makedirs(targetdir)
-        except OSError:
-            pass
-
-        os.chdir(targetdir)
-
-        for f in os.listdir(targetdir):
-            if f.endswith(".py"):
-                os.remove(f)
-
-    def test_generate_from_samples_directory(self, sourcedir, targetdir):
-        apic = pytest.config.getoption('apic')
-        if not apic:
-            apic = [['http://mock', 'admin', 'password', False]]
-        apic = apic[0]
-        url, user, password, secure = apic
-        url = str(url).split('//')[1]
-        args = Namespace(sourcedir=sourcedir, filein=None, stdin=None,
-                         targetdir=targetdir, ip=url, password=password,
-                         nocommit=True)
-        assert arya.runfromcli(args)
-
-    @needapic
-    def test_execute_cobra_scripts(self, testfiles):
-        cobrafile = testfiles[1]
-        subprocess.check_call(['python', cobrafile])