On Thu, Mar 20, 2025 at 10:16 AM David G. Johnston <david.g.johns...@gmail.com> wrote: > > In short, ready to commit (see last paragraph below however), but the > committer will need to run the python script at the time of commit on the > then-current tree. >
hi. more explanation, since the python script seems quite large... each <sect1 id="functions-XXX"> in doc/src/sgml/func.sgml corresponds to each individual section in [1]. each <sect1 id="functions-XXX"> within func.sgml is unique. if you try to rename it, having two <sect1 id="functions-logical"> will error out saying something like: ../../Desktop/pg_src/src6/postgres/doc/src/sgml/postgres.sgml:199: element sect1: validity error : ID functions-logical already defined see [2] also. Based on this, we can use the literal string <sect1 id="functions-XXX"> to perform pattern matching and identify the line numbers that mark the start and end of each <sect1> section. The polished v2 python script use the following steps for splitting func.sgml into several pieces: 0. For each 9.X section listed in [1], create an empty SGML file to hold the corresponding content. 1. Use the pattern <sect1 id="functions-XXX"> to locate the starting and ending line number of each section in func.sgml 2. Copy func.sgml all the content block (<sect1>) <sect1 id="functions-XXX"> ...main content </sect1> into the newly created SGML files. 3. Remove the copied content from func.sgml. 4. In func.sgml, insert general entity references [3] to include the newly created SGML files. because PG18, and PG17, Chapter 9. Functions and Operators have the same amount of section (31), so v1-0001-split_func_sgml.py will work just fine. but I did some minor changes, therefore v2 attached. ---------------------------------------------------- I used the sed --in-place option [3] to modify and truncate the original large func.sgml file directly. I also used the -n and -p options with sed to extract lines from func.sgml between line X and line Y, as shown in reference [4]. for the attach file: first run ``python3 v2-0001-split_func_sgml.py`` then run ``git apply v2-0001-update-filelist.sgml-allfiles.sgml.no-cfbot`` (`git am` won't work, need to use `git apply`). [1] https://www.postgresql.org/docs/current/functions.html [2] https://en.wikipedia.org/wiki/Document_type_definition [3] https://www.gnu.org/software/sed/manual/html_node/Command_002dLine-Options.html#index-_002di [4] https://www.gnu.org/software/sed/manual/html_node/Common-Commands.html#index-n-_0028next_002dline_0029
v2-0001-update-filelist.sgml-allfiles.sgml.no-cfbot
Description: Binary data
import subprocess import os import re #https://git-scm.com/docs/git-rev-parse#Documentation/git-rev-parse.txt---show-toplevel top_dir = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]) top_dir = top_dir.decode().rstrip('\n') top_doc_dir = top_dir + "/doc/src/sgml" #go to doc/src/sgml directory first, exit when the directory does not exist try: os.chdir(top_doc_dir) except FileNotFoundError: print(f'{top_doc_dir} not does not exist. exit now') quit() func_sgml="func.sgml" # func_logical="func-logical.sgml" func_comparison="func-comparison.sgml" func_math="func-math.sgml" func_string="func-string.sgml" func_binarystring="func-binarystring.sgml" func_bitstring="func-bitstring.sgml" func_matching="func-matching.sgml" func_formatting="func-formatting.sgml" func_datetime="func-datetime.sgml" func_enum="func-enum.sgml" func_geometry="func-geometry.sgml" func_net="func-net.sgml" func_textsearch="func-textsearch.sgml" func_uuid="func-uuid.sgml" func_xml="func-xml.sgml" func_json="func-json.sgml" func_sequence="func-sequence.sgml" func_conditional="func-conditional.sgml" func_array="func-array.sgml" func_range="func-range.sgml" func_aggregate="func-aggregate.sgml" func_window="func-window.sgml" func_merge_support ="func-merge-support.sgml" func_subquery="func-subquery.sgml" func_comparisons="func-comparisons.sgml" func_srf="func-srf.sgml" func_info="func-info.sgml" func_admin="func-admin.sgml" func_trigger="func-trigger.sgml" func_event_triggers="func-event-triggers.sgml" func_statistics="func-statistics.sgml" # func_filenames = list() func_filenames.append(func_logical) func_filenames.append(func_comparison) func_filenames.append(func_math) func_filenames.append(func_string) func_filenames.append(func_binarystring) func_filenames.append(func_bitstring) func_filenames.append(func_matching) func_filenames.append(func_formatting) func_filenames.append(func_datetime) func_filenames.append(func_enum) func_filenames.append(func_geometry) func_filenames.append(func_net) func_filenames.append(func_textsearch) func_filenames.append(func_uuid) func_filenames.append(func_xml) func_filenames.append(func_json) func_filenames.append(func_sequence) func_filenames.append(func_conditional) func_filenames.append(func_array) func_filenames.append(func_range) func_filenames.append(func_aggregate) func_filenames.append(func_window) func_filenames.append(func_merge_support ) func_filenames.append(func_subquery) func_filenames.append(func_comparisons) func_filenames.append(func_srf) func_filenames.append(func_info) func_filenames.append(func_admin) func_filenames.append(func_trigger) func_filenames.append(func_event_triggers) func_filenames.append(func_statistics) # func_string_begin_lineno= -1 func_logical_begin_lineno=-1 func_comparison_begin_lineno=-1 func_math_begin_lineno=-1 func_string_begin_lineno=-1 func_binarystring_begin_lineno=-1 func_bitstring_begin_lineno=-1 func_matching_begin_lineno=-1 func_formatting_begin_lineno=-1 func_datetime_begin_lineno=-1 func_enum_begin_lineno=-1 func_geometry_begin_lineno=-1 func_net_begin_lineno=-1 func_textsearch_begin_lineno=-1 func_uuid_begin_lineno=-1 func_xml_begin_lineno=-1 func_json_begin_lineno=-1 func_sequence_begin_lineno=-1 func_conditional_begin_lineno=-1 func_array_begin_lineno=-1 func_range_begin_lineno=-1 func_aggregate_begin_lineno=-1 func_window_begin_lineno=-1 func_merge_support_begin_lineno=-1 func_subquery_begin_lineno=-1 func_comparisons_begin_lineno=-1 func_srf_begin_lineno=-1 func_info_begin_lineno=-1 func_admin_begin_lineno=-1 func_trigger_begin_lineno=-1 func_event_triggers_begin_lineno=-1 func_statistics_begin_lineno=-1 # func_logical_end_lineno=-1 func_comparison_end_lineno=-1 func_math_end_lineno=-1 func_string_end_lineno=-1 func_binarystring_end_lineno=-1 func_bitstring_end_lineno=-1 func_matching_end_lineno=-1 func_formatting_end_lineno=-1 func_datetime_end_lineno=-1 func_enum_end_lineno=-1 func_geometry_end_lineno=-1 func_net_end_lineno=-1 func_textsearch_end_lineno=-1 func_uuid_end_lineno=-1 func_xml_end_lineno=-1 func_json_end_lineno=-1 func_sequence_end_lineno=-1 func_conditional_end_lineno=-1 func_array_end_lineno=-1 func_range_end_lineno=-1 func_aggregate_end_lineno=-1 func_window_end_lineno=-1 func_merge_support_end_lineno=-1 func_subquery_end_lineno=-1 func_comparisons_end_lineno=-1 func_srf_end_lineno=-1 func_info_end_lineno=-1 func_admin_end_lineno=-1 func_trigger_end_lineno=-1 func_event_triggers_end_lineno=-1 #based on line number pattern in func.sgml def get_line_number(file_name: str): global func_logical_begin_lineno global func_comparison_begin_lineno global func_math_begin_lineno global func_string_begin_lineno global func_binarystring_begin_lineno global func_bitstring_begin_lineno global func_matching_begin_lineno global func_formatting_begin_lineno global func_datetime_begin_lineno global func_enum_begin_lineno global func_geometry_begin_lineno global func_net_begin_lineno global func_textsearch_begin_lineno global func_uuid_begin_lineno global func_xml_begin_lineno global func_json_begin_lineno global func_sequence_begin_lineno global func_conditional_begin_lineno global func_array_begin_lineno global func_range_begin_lineno global func_aggregate_begin_lineno global func_window_begin_lineno global func_merge_support_begin_lineno global func_subquery_begin_lineno global func_comparisons_begin_lineno global func_srf_begin_lineno global func_info_begin_lineno global func_admin_begin_lineno global func_trigger_begin_lineno global func_event_triggers_begin_lineno global func_statistics_begin_lineno global func_logical_end_lineno global func_comparison_end_lineno global func_math_end_lineno global func_string_end_lineno global func_binarystring_end_lineno global func_bitstring_end_lineno global func_matching_end_lineno global func_formatting_end_lineno global func_datetime_end_lineno global func_enum_end_lineno global func_geometry_end_lineno global func_net_end_lineno global func_textsearch_end_lineno global func_uuid_end_lineno global func_xml_end_lineno global func_json_end_lineno global func_sequence_end_lineno global func_conditional_end_lineno global func_array_end_lineno global func_range_end_lineno global func_aggregate_end_lineno global func_window_end_lineno global func_merge_support_end_lineno global func_subquery_end_lineno global func_comparisons_end_lineno global func_srf_end_lineno global func_info_end_lineno global func_admin_end_lineno global func_trigger_end_lineno global func_event_triggers_end_lineno global func_statistics_end_lineno with open(file_name, 'r+') as f: for i, line in enumerate(f, 1): if r'<sect1 id="functions-logical">' in line : func_logical_begin_lineno = i elif r'<sect1 id="functions-comparison">' in line : func_comparison_begin_lineno = i func_logical_end_lineno = i - 2 elif r'<sect1 id="functions-math">' in line : func_comparison_end_lineno = i - 2 func_math_begin_lineno = i elif r'<sect1 id="functions-string">' in line : func_math_end_lineno = i - 3 func_string_begin_lineno = i elif r'<sect1 id="functions-binarystring">' in line : func_string_end_lineno = i - 3 func_binarystring_begin_lineno = i elif r'<sect1 id="functions-bitstring">' in line : func_binarystring_end_lineno = i - 3 func_bitstring_begin_lineno = i elif r'<sect1 id="functions-matching">' in line : func_bitstring_end_lineno = i - 3 func_matching_begin_lineno = i elif r'<sect1 id="functions-formatting">' in line : func_matching_end_lineno = i - 3 func_formatting_begin_lineno = i elif r'<sect1 id="functions-datetime">' in line : func_formatting_end_lineno = i - 3 func_datetime_begin_lineno = i elif r'<sect1 id="functions-enum">' in line : func_datetime_end_lineno = i - 3 func_enum_begin_lineno = i elif r'<sect1 id="functions-geometry">' in line : func_enum_end_lineno = i - 2 func_geometry_begin_lineno = i elif r'<sect1 id="functions-net">' in line : func_geometry_end_lineno = i - 3 func_net_begin_lineno = i elif r'<sect1 id="functions-textsearch">' in line : func_net_end_lineno = i - 3 func_textsearch_begin_lineno = i elif r'<sect1 id="functions-uuid">' in line : func_textsearch_end_lineno = i - 2 func_uuid_begin_lineno = i elif r'<sect1 id="functions-xml">' in line : func_uuid_end_lineno = i - 2 func_xml_begin_lineno = i elif r'<sect1 id="functions-json">' in line : func_xml_end_lineno = i - 2 func_json_begin_lineno = i elif r'<sect1 id="functions-sequence">' in line : func_json_end_lineno = i - 2 func_sequence_begin_lineno = i elif r'<sect1 id="functions-conditional">' in line : func_sequence_end_lineno = i - 3 func_conditional_begin_lineno = i elif r'<sect1 id="functions-array">' in line : func_conditional_end_lineno = i - 2 func_array_begin_lineno = i elif r'<sect1 id="functions-range">' in line : func_array_end_lineno = i - 2 func_range_begin_lineno = i elif r'<sect1 id="functions-aggregate">' in line : func_range_end_lineno = i - 2 func_aggregate_begin_lineno = i elif r'<sect1 id="functions-window">' in line : func_aggregate_end_lineno = i - 2 func_window_begin_lineno = i elif r'<sect1 id="functions-merge-support">' in line : func_window_end_lineno = i - 2 func_merge_support_begin_lineno = i elif r'<sect1 id="functions-subquery">' in line : func_merge_support_end_lineno = i - 2 func_subquery_begin_lineno = i elif r'<sect1 id="functions-comparisons">' in line : func_subquery_end_lineno = i - 3 func_comparisons_begin_lineno = i elif r'<sect1 id="functions-srf">' in line : func_comparisons_end_lineno = i - 2 func_srf_begin_lineno = i elif r'<sect1 id="functions-info">' in line : func_srf_end_lineno = i - 2 func_info_begin_lineno = i elif r'<sect1 id="functions-admin">' in line : func_info_end_lineno = i - 2 func_admin_begin_lineno = i elif r'<sect1 id="functions-trigger">' in line : func_admin_end_lineno = i - 2 func_trigger_begin_lineno = i elif r'<sect1 id="functions-event-triggers">' in line : func_trigger_end_lineno = i - 2 func_event_triggers_begin_lineno = i elif r'<sect1 id="functions-statistics">' in line : func_event_triggers_end_lineno = i - 2 func_statistics_begin_lineno = i elif r'</chapter>' in line : #check the end of doc/src/sgml/func.sgml. that's the relative position of last occurence of "</sect1>" func_statistics_end_lineno = i -2 #line number is important property. they should strict following the order. def validate_line_number(): if (not (func_logical_begin_lineno < func_logical_end_lineno < func_comparison_begin_lineno < func_comparison_end_lineno < func_math_begin_lineno < func_math_end_lineno < func_string_begin_lineno < func_string_end_lineno < func_binarystring_begin_lineno < func_binarystring_end_lineno < func_bitstring_begin_lineno < func_bitstring_end_lineno < func_matching_begin_lineno < func_matching_end_lineno < func_formatting_begin_lineno < func_formatting_end_lineno < func_datetime_begin_lineno < func_datetime_end_lineno < func_enum_begin_lineno < func_enum_end_lineno < func_geometry_begin_lineno < func_geometry_end_lineno < func_net_begin_lineno < func_net_end_lineno < func_textsearch_begin_lineno < func_textsearch_end_lineno < func_uuid_begin_lineno < func_uuid_end_lineno < func_xml_begin_lineno < func_xml_end_lineno < func_json_begin_lineno < func_json_end_lineno < func_sequence_begin_lineno < func_sequence_end_lineno < func_conditional_begin_lineno < func_conditional_end_lineno < func_array_begin_lineno < func_array_end_lineno < func_range_begin_lineno < func_range_end_lineno < func_aggregate_begin_lineno < func_aggregate_end_lineno < func_window_begin_lineno < func_window_end_lineno < func_merge_support_begin_lineno < func_merge_support_end_lineno < func_subquery_begin_lineno < func_subquery_end_lineno < func_comparisons_begin_lineno < func_comparisons_end_lineno < func_srf_begin_lineno < func_srf_end_lineno < func_info_begin_lineno < func_info_end_lineno < func_admin_begin_lineno < func_admin_end_lineno < func_trigger_begin_lineno < func_trigger_end_lineno < func_event_triggers_begin_lineno < func_event_triggers_end_lineno < func_statistics_begin_lineno < func_statistics_end_lineno)): ValueError("don't have related file") print("quiting line numbers begin is invalid") quit() #--step0 get line number info, and validate it. get_line_number(func_sgml) validate_line_number() #--step1. create doc/src/sgml/func directory, move func.sgml to there. create each invidual sgml file os.mkdir(top_doc_dir+ "/func") os.chdir(top_doc_dir+ "/func") print ("Updated directory:" , os.getcwd()) subprocess.call(["git", "add", "."]) subprocess.call(["mv","../func.sgml", "func.sgml"]) for x in func_filenames: subprocess.call(["touch", x]) #---step2 construct sed copy commands and execute it sed_copy_commands = list() sed_copy_commands.append( f"sed -n '{func_logical_begin_lineno}, {func_logical_end_lineno}p' {func_sgml} > {func_logical}") sed_copy_commands.append( f"sed -n '{func_comparison_begin_lineno}, {func_comparison_end_lineno}p' {func_sgml} > {func_comparison}") sed_copy_commands.append( f"sed -n '{func_math_begin_lineno}, {func_math_end_lineno}p' {func_sgml} > {func_math}") sed_copy_commands.append( f"sed -n '{func_string_begin_lineno}, {func_string_end_lineno}p' {func_sgml} > {func_string}") sed_copy_commands.append( f"sed -n '{func_binarystring_begin_lineno}, {func_binarystring_end_lineno}p' {func_sgml} > {func_binarystring}") sed_copy_commands.append( f"sed -n '{func_bitstring_begin_lineno}, {func_bitstring_end_lineno}p' {func_sgml} > {func_bitstring}") sed_copy_commands.append( f"sed -n '{func_matching_begin_lineno}, {func_matching_end_lineno}p' {func_sgml} > {func_matching}") sed_copy_commands.append( f"sed -n '{func_formatting_begin_lineno}, {func_formatting_end_lineno}p' {func_sgml} > {func_formatting}") sed_copy_commands.append( f"sed -n '{func_datetime_begin_lineno}, {func_datetime_end_lineno}p' {func_sgml} > {func_datetime}") sed_copy_commands.append( f"sed -n '{func_enum_begin_lineno}, {func_enum_end_lineno}p' {func_sgml} > {func_enum}") sed_copy_commands.append( f"sed -n '{func_geometry_begin_lineno}, {func_geometry_end_lineno}p' {func_sgml} > {func_geometry}") sed_copy_commands.append( f"sed -n '{func_net_begin_lineno}, {func_net_end_lineno}p' {func_sgml} > {func_net}") sed_copy_commands.append( f"sed -n '{func_textsearch_begin_lineno}, {func_textsearch_end_lineno}p' {func_sgml} > {func_textsearch}") sed_copy_commands.append( f"sed -n '{func_uuid_begin_lineno}, {func_uuid_end_lineno}p' {func_sgml} > {func_uuid}") sed_copy_commands.append( f"sed -n '{func_xml_begin_lineno}, {func_xml_end_lineno}p' {func_sgml} > {func_xml}") sed_copy_commands.append( f"sed -n '{func_json_begin_lineno}, {func_json_end_lineno}p' {func_sgml} > {func_json}") sed_copy_commands.append( f"sed -n '{func_sequence_begin_lineno}, {func_sequence_end_lineno}p' {func_sgml} > {func_sequence}") sed_copy_commands.append( f"sed -n '{func_conditional_begin_lineno}, {func_conditional_end_lineno}p' {func_sgml} > {func_conditional}") sed_copy_commands.append( f"sed -n '{func_array_begin_lineno}, {func_array_end_lineno}p' {func_sgml} > {func_array}") sed_copy_commands.append( f"sed -n '{func_range_begin_lineno}, {func_range_end_lineno}p' {func_sgml} > {func_range}") sed_copy_commands.append( f"sed -n '{func_aggregate_begin_lineno}, {func_aggregate_end_lineno}p' {func_sgml} > {func_aggregate}") sed_copy_commands.append( f"sed -n '{func_window_begin_lineno}, {func_window_end_lineno}p' {func_sgml} > {func_window}") sed_copy_commands.append( f"sed -n '{func_merge_support_begin_lineno}, {func_merge_support_end_lineno}p' {func_sgml} > {func_merge_support}") sed_copy_commands.append( f"sed -n '{func_subquery_begin_lineno}, {func_subquery_end_lineno}p' {func_sgml} > {func_subquery}") sed_copy_commands.append( f"sed -n '{func_comparisons_begin_lineno}, {func_comparisons_end_lineno}p' {func_sgml} > {func_comparisons}") sed_copy_commands.append( f"sed -n '{func_srf_begin_lineno}, {func_srf_end_lineno}p' {func_sgml} > {func_srf}") sed_copy_commands.append( f"sed -n '{func_info_begin_lineno}, {func_info_end_lineno}p' {func_sgml} > {func_info}") sed_copy_commands.append( f"sed -n '{func_admin_begin_lineno}, {func_admin_end_lineno}p' {func_sgml} > {func_admin}") sed_copy_commands.append( f"sed -n '{func_trigger_begin_lineno}, {func_trigger_end_lineno}p' {func_sgml} > {func_trigger}") sed_copy_commands.append( f"sed -n '{func_event_triggers_begin_lineno}, {func_event_triggers_end_lineno}p' {func_sgml} > {func_event_triggers}") sed_copy_commands.append( f"sed -n '{func_statistics_begin_lineno}, {func_statistics_end_lineno}p' {func_sgml} > {func_statistics}") print(f'sed command for copying func.sgml content to new sgml file') # https://superuser.com/questions/852404/what-does-n-option-in-sed-do for x in sed_copy_commands: print(f'sed copy command=> {x}') subprocess.call([x], shell=True) #-----step3 validate that the new file only have 2 "sect1". def validate_new_file_sect1(file_name: str, pattern: str): matches_all = [] with open(file_name, 'r+') as f: for i, line in enumerate(f, 1): matches = re.findall(pattern, line) if (len(matches) > 0): matches_all = matches_all + matches if (len(matches_all) != 2): print(f'{file_name} should only have 2 \"{pattern}\" attribute. now quit') quit() for x in func_filenames: validate_new_file_sect1(x, "sect1") def validate_new_file_sect1id(file_name: str, pattern: str): matches_all = [] with open(file_name, 'r+') as f: for i, line in enumerate(f, 1): matches = re.findall(pattern, line) if (len(matches) > 0): matches_all = matches_all + matches if (len(matches_all) != 1): print(f'{file_name} should only have 1 \"{pattern}\" attribute. now quit') quit() #------step3 validate new files string <sect1 id=functions-XXX is unique. validate_new_file_sect1id(func_logical,r'<sect1 id="functions-logical">') validate_new_file_sect1id(func_comparison,r'<sect1 id="functions-comparison">') validate_new_file_sect1id(func_math,r'<sect1 id="functions-math">') validate_new_file_sect1id(func_string, r'<sect1 id="functions-string">') validate_new_file_sect1id(func_binarystring,r'<sect1 id="functions-binarystring">') validate_new_file_sect1id(func_bitstring,r'<sect1 id="functions-bitstring">') validate_new_file_sect1id(func_matching,r'<sect1 id="functions-matching">') validate_new_file_sect1id(func_formatting,r'<sect1 id="functions-formatting">') validate_new_file_sect1id(func_datetime,r'<sect1 id="functions-datetime">') validate_new_file_sect1id(func_enum,r'<sect1 id="functions-enum">') validate_new_file_sect1id(func_geometry,r'<sect1 id="functions-geometry">') validate_new_file_sect1id(func_net,r'<sect1 id="functions-net">') validate_new_file_sect1id(func_textsearch,r'<sect1 id="functions-textsearch">') validate_new_file_sect1id(func_uuid,r'<sect1 id="functions-uuid">') validate_new_file_sect1id(func_xml,r'<sect1 id="functions-xml">') validate_new_file_sect1id(func_json,r'<sect1 id="functions-json">') validate_new_file_sect1id(func_sequence,r'<sect1 id="functions-sequence">') validate_new_file_sect1id(func_conditional,r'<sect1 id="functions-conditional">') validate_new_file_sect1id(func_array,r'<sect1 id="functions-array">') validate_new_file_sect1id(func_range,r'<sect1 id="functions-range">') validate_new_file_sect1id(func_aggregate,r'<sect1 id="functions-aggregate">') validate_new_file_sect1id(func_window,r'<sect1 id="functions-window">') validate_new_file_sect1id(func_merge_support,r'<sect1 id="functions-merge-support">') validate_new_file_sect1id(func_subquery,r'<sect1 id="functions-subquery">') validate_new_file_sect1id(func_comparisons,r'<sect1 id="functions-comparisons">') validate_new_file_sect1id(func_srf,r'<sect1 id="functions-srf">') validate_new_file_sect1id(func_info,r'<sect1 id="functions-info">') validate_new_file_sect1id(func_admin,r'<sect1 id="functions-admin">') validate_new_file_sect1id(func_trigger,r'<sect1 id="functions-trigger">') validate_new_file_sect1id(func_event_triggers,r'<sect1 id="functions-event-triggers">') validate_new_file_sect1id(func_statistics,r'<sect1 id="functions-statistics">') #construct the place-holder string in func.sgml all_func_sgml_place_holder = """&func-logical; &func-comparison; &func-math; &func-string; &func-binarystring; &func-bitstring; &func-matching; &func-formatting; &func-datetime; &func-enum; &func-geometry; &func-net; &func-textsearch; &func-uuid; &func-xml; &func-json; &func-sequence; &func-conditional; &func-array; &func-range; &func-aggregate; &func-window; &func-merge-support; &func-subquery; &func-comparisons; &func-srf; &func-info; &func-admin; &func-trigger; &func-event-triggers; &func-statistics; </chapter> """ #---step4 truncate func.sgml # after line <sect1 id="functions-logical">' (inclusive) will be deleted # that's why "func_logical_begin_lineno -1" sed_truncate= f"sed -i {func_logical_begin_lineno -1}q {func_sgml}" print(f'\nsed command for truncate func.sgml=> {sed_truncate}') subprocess.call(sed_truncate, shell=True) # insert content before line X in file_name def write_line(file_name:str, line:int, content:str): line -= 1 with open(file_name, "r") as file: lines = file.readlines() lines[line] = lines[line] + content # concatenate the content with open(file_name, "w") as file: file.write("".join(lines)) # Write the modified content to the file #---step5 append the place-holder string to the end of func.sgml. # because of command sed_truncate, we need begin with func_logical_begin_lineno -1 write_line(func_sgml, (func_logical_begin_lineno -1), all_func_sgml_place_holder) #git related. os.chdir(top_doc_dir+ "/func") print ("Updated directory:" , os.getcwd()) subprocess.call(["git", "add", "./*"])