87 lines
2.9 KiB
Python
87 lines
2.9 KiB
Python
import os
|
|
import re
|
|
import glob
|
|
import itertools
|
|
|
|
|
|
class Related(object):
|
|
# Initializes the RelatedFiles object.
|
|
#
|
|
# file_path - the file to look related files for
|
|
# patterns - a dictionary of patterns in the following format:
|
|
# {"(.+)_controller.rb": ["*/the/paths/$1/**", "*/test/$1_controller_test.rb"]}
|
|
#
|
|
# The glob paths will have their $i replaced by the matched groups within the file name
|
|
# matcher.
|
|
def __init__(self, file_path, patterns, folders):
|
|
self.__file_path = file_path
|
|
self.__patterns = patterns
|
|
self.__root = self.__root(folders)
|
|
self.__files = []
|
|
self.__descriptions = []
|
|
self.__build()
|
|
|
|
# # Retrieves a list of all related descriptions.
|
|
def descriptions(self):
|
|
return self.__descriptions
|
|
|
|
# # Retrieves a list of all related files paths.
|
|
def files(self):
|
|
return self.__files
|
|
|
|
# Builds a list with all related files and sets self.descriptions and
|
|
# self.files.
|
|
def __build(self):
|
|
files = set()
|
|
|
|
file_path = self.__to_posixpath(self.__file_path)
|
|
|
|
# for each matching pattern
|
|
for regex, paths in self.__patterns.iteritems():
|
|
match = re.compile(regex).match(file_path)
|
|
if match:
|
|
# returns a flattened file list
|
|
files.update(self.__files_for_paths(regex, match, paths))
|
|
|
|
# sorts items
|
|
files = list(files)
|
|
files.sort()
|
|
|
|
self.__files = files
|
|
self.__descriptions = [self.__file_without_root(file) for file in files]
|
|
|
|
# Returns the root folder for the given file and folders
|
|
def __root(self, folders):
|
|
for folder in folders:
|
|
if self.__file_path.startswith(os.path.join(folder, "")):
|
|
return folder
|
|
|
|
# Retrieves a list of files fot the given match and paths
|
|
def __files_for_paths(self, regex, match, paths):
|
|
paths = [self.__replaced_path(match, path) for path in paths]
|
|
|
|
files = [glob.glob(os.path.join(self.__root, path)) for path in paths]
|
|
flattened = [self.__to_posixpath(path) for path in list(itertools.chain.from_iterable(files))]
|
|
|
|
# Ignores current file
|
|
if self.__file_path in flattened:
|
|
flattened.remove(unicode(self.__file_path))
|
|
|
|
return flattened
|
|
|
|
# Retrieves the file name without the root part.
|
|
def __file_without_root(self, file):
|
|
return os.path.basename(self.__root) + file[len(self.__root):]
|
|
|
|
# Retrieves a path with its interpolation vars replaces by the found groups
|
|
# on match.
|
|
def __replaced_path(self, match, path):
|
|
replaced_path = path
|
|
for i, group in enumerate(match.groups()):
|
|
replaced_path = replaced_path.replace("$%s" % (i + 1), group)
|
|
return replaced_path
|
|
|
|
# Converts paths to posixpaths.
|
|
def __to_posixpath(self, path):
|
|
return re.sub("\\\\", "/", path)
|