Guest User

Untitled

a guest
Jun 2nd, 2025
30
0
317 days
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.96 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2. import re
  3. import sys
  4.  
  5. def postprocess_gcode(filename):
  6.     """
  7.    Postprocesses a G-code file to move estimated printing time lines
  8.    before the EXECUTABLE_BLOCK_START marker, preserving original line endings.
  9.    """
  10.     try:
  11.         with open(filename, 'rb') as f: # Open in binary read mode
  12.             binary_content = f.read()
  13.     except FileNotFoundError:
  14.         print(f"Error: File '{filename}' not found.")
  15.         return False
  16.     except Exception as e:
  17.         print(f"Error reading file '{filename}': {e}")
  18.         return False
  19.  
  20.     # Try to decode using UTF-8; G-code is often ASCII, which is UTF-8 compatible.
  21.     # If other encodings are possible, this might need to be more flexible.
  22.     try:
  23.         text_content = binary_content.decode('utf-8')
  24.     except UnicodeDecodeError:
  25.         try:
  26.             # Fallback to latin-1 if UTF-8 fails, as it can decode any byte.
  27.             # This might not render special characters correctly if they weren't originally latin-1.
  28.             print(f"Warning: Could not decode '{filename}' as UTF-8. Attempting latin-1.")
  29.             text_content = binary_content.decode('latin-1')
  30.         except Exception as e:
  31.             print(f"Error decoding file '{filename}': {e}")
  32.             return False
  33.    
  34.     # Split lines, keeping the original line endings
  35.     if not text_content: # Handle empty file
  36.         lines = []
  37.     else:
  38.         lines = text_content.splitlines(keepends=True)
  39.  
  40.     # Patterns we're looking for (anchored to start of line string)
  41.     time_pattern1 = re.compile(r'^; estimated printing time \(normal mode\) =')
  42.     time_pattern2 = re.compile(r'^; estimated first layer printing time \(normal mode\) =')
  43.     executable_pattern = re.compile(r'^; EXECUTABLE_BLOCK_START')
  44.  
  45.     # Store data about found lines
  46.     time_lines_data = [] # List of tuples: (original_index, line_content_with_ending)
  47.     executable_pos = -1
  48.     first_executable_block_found = False
  49.  
  50.     for i, line_with_ending in enumerate(lines):
  51.         if executable_pattern.match(line_with_ending):
  52.             if not first_executable_block_found:
  53.                 executable_pos = i
  54.                 first_executable_block_found = True
  55.         elif (time_pattern1.match(line_with_ending) or time_pattern2.match(line_with_ending)):
  56.             if executable_pos != -1 and i > executable_pos:
  57.                 time_lines_data.append((i, line_with_ending))
  58.  
  59.     if executable_pos != -1 and time_lines_data:
  60.         lines_to_insert_content = [line_content for _, line_content in time_lines_data]
  61.        
  62.         indices_to_delete = sorted([original_idx for original_idx, _ in time_lines_data], reverse=True)
  63.        
  64.         for index_to_delete in indices_to_delete:
  65.             del lines[index_to_delete]
  66.        
  67.         # The executable_pos is the index in the 'lines' list *before* insertion.
  68.         # If lines were deleted *before* executable_pos, its index would shift.
  69.         # However, we only delete lines *after* executable_pos, so its index relative
  70.         # to the start of the list remains correct for identifying the insertion point.
  71.         current_insert_pos = executable_pos
  72.         for line_content_with_ending in lines_to_insert_content:
  73.             lines.insert(current_insert_pos, line_content_with_ending)
  74.             current_insert_pos += 1
  75.  
  76.         # Join the lines back into a single string (original line endings are preserved)
  77.         modified_text_content = "".join(lines)
  78.        
  79.         # Encode back to bytes using the initially successful (or fallback) encoding
  80.         try:
  81.             # Attempt to encode with UTF-8 first if that's what we decoded with
  82.             # This assumes that if it decoded as UTF-8, it can be encoded back.
  83.             # A more robust solution might store the detected encoding.
  84.             # For simplicity, we'll try UTF-8, then latin-1 for encoding.
  85.             try:
  86.                 output_binary_content = modified_text_content.encode('utf-8')
  87.             except UnicodeEncodeError: # Should not happen if decoded as UTF-8 and no invalid chars added
  88.                  print(f"Warning: Could not encode modified content of '{filename}' as UTF-8. Attempting latin-1.")
  89.                  output_binary_content = modified_text_content.encode('latin-1')
  90.  
  91.         except Exception as e:
  92.             print(f"Error encoding modified content for '{filename}': {e}")
  93.             return False
  94.  
  95.         try:
  96.             with open(filename, 'wb') as f: # Open in binary write mode
  97.                 f.write(output_binary_content)
  98.             # print(f"File '{filename}' processed successfully, line endings preserved.")
  99.             return True
  100.         except Exception as e:
  101.             print(f"Error writing to file '{filename}': {e}")
  102.             return False
  103.     else:
  104.         # print(f"No relevant changes made to '{filename}'.")
  105.         return True # Operation completed, even if no changes were made.
  106.  
  107. sourceFile=sys.argv[1]
  108. postprocess_gcode(sourceFile)
  109.  
Advertisement
Add Comment
Please, Sign In to add comment