Added sher.py

- sher.py for searching in directories and files
- miscutils.py containing a search engine
- modified fsutils.py: Added a DirInfo class
- added test configuration
pull/8/head
Julius 6 years ago
parent 685ce33d9a
commit a027c4038e

@ -56,6 +56,8 @@ jobs:
. venv/bin/activate
python riddle2.py -t
- store_artifacts:
path: test-reports
destination: test-reports
- run:
name: run tests for sher.py
command: |
. venv/bin/activate
python sher.py -d . -q "."

@ -68,3 +68,59 @@ class FileInfo:
self._init_info(dest)
else:
self._init_info(dest)
class DirInfo:
""" A simple wrapper around the os path functions that returns basic directory info
and let's you peform basic directory tasks."""
def __init__(self, dirname: str):
self._init_info(dirname)
def _init_info(self, dirname: str):
""" Set's all the required variables for performing file tasks and to
access when working with the file object. """
# stringvars
self._path = os.path.normpath(dirname.replace('\\', '/')).encode('utf-8')
if not os.path.isdir(self._path):
raise Exception("Not a Directory")
self.parent_dir, self.basename = os.path.split(self._path)
self.fullname = os.path.join(self.parent_dir, self.basename)
# boolvars
self.exist = os.path.exists(self.fullname)
self.ismount = self.islink = False
if self.exist:
self.ismount = os.path.ismount(self.fullname)
self.islink = os.path.islink(self.fullname)
def get_content(self) -> list:
""" Returns the content of the directory without subdirectory contents. """
return os.listdir(self.fullname)
def get_full_content(self) -> list:
""" Returns the content of the direcdtory tree. """
content = []
for dirname, dirnames, filenames in os.walk(self.fullname):
# print path to all subdirectories first.
for subdirname in dirnames:
content.append(os.path.join(dirname, subdirname).decode('utf-8'))
# print path to all filenames.
for filename in filenames:
content.append(os.path.join(dirname, filename).decode('utf-8'))
return content
def delete(self):
shutil.rmtree(self.fullname)
def delete_empty(self):
""" Deletes the directory if it is empty. Raises an Exception if it is not. """
if len(self.get_content()):
raise Exception('Directory not empty')
else:
self.delete()
def create(self):
if not self.exist:
os.mkdir(self.fullname)
self._init_info(self.fullname)

@ -0,0 +1,64 @@
class SearchEngine:
""" A Search engine that searches a list of strings for
specific string occurences. """
def __init__(self, data: list):
self.data = data
def search(self, q: str) -> tuple:
q = q.lower()
_score_dic = {}
# checking for query syntax
if '"' in q:
_static_q = q.split('"')[1::2]
print("STATIC: {}".format(_static_q))
_flex_q = q.split('"')[0::2]
print("FLEX: {}".format(_flex_q))
for _static_single in _static_q: # search for whole term
_score_dic.update(self._static_search(_static_single))
for _flex_single in _flex_q: # search for single words
_score_dic.update(self._flex_search(_flex_single.split(' ')))
else:
_flex_q = q.split(' ')
print("FLEX: {}".format(_flex_q))
_score_dic.update(self._flex_search(_flex_q))
returnable = sorted(_score_dic, key=_score_dic.get)
returnable.reverse()
return tuple(returnable) # change into a tuple because the order matters
def _flex_search(self, q: list, data: list=None) -> dict: # single word search
_rescore_dic = {} # returnable score dictionary
if not data:
data = self.data
if len(q) > 0:
for entry in data:
for sin_query in q:
if sin_query in entry.lower() and len(sin_query) > 0:
if entry not in _rescore_dic.keys():
_rescore_dic[entry] = 0
# for each appereance the rank score increases
_rescore_dic[entry] += (entry.lower().count(sin_query) / 10) + 0.9
return _rescore_dic
def _static_search(self, q: str, data: list=None) -> dict: # whole term search
_rescore_dic = {}
if not data:
data = self.data
if len(q) > 0:
for entry in data:
if q in entry.lower():
if entry not in _rescore_dic.keys():
_rescore_dic[entry] = 0
_rescore_dic[entry] += (entry.lower().count(q) * 100)
return _rescore_dic

@ -0,0 +1,59 @@
import os
import optparse
from lib import miscutils, fsutils
sources = {}
def optparse_init() -> tuple:
parser = optparse.OptionParser()
parser.add_option('-f', '--file', type='string', dest='s_file', help='Searching lines in the given file.')
parser.add_option('-d', '--directory', type='string', dest='s_dir', help='Searching files in a directorys.')
parser.add_option('-q', '--query', type='string', dest='query', help='The search term.')
parser.add_option('-l', '--loop', action='store_true', default=False, dest='loop', help='Looping over the input?')
return parser.parse_args()
def read_file_source(fname):
finfo = fsutils.FileInfo(fname)
if finfo.exist:
with finfo.open('r') as f:
return list(f.readlines())
def read_directory_source(dirname):
""" Reading the contents of the directory """
dinfo = fsutils.DirInfo(dirname)
if dinfo.exist:
return dinfo.get_full_content()
def main():
options, args = optparse_init()
engines = []
if options.s_file:
e_file = miscutils.SearchEngine(read_file_source(options.s_file))
engines.append(e_file)
if options.s_dir:
e_dir = miscutils.SearchEngine(read_directory_source(options.s_dir))
engines.append(e_dir)
while True:
if options.query and not options.loop:
query = options.query
else:
query = input('Search: ')
for engine in engines:
for res in engine.search(query):
print(res)
print('- - - - -')
if not options.loop:
break
if __name__ == '__main__':
main()
Loading…
Cancel
Save