diff --git a/docx_search.py b/docx_search.py deleted file mode 100644 index 9bfc7ec..0000000 --- a/docx_search.py +++ /dev/null @@ -1,99 +0,0 @@ -import os -import logging -from docx import Document -from concurrent.futures import ThreadPoolExecutor -from datetime import datetime - -# Configure logger -log_format = '(%(asctime)s) [%(levelname)s] %(message)s' -log_file_name = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + '.log' -log_file_path = os.path.join(os.getcwd(), "logs", log_file_name) - -logging.basicConfig(level=logging.DEBUG, format=log_format, handlers=[ - logging.FileHandler(log_file_path, encoding='utf-8'), - logging.StreamHandler() -]) - -logger = logging.getLogger(__name__) - -def __check(fpath, target): - """ - Check if the target word is present in the paragraphs of a given Word document. - - @param fpath: The file path of the Word document. - @type fpath: str - @param target: The word to search for in the document. - @type target: str - @return: True if the word is found, False otherwise. - @rtype: bool - """ - try: - doc = Document(fpath) - for paragraph in doc.paragraphs: - if target in paragraph.text: - return True - return False - except Exception as e: - logger.error("Error processing %s: %s" % (fpath, e)) - return False - -def __process_file(file): - """ - Process a Word document file, checking if a target word is present. - - @param file: A tuple containing the file name and the target word. - @type file: tuple - @return: None - @rtype: None - """ - fname, target = file - fpath = os.path.join(os.getcwd(), fname) - if __check(fpath, target): - logger.info("'%s' found in %s" % (target, fname)) - else: - logger.debug("'%s' not found in %s" % (target, fname)) - -def __main(target_dir=None, target_word=None): - """ - Main function to search for a word in .docx files in the current directory. - - @param target_dir: The target directory to search for .docx files. If None, the current working directory is used. - @type target_dir: str or None - @param target_word: The word to search for. - @type target_word: str or None - @return: None - @rtype: None - """ - if target_word is None or target_word == '': - raise ValueError("target_word cannot be None or an empty string. Please pass in a valid value.") - - if target_dir is None: - target_dir = os.getcwd() - - file_list = [(fname, target_word) for fname in os.listdir(target_dir) if fname.endswith(".docx")] - - with ThreadPoolExecutor() as executor: - executor.map(__process_file, file_list) - -def docx_search(target_dir=None, target_word=None): - """ - Search for a target word in .docx files within a specified directory. - - This function calls the __main function to perform the actual search operation. - - @param target_dir: The target directory to search for .docx files. If None, the current working directory is used. - @type target_dir: str or None - @param target_word: The word to search for in the documents. - @type target_word: str or None - @return: None - @rtype: None - """ - import time - start_time = time.time() - __main(target_dir=target_dir, target_word=target_word) - end_time = time.time() - execution_time = end_time - start_time - logger.debug("Execution Time: %s seconds" % execution_time) - -if __name__ == "__main__": - docx_search() diff --git a/search.py b/search.py index d3bb879..9b1f7ed 100644 --- a/search.py +++ b/search.py @@ -1,24 +1,116 @@ -import argparse import os -from docx_search import docx_search +import logging +from docx import Document +from concurrent.futures import ThreadPoolExecutor +from datetime import datetime +import tkinter as tk +from tkinter import filedialog +# Configure logger +if not os.path.isdir('logs'): + os.mkdir('logs') -def main(): - parser = argparse.ArgumentParser(description='Search for a word in .docx files in a specified directory.') - parser.add_argument('--dir', dest='target_dir', type=str, default=os.getcwd(), - help='The target directory to search for .docx files. Defaults to the current working directory.') - parser.add_argument('--word', dest='target_word', type=str, - help='The word to search for in the documents. If not provided, the user will be prompted.') - args = parser.parse_args() +log_format = '(%(asctime)s) [%(levelname)s] %(message)s' +log_file_name = datetime.now().strftime('%Y-%m-%d_%H-%M-%S') + '.log' +log_file_path = os.path.join(os.getcwd(), "logs", log_file_name) - target_dir = args.target_dir - target_word = args.target_word +logging.basicConfig(level=logging.DEBUG, format=log_format, handlers=[ + logging.FileHandler(log_file_path, encoding='utf-8'), + logging.StreamHandler() +]) - if not target_word: - target_word = input("Enter the word to search for: ") +logger = logging.getLogger(__name__) - docx_search(target_dir=target_dir, target_word=target_word) +def __check(fpath, target): + try: + doc = Document(fpath) + for paragraph in doc.paragraphs: + if target in paragraph.text: + return True + return False + except Exception as e: + logger.error("Error processing %s: %s" % (fpath, e)) + return False +def __process_file(file): + fname, target = file + fpath = os.path.join(os.getcwd(), fname) + if __check(fpath, target): + logger.info("'%s' found in %s" % (target, fname)) + return fname + else: + logger.debug("'%s' not found in %s" % (target, fname)) + return None + +def perform_search(target_dir=None, target_word=None): + if target_word is None or target_word == '': + raise ValueError("target_word cannot be None or an empty string. Please pass in a valid value.") + + if target_dir is None: + target_dir = os.getcwd() + + file_list = [(fname, target_word) for fname in os.listdir(target_dir) if fname.endswith(".docx")] + + results = [] + with ThreadPoolExecutor() as executor: + results = list(executor.map(__process_file, file_list)) + + return [result for result in results if result is not None] + +class GUIFrontend: + def __init__(self, master): + self.master = master + self.master.title("Document Search App") + + self.target_word_label = tk.Label(master, text="Target Word:") + self.target_word_label.pack() + + self.target_word_entry = tk.Entry(master) + self.target_word_entry.pack() + + self.browse_button = tk.Button(master, text="Browse", command=self.browse_directory) + self.browse_button.pack() + + self.search_button = tk.Button(master, text="Search", command=self.search_documents) + self.search_button.pack() + + self.result_listbox = tk.Listbox(master) + self.result_listbox.pack() + self.result_listbox.bind("", self.open_file) + + # Initialize target_directory + self.target_directory = None + + def browse_directory(self): + directory = filedialog.askdirectory() + if directory: + self.target_directory = directory + + def search_documents(self): + target_word = self.target_word_entry.get() + if not target_word: + tk.messagebox.showerror("Error", "Target word cannot be empty.") + return + + if self.target_directory is None: + self.target_directory = os.getcwd() + + results = perform_search(target_dir=self.target_directory, target_word=target_word) + self.update_result_list(results) + + def update_result_list(self, results): + self.result_listbox.delete(0, tk.END) + for result in results: + self.result_listbox.insert(tk.END, result) + + def open_file(self, event): + selected_item = self.result_listbox.curselection() + if selected_item: + file_name = self.result_listbox.get(selected_item) + file_path = os.path.join(self.target_directory, file_name) + os.startfile(file_path) if __name__ == "__main__": - main() + root = tk.Tk() + app = GUIFrontend(root) + root.mainloop()