From 331e2776c3f2504ce9662a0e991169bfe8dda365 Mon Sep 17 00:00:00 2001 From: Mohamed Shakib <50780268+Mo-Shakib@users.noreply.github.com> Date: Tue, 29 Oct 2024 19:51:14 +0600 Subject: [PATCH] Update README_automation.py Version - v3.0.0 --- README_automation.py | 230 ++++++++++++++++++++++++++++--------------- 1 file changed, 153 insertions(+), 77 deletions(-) diff --git a/README_automation.py b/README_automation.py index 0fa0adb..b939dfb 100644 --- a/README_automation.py +++ b/README_automation.py @@ -1,9 +1,9 @@ # GitHub README.md automation script by Mohammad Shakib # This script can automatically update the readme file based on the files present in the repo. -# Last update: 10-01-2022 -# Version - v2.0.0 +# Last update: 29-11-2024 +# Version - v3.0.0 -import os, time, pytz, git, markdown +import os, time, pytz, git, markdown, re from LeetCode_problem_info import problem_info from datetime import datetime from git.objects.commit import Commit @@ -11,92 +11,168 @@ # - - - - - - - - - - - - - - - - - - - - - - - - def get_date(epoch_time): return datetime.fromtimestamp(epoch_time) - -submissionDate_fileName = {} -dir_path = os.path.dirname(os.path.realpath(__file__)) -repo = git.Repo(dir_path) -tree = repo.tree() - -for blob in tree.trees[1]: - commit = next(repo.iter_commits(paths=blob.path, max_count=1)) - date = str(get_date(commit.committed_date))[:10] - submissionDate_fileName[blob.name] = date - -# - - - - - - - - - - - - - - - - - - - - - - - - - - -all_files = [] -all_files_id = [] -file_data = {} -submissionTime = {} -skip_files = ['test.py', 'main.py'] -driver = problem_info.Get_Info() -problem_details = driver.all_data() -readme_edit = open("README.md", "w") - -for files in os.listdir("Python"): - if files.endswith(".py"): - if files not in skip_files: - all_files.append(files) - file_id = files.split(".")[0] - all_files_id.append(file_id) - file_data[file_id] = files + "." + submissionDate_fileName[files] - print(submissionDate_fileName[files]) - -newfiles = all_files_id -newfiles_data = {} -for i in newfiles: - newfiles_data[i] = file_data[i] - -print('[*] Updating README.md...') - -readme_edit.write('# LeetCode Solutions\n\n') -readme_edit.write('[![wakatime](https://wakatime.com/badge/github/Mo-Shakib/LeetCode.svg)](https://wakatime.com/badge/github/Mo-Shakib/LeetCode) ') -readme_edit.write('![example workflow](https://github.com/Mo-Shakib/LeetCode/actions/workflows/Readme-automation.yml/badge.svg)\n\n') -readme_edit.write('\n') -readme_edit.write('\n\n[LeetCode](https://leetcode.com/) is a website containing many algorithm questions. Most of them are real interview questions of Google, Facebook, LinkedIn, Apple, etc. and it always help to sharp our algorithm skills. This repo shows my solutions in Python. Please feel free to reference and STAR to support this repo, thank you!\n\n\n') - -readme_edit.write('| # | Title | Solution | Difficulty | Submission Date |\n') -readme_edit.write('| ----- | ----- | -------- | ---------- | --------------- |\n') - -newfiles_data = {k: v for k, v in sorted(newfiles_data.items(), key = lambda item: item[1][-10:])} - -for key, file_data in newfiles_data.items(): - print(f'[+] Adding: {file_data[:-11]}') - problem_id = newfiles_data[key].split(".")[0] - url = "https://leetcode.com/problems/" + newfiles_data[key].split(".")[1] - problem_name = newfiles_data[key].split(".")[1].strip() - problem_name = problem_name.replace("-", " ") - date = newfiles_data[key].split(".")[3] - filePath = "Python/" + newfiles_data[key][:-11] - try: - problem_info = problem_details[int(problem_id)] - except KeyError: - problem_info = ['-','-','-'] - readme_edit.write(f"| **{problem_id}** | [{problem_name.capitalize()}]({url}) | [Python]({filePath}) | {problem_info[2]}| {date} |\n") - -current_time = datetime.now(pytz.timezone('Asia/Dhaka')) -current_time = current_time.strftime("%d %B, %Y | %H:%M:%S") + +def create_problem_description_file(file_path, root_directory): + filename = os.path.basename(file_path) + description_filename = os.path.splitext(filename)[0] + ".md" # Save description as .md + description_path = os.path.join(root_directory, description_filename) + + with open(file_path, 'r') as file: + lines = file.readlines() + + title = "" + url = "" + description_lines = [] + code_lines = [] + start_description = False + start_code = False + + for line in lines: + if re.match(r"# \[\d+\]", line): # Detects line containing "[ID] Title" + title_info = line.split(" ", 2) + problem_id = title_info[1].strip("[]") + title = title_info[2].strip() + elif "https://" in line: # Detects URL line + url = line.strip("# ").strip() + elif line.strip().startswith("#") and start_description: # Adds lines to the description + description_lines.append(line.strip("# ").strip()) + elif line.strip().startswith("#") and "Given" in line: # Start description collection at "Given" + start_description = True + description_lines.append(line.strip("# ").strip()) + + # Extract code between # @lc code=start and # @lc code=end, excluding those markers + if line.strip() == "# @lc code=start": + start_code = True + elif line.strip() == "# @lc code=end": + start_code = False + elif start_code: + code_lines.append(line.rstrip()) + + + # Description + description_content = f"# {title}\n\n**URL**: [{url}]({url})\n\n**Description**:\n" + "\n".join(description_lines[2:-2]) + "\n\n" + code_content = "\n".join(code_lines) + + formatted_description_content = format_description(description_content) + + # Save to the root directory as a .md file (overwrite if exists) + with open(description_path, 'w') as desc_file: + desc_file.write(formatted_description_content) + desc_file.write("**Solution Code**:\n") + desc_file.write("```python\n") + desc_file.write(code_content) + desc_file.write("\n```\n") + + print(f"[+] Problem description file created at {description_path}") + return problem_id, title, url, description_filename + +def format_description(content): + lines = content.splitlines() + formatted_lines = [] + + in_code_block = False # Track whether we're currently in a code block + + for line in lines: + if line.startswith("Example") or line.startswith("Constraints"): + # Close previous code block if applicable + if in_code_block: + formatted_lines.append("```") + in_code_block = False + + formatted_lines.append('\n __'+line+'__') # Add the example or constraint line + + formatted_lines.append("```") # Open a new code block + in_code_block = True # We're in a code block now + elif line.startswith("**Code**:") or line.startswith("Follow up:"): + # Close the last code block when reaching "**Code**:" + if in_code_block: + formatted_lines.append("```") + in_code_block = False + formatted_lines.append(line) # Add the "**Code**:" line + elif line.startswith('**Description**'): + formatted_lines.append("\n**Description**") + + else: + # Add line normally if it's not empty + if line: + if in_code_block: + formatted_lines.append(line) + else: + formatted_lines.append(line) + + # Close the last code block if we're still in one + if in_code_block: + formatted_lines.append("```") + formatted_lines.append('\n') + return "\n".join(formatted_lines) + + +def process_directory(root_directory): + subdirectories = ["easy", "medium", "hard"] + + # Custom header for the README.md file + readme_header = """# LeetCode Solutions + +[![wakatime](https://wakatime.com/badge/github/Mo-Shakib/LeetCode.svg)](https://wakatime.com/badge/github/Mo-Shakib/LeetCode) ![example workflow](https://github.com/Mo-Shakib/LeetCode/actions/workflows/Readme-automation.yml/badge.svg) + + + +[LeetCode](https://leetcode.com/) is a website containing many algorithm questions. Most of them are real interview questions of Google, Facebook, LinkedIn, Apple, etc. and it always help to sharp our algorithm skills. This repo shows my solutions in Python. Please feel free to reference and STAR to support this repo, thank you! +""" + + readme_lines = [readme_header] + + for subdir in subdirectories: + dir_path = os.path.join(root_directory, subdir) + if os.path.exists(dir_path): + # Start new section for each difficulty level + readme_lines.append(f"\n\n## {subdir.capitalize()}\n") + for filename in os.listdir(dir_path): + if filename.endswith(".py"): + file_path = os.path.join(dir_path, filename) + problem_id, title, url, description_filename = create_problem_description_file(file_path, root_directory) + # Add entry to the section's list format + readme_lines.append(f"[{title}]({url}) - [Solution]({description_filename})") + + # Create or overwrite README.md file in the root directory + readme_path = os.path.join(root_directory, "README.md") + with open(readme_path, 'w') as readme_file: + readme_file.write("\n".join(readme_lines)) + + print(f"[+] README.md file created at {readme_path}") + +# Example usage +root_directory = os.path.dirname(__file__) # Set root directory to current script location +process_directory(root_directory) + +# print('[=] Task Successfull') + +# current_time = datetime.now(pytz.timezone('Asia/Dhaka')) +# current_time = current_time.strftime("%d %B, %Y | %H:%M:%S") # readme_edit.write('\n\n\n') # readme_edit.write(f'__Last update:__ {current_time}') + + + print('[=] README.md updated.') -readme_edit.close() +# readme_edit.close() time.sleep(1) # Writing website for the readme -print('Writing index.html file') -markdown.markdownFromFile( - input='README.md', - output='index.html', - encoding='utf8', -) -print('Done writing index.html') +# print('Writing index.html file') +# markdown.markdownFromFile( +# input='README.md', +# output='index.html', +# encoding='utf8', +# ) +# print('Done writing index.html') print("[+] Adding changes to GitHub") commit_message = "Updated by automated commit 🤖" -repo.git.add('README.md','index.html') +repo.git.add('.') repo.git.commit('-m', commit_message, author='Shakib') origin = repo.remote(name='origin') origin.push()