Go to the documentation of this file.00001 import re
00002 import os
00003 from ros_introspection.resource_list import is_package, get_python_dependency
00004
00005 PKG = '([^\.;]+)(\.?[^;]*)?'
00006 PYTHON1 = '^import ' + PKG
00007 PYTHON2 = 'from ' + PKG + ' import .*'
00008 CPLUS = re.compile('#include\s*[<\\"]([^/]*)/?([^/]*)[>\\"]')
00009 CPLUS2 = re.compile('#include\s*[<\\"]([^/]*)/([^/]*)/([^/]*)[>\\"]')
00010 ROSCPP = re.compile('#include\s*<ros/ros.h>')
00011
00012 EXPRESSIONS = [re.compile(PYTHON1), re.compile(PYTHON2), CPLUS, CPLUS2]
00013
00014
00015 def is_python_hashbang_line(s):
00016 return s[0:2] == '#!' and 'python' in s
00017
00018
00019 class SourceCodeFile:
00020 def __init__(self, rel_fn, file_path):
00021 self.rel_fn = rel_fn
00022 self.file_path = file_path
00023 self.tags = set()
00024 self.changed_contents = None
00025
00026 self.lines = map(str.strip, self.get_contents().split('\n'))
00027 if '.py' in self.file_path or (len(self.lines) > 0 and is_python_hashbang_line(self.lines[0])):
00028 self.language = 'python'
00029 else:
00030 self.language = 'c++'
00031
00032 parts = os.path.split(rel_fn)
00033 if parts and parts[0] == 'test':
00034 self.tags.add('test')
00035
00036 def get_contents(self):
00037 if self.changed_contents:
00038 return self.changed_contents
00039 return open(self.file_path).read()
00040
00041 def replace_contents(self, contents):
00042 self.changed_contents = contents
00043 self.lines = map(unicode.strip, unicode(contents).split('\n'))
00044
00045 def search_for_patterns(self, patterns):
00046 matches = []
00047 contents = self.get_contents()
00048 for pattern in patterns:
00049 matches += pattern.findall(contents)
00050 return matches
00051
00052 def search_lines_for_patterns(self, patterns):
00053 matches = []
00054 for line in self.lines:
00055 for pattern in patterns:
00056 m = pattern.search(line)
00057 if m:
00058 matches.append(m.groups())
00059 return matches
00060
00061 def search_lines_for_pattern(self, pattern):
00062 return self.search_lines_for_patterns([pattern])
00063
00064 def get_import_packages(self):
00065 pkgs = set()
00066 for match in self.search_lines_for_patterns(EXPRESSIONS):
00067 pkgs.add(match[0])
00068 if len(self.search_lines_for_pattern(ROSCPP)) > 0:
00069 pkgs.add('roscpp')
00070 return sorted(list(pkgs))
00071
00072 def get_dependencies(self):
00073 deps = []
00074 for pkg in self.get_import_packages():
00075 if is_package(pkg):
00076 deps.append(pkg)
00077 return deps
00078
00079 def get_external_python_dependencies(self):
00080 deps = []
00081 if self.language != 'python':
00082 return deps
00083
00084 for pkg in self.get_import_packages():
00085 p_dep = get_python_dependency(pkg)
00086 if p_dep:
00087 deps.append(p_dep)
00088 return deps
00089
00090 def is_executable(self):
00091 return os.access(self.file_path, os.X_OK)
00092
00093 def __lt__(self, other):
00094 return self.rel_fn < other.rel_fn
00095
00096 def __repr__(self):
00097 attribs = [self.language] + list(self.tags)
00098 return '%s (%s)' % (self.rel_fn, ', '.join(attribs))
00099
00100 def write(self):
00101 if self.changed_contents:
00102 with open(self.file_path, 'w') as f:
00103 f.write(self.changed_contents)