From a4b9e61da01caf00f7373901f791be56ca8b713c Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Wed, 24 Jul 2024 17:12:03 +0200 Subject: [PATCH 01/12] feat(gen): test replace concepts --- concepts.py | 1 + walk.py | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 concepts.py create mode 100644 walk.py diff --git a/concepts.py b/concepts.py new file mode 100644 index 0000000000..3d0c489b1f --- /dev/null +++ b/concepts.py @@ -0,0 +1 @@ +concepts_list = [] \ No newline at end of file diff --git a/walk.py b/walk.py new file mode 100644 index 0000000000..4c3378af17 --- /dev/null +++ b/walk.py @@ -0,0 +1,60 @@ +import os + +# TODO merge create_concepts_list function and replace_concepts function + +# This function turns a string into kebab case (kebab-case-is-like-this) for anchor links, for instance Public flexible IP adress -> #public-flexible-ip-address +def to_kebab_case(value): + return "-".join(value.lower().split()) + + +# This function retrieves the concepts of a product and , and store them as a list of list ([concept1, url1], [concept2, url2]) +def create_concepts_list(product): + # gets current working directory + directory_path=os.getcwd() + concepts_list = [] + for dirpath, dirnames, filenames in os.walk(f"{directory_path}/{product}"): + for filename in filenames: + if filename.endswith("concepts.mdx"): + file_path=f"{dirpath}/{filename}" + # print(file_path) + with open(file_path, 'r') as file: + for line in file: + concept_specs = [] + if line.startswith("## "): + # Removes "## " at the begining of concept line, and appends it the concept to concept_specs + concept_specs.append(line.strip("# \n").lower()) + # Creates the relative path and appends it to concept_specs + relative_path = file_path.removeprefix(directory_path).removesuffix(".mdx") + "/#" + to_kebab_case(line.strip("# \n")) + concept_specs.append(relative_path) + # Appends the list of concept specs (concept + link) to concepts_list + concepts_list.append(concept_specs) + return concepts_list + + +# create_concepts_list(input("Enter a category and product, e.g. \'compute/instances\' :")) +create_concepts_list("serverless/jobs") + +# TODO Create a function that takes a specific product (= subfolder such as object, functions, instances, etc. in contents) and walks the pages of this product to look for the first ocurrence of each concept, checks if the line contains a link to the concept (if line contains slug then skip), and if not, replaces the concept with "[concept](link to concept)". + +# TODO find a way to avoid errors with concepts that contain another concept ("permission" and "permission set" for instance), like: if concept + +def replace_concepts(product,concepts_list): + # gets current working directory + directory_path=os.getcwd() + # create absolute path to product folder with cwd (path/to/docs/content) + category and product path from user input (e.g. serverless/jobs or compute/instances) + product_path = f"{directory_path}/{product}" + for dirpath, dirnames, filenames in os.walk(product_path): + for filename in filenames: + file_path=f"{dirpath}/{filename}" + with open(file_path, 'r+') as file: + # Exclude product index files and concepts files (obviously) + if filename.endswith(".mdx") and filename != "index.mdx" and filename != "concepts.mdx": + for line in file: + # TODO Exclude frontmatter from line read/replace (if line starts with stuff from frontmatter or other method) + for concept in concepts_list: + # look for concept in concepts list, and replace concept with [concept](URL) if match. + if line.find(concepts_list[0]) != -1: + line.replace(concept, f"[{concept[0]}]({concept[1]})") + pass + +replace_concepts("serverless/jobs") From e7860f4c8e06fb1365cc5bc7427e860243c8991d Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Wed, 24 Jul 2024 18:06:02 +0200 Subject: [PATCH 02/12] feat(gen): test replace concepts --- concepts.py | 1 - walk.py | 33 +++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 11 deletions(-) delete mode 100644 concepts.py diff --git a/concepts.py b/concepts.py deleted file mode 100644 index 3d0c489b1f..0000000000 --- a/concepts.py +++ /dev/null @@ -1 +0,0 @@ -concepts_list = [] \ No newline at end of file diff --git a/walk.py b/walk.py index 4c3378af17..5efe9fa0d1 100644 --- a/walk.py +++ b/walk.py @@ -11,6 +11,7 @@ def to_kebab_case(value): def create_concepts_list(product): # gets current working directory directory_path=os.getcwd() + global concepts_list concepts_list = [] for dirpath, dirnames, filenames in os.walk(f"{directory_path}/{product}"): for filename in filenames: @@ -30,15 +31,9 @@ def create_concepts_list(product): concepts_list.append(concept_specs) return concepts_list - -# create_concepts_list(input("Enter a category and product, e.g. \'compute/instances\' :")) -create_concepts_list("serverless/jobs") - # TODO Create a function that takes a specific product (= subfolder such as object, functions, instances, etc. in contents) and walks the pages of this product to look for the first ocurrence of each concept, checks if the line contains a link to the concept (if line contains slug then skip), and if not, replaces the concept with "[concept](link to concept)". -# TODO find a way to avoid errors with concepts that contain another concept ("permission" and "permission set" for instance), like: if concept - -def replace_concepts(product,concepts_list): +def replace_concepts(product): # gets current working directory directory_path=os.getcwd() # create absolute path to product folder with cwd (path/to/docs/content) + category and product path from user input (e.g. serverless/jobs or compute/instances) @@ -49,12 +44,30 @@ def replace_concepts(product,concepts_list): with open(file_path, 'r+') as file: # Exclude product index files and concepts files (obviously) if filename.endswith(".mdx") and filename != "index.mdx" and filename != "concepts.mdx": + # add a first_ocurrence_replaced = False, and set it to True after replacement, and if True, break replacement "if" block to switch to next concept in the list + first_ocurrence_replaced = False + replaced_content = "" for line in file: # TODO Exclude frontmatter from line read/replace (if line starts with stuff from frontmatter or other method) for concept in concepts_list: # look for concept in concepts list, and replace concept with [concept](URL) if match. - if line.find(concepts_list[0]) != -1: - line.replace(concept, f"[{concept[0]}]({concept[1]})") - pass + if line.find(concept[0]) != -1 and not first_ocurrence_replaced: + # TODO find a way to avoid errors with concepts that contain another concept ("permission" and "permission set" for instance), like: if concept + + + # ----- TODO The lines below do not work properly ----- + # replacing the + new_line = line.replace(concept[0], f"[{concept[0]}]({concept[1]})") + replaced_content = f"{replaced_content}{new_line}\n" + file.write(replaced_content) + first_ocurrence_replaced = True + # --------------------------------------------------------- + + + + file.close() + +# create_concepts_list(input("Enter a category and product, e.g. \'compute/instances\' :")) +create_concepts_list("serverless/jobs") replace_concepts("serverless/jobs") From ed8c74d1fcf958c8a853e713f1ba45ee3a00805f Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Thu, 25 Jul 2024 18:07:05 +0200 Subject: [PATCH 03/12] docs(gen): update --- walk.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/walk.py b/walk.py index 5efe9fa0d1..eb446eef60 100644 --- a/walk.py +++ b/walk.py @@ -43,29 +43,24 @@ def replace_concepts(product): file_path=f"{dirpath}/{filename}" with open(file_path, 'r+') as file: # Exclude product index files and concepts files (obviously) + if filename.endswith(".mdx") and filename != "index.mdx" and filename != "concepts.mdx": # add a first_ocurrence_replaced = False, and set it to True after replacement, and if True, break replacement "if" block to switch to next concept in the list - first_ocurrence_replaced = False - replaced_content = "" - for line in file: + data = file.readlines() + for line in data: # TODO Exclude frontmatter from line read/replace (if line starts with stuff from frontmatter or other method) for concept in concepts_list: + first_ocurrence_replaced = 0 # look for concept in concepts list, and replace concept with [concept](URL) if match. - if line.find(concept[0]) != -1 and not first_ocurrence_replaced: + if concept[0] in line and first_ocurrence_replaced == 0 : # TODO find a way to avoid errors with concepts that contain another concept ("permission" and "permission set" for instance), like: if concept - - # ----- TODO The lines below do not work properly ----- - # replacing the + line_index = data.index(line) new_line = line.replace(concept[0], f"[{concept[0]}]({concept[1]})") - replaced_content = f"{replaced_content}{new_line}\n" - file.write(replaced_content) - first_ocurrence_replaced = True - # --------------------------------------------------------- - - + data[line_index] = new_line + first_ocurrence_replaced = 1 + print(new_line) - file.close() # create_concepts_list(input("Enter a category and product, e.g. \'compute/instances\' :")) create_concepts_list("serverless/jobs") From b1a6cd80effa7b764436759501773163c9583b1f Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Thu, 17 Oct 2024 18:27:45 +0200 Subject: [PATCH 04/12] chore(gen): update --- main.py | 9 +++++ walk.py | 119 ++++++++++++++++++++++++++++++-------------------------- 2 files changed, 72 insertions(+), 56 deletions(-) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000000..a7caaf3cbe --- /dev/null +++ b/main.py @@ -0,0 +1,9 @@ +from walk import AddLinkOnFirstConcept + +def main(): + # Create a TicTacToe instance and start the game + add_link_on_first_concept = AddLinkOnFirstConcept() + add_link_on_first_concept.replace() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/walk.py b/walk.py index eb446eef60..74a86d8e15 100644 --- a/walk.py +++ b/walk.py @@ -1,68 +1,75 @@ import os +import fileinput, sys -# TODO merge create_concepts_list function and replace_concepts function +class AddLinkOnFirstConcept: -# This function turns a string into kebab case (kebab-case-is-like-this) for anchor links, for instance Public flexible IP adress -> #public-flexible-ip-address -def to_kebab_case(value): - return "-".join(value.lower().split()) + def __init__(self): + pass -# This function retrieves the concepts of a product and , and store them as a list of list ([concept1, url1], [concept2, url2]) -def create_concepts_list(product): - # gets current working directory - directory_path=os.getcwd() - global concepts_list - concepts_list = [] - for dirpath, dirnames, filenames in os.walk(f"{directory_path}/{product}"): - for filename in filenames: - if filename.endswith("concepts.mdx"): - file_path=f"{dirpath}/{filename}" - # print(file_path) - with open(file_path, 'r') as file: - for line in file: - concept_specs = [] - if line.startswith("## "): - # Removes "## " at the begining of concept line, and appends it the concept to concept_specs - concept_specs.append(line.strip("# \n").lower()) - # Creates the relative path and appends it to concept_specs - relative_path = file_path.removeprefix(directory_path).removesuffix(".mdx") + "/#" + to_kebab_case(line.strip("# \n")) - concept_specs.append(relative_path) - # Appends the list of concept specs (concept + link) to concepts_list - concepts_list.append(concept_specs) - return concepts_list + def to_kebab_case(self, value): + return "-".join(value.lower().split()) -# TODO Create a function that takes a specific product (= subfolder such as object, functions, instances, etc. in contents) and walks the pages of this product to look for the first ocurrence of each concept, checks if the line contains a link to the concept (if line contains slug then skip), and if not, replaces the concept with "[concept](link to concept)". + def select_folder_to_process(self): + product=input("enter the product to process (in the \"category/product\" format: ") + return product -def replace_concepts(product): - # gets current working directory - directory_path=os.getcwd() - # create absolute path to product folder with cwd (path/to/docs/content) + category and product path from user input (e.g. serverless/jobs or compute/instances) - product_path = f"{directory_path}/{product}" - for dirpath, dirnames, filenames in os.walk(product_path): - for filename in filenames: - file_path=f"{dirpath}/{filename}" - with open(file_path, 'r+') as file: - # Exclude product index files and concepts files (obviously) + # This function retrieves the concepts of a product and , and store them as a list of list ([concept1, url1], [concept2, url2]) + def create_concepts_list(self, product): + # gets current working directory + directory_path=os.getcwd() + concepts_list = [] + for dirpath, dirnames, filenames in os.walk(f"{directory_path}/{product}"): + for filename in filenames: + if filename.endswith("concepts.mdx"): + file_path=f"{dirpath}/{filename}" + # print(file_path) + with open(file_path, 'r') as file: + for line in file: + concept_specs = [] + if line.startswith("## "): + # Removes "## " at the begining of concept line, and appends it the concept to concept_specs + concept_specs.append(line.strip("# \n").lower()) + # Creates the relative path and appends it to concept_specs + concept_anchor = file_path.removeprefix(directory_path).removesuffix(".mdx") + "/#" + self.to_kebab_case(line.strip("# \n")) + concept_specs.append(concept_anchor) + # Appends the list of concept specs (concept + concept_anchor) to concepts_list + concepts_list.append(concept_specs) + return concepts_list + def create_files_to_update_list(self, product): + files_list = [] + for dirpath, dirnames, filenames in os.walk(product): + for filename in filenames: if filename.endswith(".mdx") and filename != "index.mdx" and filename != "concepts.mdx": - # add a first_ocurrence_replaced = False, and set it to True after replacement, and if True, break replacement "if" block to switch to next concept in the list - data = file.readlines() - for line in data: - # TODO Exclude frontmatter from line read/replace (if line starts with stuff from frontmatter or other method) - for concept in concepts_list: - first_ocurrence_replaced = 0 - # look for concept in concepts list, and replace concept with [concept](URL) if match. - if concept[0] in line and first_ocurrence_replaced == 0 : - # TODO find a way to avoid errors with concepts that contain another concept ("permission" and "permission set" for instance), like: if concept + file_path = f"{dirpath}/{filename}" + files_list.append(file_path) + return files_list - line_index = data.index(line) - new_line = line.replace(concept[0], f"[{concept[0]}]({concept[1]})") - data[line_index] = new_line - first_ocurrence_replaced = 1 - print(new_line) + def replace_string_in_file(file_path, old_string, new_string): + with open(file_path, "r") as current_file: + content = current_file.read() + file.close() + # Replace the old string with the new string + new_content = content.replace(old_string, new_string, 1) -# create_concepts_list(input("Enter a category and product, e.g. \'compute/instances\' :")) -create_concepts_list("serverless/jobs") - -replace_concepts("serverless/jobs") + # Open the file in write mode to overwrite with new content + with open(file_path, 'w') as file: + file.write(new_content) + file.close() + + return + + def replace(self): + # product = self.select_folder_to_process() + product = "serverless/jobs" + concepts_list = self.create_concepts_list(product) + files_list = self.create_files_to_update_list(product) + for file in files_list: + for concept in concepts_list: + old_string = concept[0] + new_string = f"[{concept[0]}]({concept[1]})" + self.replace_string_in_file(file, old_string, new_string) + + return From 1563fc3335e1e0d852b7370be80adf1031e2a1d7 Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Fri, 18 Oct 2024 11:34:53 +0200 Subject: [PATCH 05/12] chore(gen): THE REPLACE WORKS ! but no edge case handling --- walk.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/walk.py b/walk.py index 74a86d8e15..c85fff9a36 100644 --- a/walk.py +++ b/walk.py @@ -46,20 +46,21 @@ def create_files_to_update_list(self, product): files_list.append(file_path) return files_list - def replace_string_in_file(file_path, old_string, new_string): - with open(file_path, "r") as current_file: - content = current_file.read() - file.close() + def replace_string_in_file(self, current_file, old_string, new_string): + with open(current_file, "r+") as file_to_read: + content = file_to_read.read() + # file_to_read.close() - # Replace the old string with the new string - new_content = content.replace(old_string, new_string, 1) + # Replace the old string with the new string + new_content = content.replace(old_string, new_string, 1) - # Open the file in write mode to overwrite with new content - with open(file_path, 'w') as file: - file.write(new_content) - file.close() - - return + # Open the file in write mode to overwrite with new content + # with open(current_file, 'w') as file_to_write: + file_to_read.seek(0) + file_to_read.truncate(0) + print(file_to_read) + file_to_read.write(new_content) + return def replace(self): # product = self.select_folder_to_process() @@ -70,6 +71,9 @@ def replace(self): for concept in concepts_list: old_string = concept[0] new_string = f"[{concept[0]}]({concept[1]})" - self.replace_string_in_file(file, old_string, new_string) + current_file=file + self.replace_string_in_file(current_file, old_string, new_string) + # Add test new content and error handling before printing line below + print(f"{old_string} replaced by {new_string} in file {file}.") return From 38b33824921d66bc3f742ecfdd76d87fa863cee3 Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Fri, 18 Oct 2024 12:19:04 +0200 Subject: [PATCH 06/12] chore(gen): Add TODO and logic for edge case handling --- walk.py | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 2 deletions(-) diff --git a/walk.py b/walk.py index c85fff9a36..65a702cef0 100644 --- a/walk.py +++ b/walk.py @@ -1,5 +1,4 @@ import os -import fileinput, sys class AddLinkOnFirstConcept: @@ -75,5 +74,90 @@ def replace(self): self.replace_string_in_file(current_file, old_string, new_string) # Add test new content and error handling before printing line below print(f"{old_string} replaced by {new_string} in file {file}.") - return + + +# TODO + +# - Check if concept is already present in file before replacing + +# - Add tests + +# - Address case where concept is part of another concept (e.g. "serverless" and "Serverless Framework") + +# - Make sure capitalized concepts are properly matched and reproduced + +# - Try a different replace method using readlines(), then looping through each line to search for concept and easily exclude frontmatter + +# - Frontmatter: +# - Enter frontmatter section: If current_line contains "---\n" then switch +# on frontmatter_check = True +# - If frontmatter_check = True and current_line == "---\n" then switch off +# frontmatter_check = False +# - If frontmatter_check = True then skip line +# +# - Code block: +# - Same as frontmatter but with "```" + +# - Monospace +# - if concept is between "`[any string]`" and "`[any string]`" then DO NOT skip line +# as +# - if concept is between "`[any string]" and "[any string]`" then skip line + +# To check programmatically if a markdown string is monospace or bold or italics, ChatGPT provides the answer below: + +# Example in Python with markdown-it-py: + +# You can use the markdown-it-py library to parse the Markdown into tokens and inspect them to detect different formatting. +# Install the library: + +# bash + +# pip install markdown-it-py + +# Code Example: + +# python + +# from markdown_it import MarkdownIt + +# # Function to check markdown formatting +# def check_formatting(markdown_text): +# md = MarkdownIt() +# tokens = md.parse(markdown_text) + +# for token in tokens: +# if token.type == 'inline': +# for child in token.children: +# if child.type == 'code_inline': +# print("Monospace text:", child.content) +# elif child.type == 'strong_open': +# print("Bold text detected") +# elif child.type == 'em_open': +# print("Italics text detected") + +# # Example usage +# markdown_string = "Here is some **bold** text, *italics*, and `monospace` code." + +# check_formatting(markdown_string) + +# Explanation: + +# The MarkdownIt parser breaks down the Markdown string into tokens. +# We loop through these tokens and check for specific types (code_inline for inline monospace, strong_open for bold, and em_open for italics). + +# Output: + +# scss + +# Bold text detected +# Italics text detected +# Monospace text: monospace + +# Parsing Bold, Italics, and Monospace + +# Monospace (inline code) is detected by the code_inline token. +# Bold text is detected by strong_open and strong_close tokens. +# Italics text is detected by em_open and em_close tokens. + +# This approach allows you to programmatically check for these specific formatting patterns in any Markdown string. From 1be5ed1c6edb0fe246fc2e392a939de1c493f4a3 Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Fri, 18 Oct 2024 12:44:07 +0200 Subject: [PATCH 07/12] chore(gen): rename files properly --- main.py | 2 +- walk.py => replace_concepts.py | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename walk.py => replace_concepts.py (100%) diff --git a/main.py b/main.py index a7caaf3cbe..29de858798 100644 --- a/main.py +++ b/main.py @@ -1,4 +1,4 @@ -from walk import AddLinkOnFirstConcept +from replace_concepts import AddLinkOnFirstConcept def main(): # Create a TicTacToe instance and start the game diff --git a/walk.py b/replace_concepts.py similarity index 100% rename from walk.py rename to replace_concepts.py From 0dd12a0851daecbb0a6750ef9807a200556d32bd Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Mon, 21 Oct 2024 11:53:03 +0200 Subject: [PATCH 08/12] chore(gen): WORKING VERSION without edge case handling --- replace_concepts.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/replace_concepts.py b/replace_concepts.py index 65a702cef0..bfe62c9fda 100644 --- a/replace_concepts.py +++ b/replace_concepts.py @@ -46,19 +46,13 @@ def create_files_to_update_list(self, product): return files_list def replace_string_in_file(self, current_file, old_string, new_string): - with open(current_file, "r+") as file_to_read: - content = file_to_read.read() - # file_to_read.close() - - # Replace the old string with the new string + with open(current_file, "r+") as file_to_process: + content = file_to_process.read() new_content = content.replace(old_string, new_string, 1) - - # Open the file in write mode to overwrite with new content - # with open(current_file, 'w') as file_to_write: - file_to_read.seek(0) - file_to_read.truncate(0) - print(file_to_read) - file_to_read.write(new_content) + file_to_process.seek(0) + file_to_process.truncate(0) + print(file_to_process) + file_to_process.write(new_content) return def replace(self): @@ -66,20 +60,26 @@ def replace(self): product = "serverless/jobs" concepts_list = self.create_concepts_list(product) files_list = self.create_files_to_update_list(product) + # Looks for each concept in each page for file in files_list: for concept in concepts_list: old_string = concept[0] new_string = f"[{concept[0]}]({concept[1]})" current_file=file - self.replace_string_in_file(current_file, old_string, new_string) - # Add test new content and error handling before printing line below - print(f"{old_string} replaced by {new_string} in file {file}.") + # Check if concept already has link to concepts page + with open(file) as file_to_check: + if new_string not in file_to_check.read(): + self.replace_string_in_file(current_file, old_string, new_string) + # Add test new content and error handling before printing line below + print(f"{old_string} replaced by {new_string} in file {file}.") + else: + print(f"{new_string} already in {file_to_check}") return # TODO -# - Check if concept is already present in file before replacing +# - DONE - Check if concept is already present in file before replacing # - Add tests From 94860982bd9f5227600e7470c888c5032621a59d Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Mon, 21 Oct 2024 11:54:30 +0200 Subject: [PATCH 09/12] chore(gen): add trailing space --- main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.py b/main.py index 29de858798..92acdabdfe 100644 --- a/main.py +++ b/main.py @@ -6,4 +6,4 @@ def main(): add_link_on_first_concept.replace() if __name__ == '__main__': - main() \ No newline at end of file + main() From 1aee5b6aa7fd6e6348727046e409c82c0f0b9d98 Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Mon, 21 Oct 2024 15:52:54 +0200 Subject: [PATCH 10/12] chore(gen): added line by line processing WORKING --- replace_concepts.py | 47 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/replace_concepts.py b/replace_concepts.py index bfe62c9fda..0e9925e4c8 100644 --- a/replace_concepts.py +++ b/replace_concepts.py @@ -1,7 +1,9 @@ import os + class AddLinkOnFirstConcept: + def __init__(self): pass @@ -9,10 +11,12 @@ def __init__(self): def to_kebab_case(self, value): return "-".join(value.lower().split()) + def select_folder_to_process(self): product=input("enter the product to process (in the \"category/product\" format: ") return product + # This function retrieves the concepts of a product and , and store them as a list of list ([concept1, url1], [concept2, url2]) def create_concepts_list(self, product): # gets current working directory @@ -36,6 +40,7 @@ def create_concepts_list(self, product): concepts_list.append(concept_specs) return concepts_list + def create_files_to_update_list(self, product): files_list = [] for dirpath, dirnames, filenames in os.walk(product): @@ -44,7 +49,21 @@ def create_files_to_update_list(self, product): file_path = f"{dirpath}/{filename}" files_list.append(file_path) return files_list + + + def check_if_concept_in_other_concept(concepts_list): + concepts = concepts_list + control_list = concepts_list + skip_concept = False + for i in concepts: + for j in control_list: + if i in j: + skip_concept = True + print(f"Concept \"{i}\" is contained in \n{j}\n") + return skip_concept + + # Working implementation def replace_string_in_file(self, current_file, old_string, new_string): with open(current_file, "r+") as file_to_process: content = file_to_process.read() @@ -55,6 +74,20 @@ def replace_string_in_file(self, current_file, old_string, new_string): file_to_process.write(new_content) return + # Version with line-by-line processing + def line_by_line_replace(self, current_file, old_string, new_string): + with open(current_file, "r") as file_to_process: + lines_of_file = file_to_process.readlines() + # iterates over each line of the file + for i in range(len(lines_of_file)): + if old_string in lines_of_file[i]: + # replace concept once in the line + lines_of_file[i] = lines_of_file[i].replace(old_string, new_string, 1) + break + with open(current_file, "w") as file_to_write: + file_to_write.writelines(lines_of_file) + return + def replace(self): # product = self.select_folder_to_process() product = "serverless/jobs" @@ -63,17 +96,19 @@ def replace(self): # Looks for each concept in each page for file in files_list: for concept in concepts_list: + skip_concept = False old_string = concept[0] new_string = f"[{concept[0]}]({concept[1]})" current_file=file # Check if concept already has link to concepts page with open(file) as file_to_check: - if new_string not in file_to_check.read(): - self.replace_string_in_file(current_file, old_string, new_string) - # Add test new content and error handling before printing line below - print(f"{old_string} replaced by {new_string} in file {file}.") - else: - print(f"{new_string} already in {file_to_check}") + if new_string not in file_to_check.read() and skip_concept == False: + self.line_by_line_replace(current_file, old_string, new_string) + # Add test new content and error handling before printing line below + print(f"{old_string} replaced by {new_string} in file {file}.") + else: + print(f"{new_string} already in {file_to_check}") + file_to_check.close() return From da9d49d0a9975bccb869401f1042e026dd8573c0 Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Mon, 21 Oct 2024 15:59:11 +0200 Subject: [PATCH 11/12] chore(gen): remove whole file approach --- replace_concepts.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/replace_concepts.py b/replace_concepts.py index 0e9925e4c8..39cf230e4f 100644 --- a/replace_concepts.py +++ b/replace_concepts.py @@ -62,19 +62,9 @@ def check_if_concept_in_other_concept(concepts_list): skip_concept = True print(f"Concept \"{i}\" is contained in \n{j}\n") return skip_concept + - # Working implementation - def replace_string_in_file(self, current_file, old_string, new_string): - with open(current_file, "r+") as file_to_process: - content = file_to_process.read() - new_content = content.replace(old_string, new_string, 1) - file_to_process.seek(0) - file_to_process.truncate(0) - print(file_to_process) - file_to_process.write(new_content) - return - - # Version with line-by-line processing + # WORKING - Version with line-by-line processing def line_by_line_replace(self, current_file, old_string, new_string): with open(current_file, "r") as file_to_process: lines_of_file = file_to_process.readlines() From c7e7b9344bb4631b9f7683b276c70089ec63548c Mon Sep 17 00:00:00 2001 From: SamyOubouaziz Date: Wed, 23 Oct 2024 18:50:42 +0200 Subject: [PATCH 12/12] feat(gen): add skip line mechanism --- replace_concepts.py | 46 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/replace_concepts.py b/replace_concepts.py index 39cf230e4f..98ba8ba3a1 100644 --- a/replace_concepts.py +++ b/replace_concepts.py @@ -62,18 +62,47 @@ def check_if_concept_in_other_concept(concepts_list): skip_concept = True print(f"Concept \"{i}\" is contained in \n{j}\n") return skip_concept - + # Check if occurrence is in code block, frontmatter, or monospace + def check_if_skip_line(self, current_line, skip_line): + # Check if in frontmatter + + if current_line == '---\n' and skip_line == False: + skip_line = True + return skip_line + + if current_line == '---\n' and skip_line == True: + skip_line = False + return skip_line + + + # Check if in code block + if current_line == '```\n' and skip_line == False: + skip_line = True + return skip_line + + if current_line == '```\n' and skip_line == True: + skip_line = False + return skip_line + + else: + return skip_line + + # TODO Check if in inline code + # WORKING - Version with line-by-line processing def line_by_line_replace(self, current_file, old_string, new_string): with open(current_file, "r") as file_to_process: lines_of_file = file_to_process.readlines() + skip_line_toggle = False # iterates over each line of the file for i in range(len(lines_of_file)): - if old_string in lines_of_file[i]: - # replace concept once in the line - lines_of_file[i] = lines_of_file[i].replace(old_string, new_string, 1) - break + skip_line = self.check_if_skip_line(lines_of_file[i], skip_line_toggle) + skip_line_toggle = skip_line + if old_string in lines_of_file[i] and skip_line == False: + # replace concept once in the line + lines_of_file[i] = lines_of_file[i].replace(old_string, new_string, 1) + break with open(current_file, "w") as file_to_write: file_to_write.writelines(lines_of_file) return @@ -86,13 +115,13 @@ def replace(self): # Looks for each concept in each page for file in files_list: for concept in concepts_list: - skip_concept = False old_string = concept[0] new_string = f"[{concept[0]}]({concept[1]})" current_file=file # Check if concept already has link to concepts page with open(file) as file_to_check: - if new_string not in file_to_check.read() and skip_concept == False: + if new_string not in file_to_check.read(): + # Replace first occurrence of concept self.line_by_line_replace(current_file, old_string, new_string) # Add test new content and error handling before printing line below print(f"{old_string} replaced by {new_string} in file {file}.") @@ -101,7 +130,6 @@ def replace(self): file_to_check.close() return - # TODO # - DONE - Check if concept is already present in file before replacing @@ -112,6 +140,8 @@ def replace(self): # - Make sure capitalized concepts are properly matched and reproduced +# - Address case when concept is in plural form (e.g. [job](link)s ). concept must have space or punctuation after (or no letter). + # - Try a different replace method using readlines(), then looping through each line to search for concept and easily exclude frontmatter # - Frontmatter: