Source code for src.tools.instrospection
"""A tool for parsing instrument modules."""
import re
from src.tools import path_tools as pt
PATTERN_DOCSTRING1 = re.compile(r'"""(.*?)"""', re.DOTALL)
PATTERN_DOCSTRING2 = re.compile(r"'''(.*?)'''", re.DOTALL)
PATTERN_IMPORT1 = re.compile(r'from +([\.\w_]+) +import +([\.\w_, ]+)\s*\n')
PATTERN_IMPORT2 = re.compile(r'from +([\.\w_]+) +import +'
r'([\.\w_]+) +as +([\.\w_]+)\s*\n')
PATTERN_IMPORT3 = re.compile(r'^import +([\.\w_]+)\s*\n', re.M)
PATTERN_IMPORT4 = re.compile(r'^import +([\.\w_]+) +as +([\.\w_]+)\s*\n', re.M)
[docs]class Module(object):
"""The class containing the entire contents of the module."""
def __init__(self, filename):
with open(filename) as fileobject:
text = fileobject.read()
self.docstring = Docstring(text)
self.imports = Imports(text)
[docs]class Docstring(object):
"""A class to contain docstrings.
Parameters
----------
text : str
The text for the docstring.
"""
def __init__(self, text):
match = PATTERN_DOCSTRING1.search(text)
if match:
textList = match.group(1).split('\n')
print repr(textList)
self.summary = textList[0]
info = textList[1:]
if len(info) == 0:
info = ['']
while len(info[0].strip()) == 0 and len(info) > 1:
del info
while len(info[-1].strip()) == 0 and len(info) > 1:
del info[-1]
self.information = '\n'.join(info)
[docs] def toCode(self):
"""Return the text of the docstring.
Returns
-------
str
The new docstring.
"""
answer = '\n'.join([self.summary, self.information])
answer = '"""' + answer + '\n"""'
return answer
[docs]class Imports(object):
"""The collection of imports."""
def __init__(self, text):
imports = []
matches = PATTERN_IMPORT1.findall(text)
for match in matches:
imports.append(Import((0, match)))
matches = PATTERN_IMPORT2.findall(text)
for match in matches:
imports.append(Import((1, match)))
matches = PATTERN_IMPORT3.findall(text)
for match in matches:
imports.append(Import((2, (match,))))
matches = PATTERN_IMPORT4.findall(text)
for match in matches:
imports.append(Import((3, match)))
self.standards = []
self.locals = []
for item in imports:
if item.importData[0].startswith('src'):
self.locals.append(item)
else:
self.standards.append(item)
self.toCode()
def toCode(self):
self.standards.sort(Import.cmp)
self.locals.sort(Import.cmp)
ans = []
for item in Imports.rejoin(self.standards):
if item not in ans:
ans.append(item)
ans.append('')
for item in Imports.rejoin(self.locals):
if item not in ans:
ans.append(item)
print '\n'.join(ans)
@classmethod
def rejoin(cls, lst):
ans = []
for item in lst:
kind = item.importType
data = item.importData
if kind == 0:
ans.append('from %s import %s' % data)
elif kind == 1:
ans.append('from %s import %s as %s' % data)
elif kind == 2:
ans.append('import %s' % data[0])
else:
ans.append('import %s as %s' % data)
return ans
[docs]class Import(object):
"""A single import command."""
def __init__(self, information):
self.importType = information[0]
self.importData = information[1]
def __lt__(self, other):
"""Return whether this import is "less than" some other."""
mine = self.importData[0]
his = other.importData[0]
value = compare(mine, his)
if value == 0:
return self.importData[1] < other.importData[1]
return value == -1
#FIXME Combine this with the compare function from below.
@classmethod
def cmp(cls, itemA, itemB):
mine = itemA.importData[0]
his = itemB.importData[0]
value = compare(mine, his)
if value == 0:
if itemA.importData[1] < itemB.importData[1]:
return -1
if itemA.importData[1] > itemB.importData[1]:
return 1
return 0
return value
[docs]class Constants(object):
"""The constants defined in the module."""
[docs]class Instrument(object):
"""An instrument class"""
[docs]class Function(object):
"""A module-level function."""
[docs]def compare(stringA, stringB):
"""Compare two import strings for sorting.
Parameters
----------
stringA : str
The first import string.
stringB : str
The import string to compare with the first.
Returns
-------
int
An integer representing how the first import string compares to the
second. If the first is smaller, the returned value is -1. If the
two are the same, 0 is returned. Otherwise, +1 is returned.
"""
stringListA = stringA.split('.')
stringListB = stringB.split('.')
for itemA, itemB in zip(stringListA, stringListB):
if itemA < itemB:
return -1
elif itemA > itemB:
return 1
equal = True
if len(stringListA) == len(stringListB):
for itemA, itemB in zip(stringListA, stringListB):
if itemA != itemB:
equal = False
if equal:
return 0
if len(stringListA) < len(stringListB):
return -1
return 1
if __name__ == '__main__':
modfile = pt.unrel('src', 'gui', 'gui_helpers.py')
mod = Module(modfile)