Utility for automatically generating client/service interface code from
    a wsdl definition, and a set of classes representing element declarations 
    and type definitions.  By default invoking this script produces three files, 
    each named after the wsdl definition name, in the current working directory.
    
    Generated Modules Suffix:
        _client.py -- client locator, rpc proxy port, messages
        _types.py  -- typecodes representing 
        _server.py -- server-side bindings
        
    Parameters:
        args -- optional can provide arguments, rather than parsing 
            command-line.
            
    return:
        Default behavior is to return None, if args are provided then
        return names of the generated files.

def wsdl2py(args=None):
    """Utility for automatically generating client/service interface code from
    a wsdl definition, and a set of classes representing element declarations 
    and type definitions.  By default invoking this script produces three files, 
    each named after the wsdl definition name, in the current working directory.
    
    Generated Modules Suffix:
        _client.py -- client locator, rpc proxy port, messages
        _types.py  -- typecodes representing 
        _server.py -- server-side bindings
        
    Parameters:
        args -- optional can provide arguments, rather than parsing 
            command-line.
            
    return:
        Default behavior is to return None, if args are provided then
        return names of the generated files.
                                                    
    """
    op = optparse.OptionParser(usage="USAGE: %wsdl2py [options] WSDL",
                 description=wsdl2py.__doc__)
    
    # Basic options
    op.add_option("-x", "--schema",
                  action="store_true", dest="schema", default=False,
                  help="process just the schema from an xsd file [no services]")

    op.add_option("-d", "--debug",
                  action="callback", callback=SetDebugCallback,
                  help="debug output")
                  
    # WS Options
    op.add_option("-a", "--address",
                  action="store_true", dest="address", default=False,
                  help="ws-addressing support, must include WS-Addressing schema.")
                  
    # pyclass Metaclass 
    op.add_option("-b", "--complexType",
                  action="callback", callback=SetPyclassMetaclass, 
                  callback_kwargs={'module':'ZSI.generate.pyclass', 
                      'metaclass':'pyclass_type'},
                  help="add convenience functions for complexTypes, including Getters, Setters, factory methods, and properties (via metaclass). *** DONT USE WITH --simple-naming ***")
    
    # Lazy Evaluation of Typecodes (done at serialization/parsing when needed).
    op.add_option("-l", "--lazy",
                  action="callback", callback=SetUpLazyEvaluation, 
                  callback_kwargs={},
                  help="EXPERIMENTAL: recursion error solution, lazy evalution of typecodes")
    
    # Use Twisted
    op.add_option("-w", "--twisted",
                  action="store_true", dest='twisted', default=False,
                  help="generate a twisted.web client/server, dependencies python>=2.4, Twisted>=2.0.0, TwistedWeb>=0.5.0")
    
    op.add_option("-o", "--output-dir",
                  action="store", dest="output_dir", default=".", type="string",
                  help="save files in directory")
    
    op.add_option("-s", "--simple-naming",
                  action="store_true", dest="simple_naming", default=False,
                  help="map element names directly to python attributes")
    
    op.add_option("-p", "--pydoc",
                  action="store_true", dest="pydoc", default=False,
                  help="top-level directory for pydoc documentation.")
    
    
    is_cmdline = args is None
    if is_cmdline:
        (options, args) = op.parse_args()
    else:
        (options, args) = op.parse_args(args)

    if len(args) != 1:
        print>>sys.stderr, 'Expecting a file/url as argument (WSDL).'
        sys.exit(os.EX_USAGE)
        
    location = args[0]
    if options.schema is True:
        reader = XMLSchema.SchemaReader(base_url=location)
    else:
        reader = WSDLTools.WSDLReader()

    load = reader.loadFromFile
    if not isfile(location):
        load = reader.loadFromURL

    try:
        wsdl = load(location)
    except Exception, e:
        print >> sys.stderr, "Error loading %s: \n\t%s" % (location, e)
        traceback.print_exc(sys.stderr)
        # exit code UNIX specific, Windows?
        if hasattr(os, 'EX_NOINPUT'): sys.exit(os.EX_NOINPUT)
        sys.exit("error loading %s" %location)
  
    if isinstance(wsdl, XMLSchema.XMLSchema): 
        wsdl.location = location
        files = _wsdl2py(options, wsdl)
    else:
        files = _wsdl2py(options, wsdl)
        files.append(_wsdl2dispatch(options, wsdl))
    
    if getattr(options, 'pydoc', False):
        _writepydoc(os.path.join('docs', 'API'), *files)
        
    if is_cmdline:
        return
    
    return files