Skip to content

Instantly share code, notes, and snippets.

@justinfx
Created June 1, 2014 05:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinfx/d62c8157c8cc02f44d5a to your computer and use it in GitHub Desktop.
Save justinfx/d62c8157c8cc02f44d5a to your computer and use it in GitHub Desktop.
A small script to convert a .cix (codeintel schema) file into a python stub module, for use in auto-completion
#!/usr/bin/env python
'''
A small script to convert a .cix (codeintel schema) file into
a python stub module, for use in auto-completion.
https://community.activestate.com/faq/codeintel-cix-schema
Requires jinja2 for the output template format
'''
import inspect
from functools import partial
from jinja2 import Template
try:
from xml.etree.cElementTree import ElementTree
except:
from cElementTree import ElementTree
MODULE_TEMPLATE = """
{% for import in imports -%}
import {{ import }}
{% endfor %}
{% for var in variables -%}
{{ var }} = None
{% endfor %}
{% for func in functions %}
def {{ func.name }}(*args, **kwargs):
pass
{% endfor %}
{% for class in classes -%}
class {{ class.name }}({{ class.parent }}):
{% if class.empty -%}
pass
{% else %}
{% for attr in class.attributes -%}
{{ attr.name }} = {{ attr.value }}
{% endfor %}
{% for method in class.methods.itervalues() -%}
def {{ method.name }}(*args, **kwargs):
pass
{% endfor %}
{% endif %}
{% endfor %}
"""
_MODULES = {}
def handle_variable(x):
return x.get('name')
def handle_function(x):
return {'name': x.get('name')}
def handle_class(x, module=None, deep=False):
c = {
'name': x.get('name'),
# 'parent': x.get('classrefs', 'object'),
'parent': 'object',
'empty': True
}
methods = {}
for child in x.getiterator():
if child.get('ilk') == 'function':
methods[child.get('name')] = handle_function(child)
if deep and module:
if not module in _MODULES:
tokens = module.split('.')
if len(tokens) > 1 :
mods = tokens[:-1]
else:
mods = []
_MODULES[module] = __import__(module, fromlist=mods)
mod = _MODULES[module]
for member in inspect.getmembers(mod):
c['methods'] = methods
if methods:
c['empty'] = False
return c
def parse(source):
template = Template(MODULE_TEMPLATE)
tree = ElementTree()
root = tree.parse(source)
# modules = {}
blobs = root.findall("./file/scope[@ilk='blob']")
for m in blobs:
module_name = m.get('name')
members = {}
# variables
members['variables'] = map(handle_variable, m.findall("variable"))
# functions
members['functions'] = map(handle_function, m.findall("scope[@ilk='function']"))
# classes
members['classes'] = map(partial(handle_class, module=module_name), m.findall("scope[@ilk='class']"))
# modules[module_name] = members
# print "Module:", module_name
yield module_name, template.render(members)
if __name__ == "__main__":
import os
import argparse
parser = argparse.ArgumentParser(description='Convert .cix to python stub modules')
parser.add_argument('source', metavar='SOURCE', help="Source .cix file to parse")
parser.add_argument('-i', '--inspect', dest='inspect', action='store_true', default=False,
help='Perform a deeper inspect by importing each module')
args = parser.parse_args()
source = args.source
doInspect = args.inspect
outdir = 'stubs'
if not os.path.exists(outdir):
os.mkdir(outdir)
for name, source in parse(source):
tokens = name.split('.')
if len(tokens) > 1:
m_name = tokens[-1]
subdir = os.path.join(outdir, *tokens[:-1])
if not os.path.exists(subdir):
os.makedirs(subdir)
else:
m_name = name
subdir = outdir
outfile = os.path.join(subdir, '%s.py' % m_name)
with open(outfile, 'w') as f:
f.write(source)
print source
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment