Advertisement
crzyc

code_context.py

Dec 22nd, 2024
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.82 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. import argparse
  5. from pathlib import Path
  6. from datetime import datetime
  7. import sqlalchemy
  8.  
  9.  
  10. def generate_tree(directory_path, output_file="file_tree.md"):
  11.     """
  12.    Generates a markdown file containing the directory/file tree structure.
  13.    """
  14.     try:
  15.         # Convert to absolute path and verify directory exists
  16.         abs_path = os.path.abspath(directory_path)
  17.         if not os.path.isdir(abs_path):
  18.             print(f"Error: '{directory_path}' is not a valid directory")
  19.             return False
  20.  
  21.         # Create or truncate output file
  22.         with open(output_file, "w", encoding="utf-8") as outfile:
  23.             # Write header with timestamp
  24.             outfile.write(f"# Directory Tree Report\n\n")
  25.             outfile.write(
  26.                 f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
  27.             )
  28.             outfile.write(f"Source directory: `{directory_path}`\n\n")
  29.             outfile.write("```\n")
  30.  
  31.             # Walk through directory recursively
  32.             for root, dirs, files in os.walk(abs_path):
  33.                 # Calculate depth for indentation
  34.                 level = root.replace(abs_path, "").count(os.sep)
  35.                 indent = "│   " * level
  36.  
  37.                 # Print directory name
  38.                 dir_name = os.path.basename(root)
  39.                 if level == 0:
  40.                     outfile.write(f"{dir_name}/\n")
  41.                 else:
  42.                     outfile.write(f"{indent}├── {dir_name}/\n")
  43.  
  44.                 # Print files
  45.                 subindent = "│   " * (level + 1)
  46.                 for i, file in enumerate(sorted(files)):
  47.                     if i == len(files) - 1 and not dirs:  # Last file in directory
  48.                         outfile.write(f"{subindent[:-4]}└── {file}\n")
  49.                     else:
  50.                         outfile.write(f"{subindent}├── {file}\n")
  51.  
  52.             outfile.write("```\n")
  53.             outfile.write("\n# End of Directory Tree Report\n")
  54.  
  55.         print(f"Successfully generated directory tree in '{output_file}'")
  56.         return True
  57.  
  58.     except Exception as e:
  59.         print(f"Error: {str(e)}")
  60.         return False
  61.  
  62.  
  63. def combine_files(directory_path, output_file="combined_output.md"):
  64.     """
  65.    Recursively combines all files from the given directory into a single markdown file.
  66.    Each file's content is formatted with markdown syntax for better readability.
  67.    """
  68.     try:
  69.         # Convert to absolute path and verify directory exists
  70.         abs_path = os.path.abspath(directory_path)
  71.         if not os.path.isdir(abs_path):
  72.             print(f"Error: '{directory_path}' is not a valid directory")
  73.             return False
  74.  
  75.         # Create or truncate output file
  76.         with open(output_file, "w", encoding="utf-8") as outfile:
  77.             # Write header with timestamp
  78.             outfile.write(f"# Combined Files Report\n\n")
  79.             outfile.write(
  80.                 f"Generated on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
  81.             )
  82.             outfile.write(f"Source directory: `{directory_path}`\n\n")
  83.             outfile.write("---\n\n")
  84.  
  85.             # Walk through directory recursively
  86.             for root, _, files in os.walk(abs_path):
  87.                 for filename in sorted(files):
  88.                     # Skip the output file itself if it's in the directory
  89.                     if filename == output_file:
  90.                         continue
  91.  
  92.                     file_path = os.path.join(root, filename)
  93.  
  94.                     # Calculate relative path from the input directory
  95.                     rel_path = os.path.relpath(file_path, abs_path)
  96.  
  97.                     try:
  98.                         # Try to read the file as text
  99.                         with open(file_path, "r", encoding="utf-8") as infile:
  100.                             # Write file header with path
  101.                             outfile.write(f"## {rel_path}\n\n")
  102.  
  103.                             # Determine language for syntax highlighting based on file extension
  104.                             ext = os.path.splitext(filename)[1].lstrip(".")
  105.                             if ext:
  106.                                 outfile.write(f"```{ext}\n")
  107.                             else:
  108.                                 outfile.write("```\n")
  109.  
  110.                             # Write file contents
  111.                             outfile.write(infile.read())
  112.                             outfile.write("\n```\n\n")
  113.  
  114.                             # Add separator between files
  115.                             outfile.write("---\n\n")
  116.                     except UnicodeDecodeError:
  117.                         # Handle binary files
  118.                         outfile.write(f"## {rel_path}\n\n")
  119.                         outfile.write("*[Binary file]*\n\n")
  120.                         outfile.write("---\n\n")
  121.                     except Exception as e:
  122.                         # Log other errors but continue processing
  123.                         outfile.write(f"## {rel_path}\n\n")
  124.                         outfile.write(f"*[Error reading file: {str(e)}]*\n\n")
  125.                         outfile.write("---\n\n")
  126.  
  127.             # Write footer
  128.             outfile.write("# End of Combined Files Report\n")
  129.  
  130.         print(f"Successfully combined files into '{output_file}'")
  131.         return True
  132.  
  133.     except Exception as e:
  134.         print(f"Error: {str(e)}")
  135.         return False
  136.  
  137. def dump_database(database_url=None, schema_only=True, output_file="database_dump.sql"):
  138.     """Dumps the database schema (or data) to a file."""
  139.     try:
  140.         if database_url:
  141.             engine = sqlalchemy.create_engine(database_url) #create a new engine if a URL is supplied
  142.         connection = engine.connect()
  143.         metadata = sqlalchemy.MetaData()
  144.         metadata.reflect(bind=engine)
  145.        
  146.         with open(output_file, "w", encoding="utf-8") as outfile:
  147.             if schema_only:
  148.                 outfile.write("-- Database Schema Dump\n")
  149.                 for table in metadata.sorted_tables:
  150.                     outfile.write(str(sqlalchemy.schema.CreateTable(table).compile(dialect=engine.dialect)) + ";\n\n")
  151.             else:
  152.                 outfile.write("-- Database Schema and Data Dump\n")
  153.                 for table in metadata.sorted_tables:
  154.                     outfile.write(str(sqlalchemy.schema.CreateTable(table).compile(dialect=engine.dialect)) + ";\n\n")
  155.                     result = connection.execute(sqlalchemy.select(table))
  156.                     column_names = result.keys()
  157.                     outfile.write(f"INSERT INTO {table.name} ({', '.join(column_names)}) VALUES\n")
  158.                     rows = result.fetchall()
  159.                     for i, row in enumerate(rows):
  160.                         values = ', '.join([repr(value) for value in row])
  161.                         outfile.write(f"({values})")
  162.                         if i < len(rows) - 1:
  163.                             outfile.write(",\n")
  164.                         else:
  165.                             outfile.write(";\n\n")
  166.         connection.close()
  167.         print(f"Successfully dumped database to '{output_file}'.")
  168.         return True
  169.  
  170.     except Exception as e:
  171.         print(f"Error dumping database: {str(e)}")
  172.         return False
  173.  
  174. def main():
  175.     parser = argparse.ArgumentParser(
  176.         description="Combine files, generate directory tree, or dump database."
  177.     )
  178.     parser.add_argument("directory", help="Directory path to process")
  179.     parser.add_argument("-o", "--output", help="Output file name", default=None)
  180.     parser.add_argument(
  181.         "--tree",
  182.         action="store_true",
  183.         help="Generate directory tree instead of combining files",
  184.     )
  185.     parser.add_argument(
  186.         "--dump-database",
  187.         action="store_true",
  188.         help="Dump database schema (or data) to a file",
  189.     )
  190.     parser.add_argument(
  191.         "--database-url",
  192.         help="URL of the database to dump (optional, uses db.py if not provided)",
  193.     )
  194.     parser.add_argument(
  195.         "--schema-only",
  196.         action="store_true",
  197.         help="Dump only the database schema (default if --dump-database is used)",
  198.     )
  199.  
  200.     args = parser.parse_args()
  201.  
  202.     if args.tree:
  203.         output_file = args.output if args.output else "file_tree.md"
  204.         if not generate_tree(args.directory, output_file):
  205.             sys.exit(1)
  206.     elif args.dump_database:
  207.         output_file = args.output if args.output else "database_dump.sql"
  208.         if not dump_database(args.database_url, schema_only=args.schema_only, output_file=output_file):
  209.             sys.exit(1)
  210.     else: # If neither --tree nor --dump-database is specified, combine files
  211.         output_file = args.output if args.output else "combined_output.md"
  212.         if not combine_files(args.directory, output_file):
  213.             sys.exit(1)
  214.  
  215. if __name__ == "__main__":
  216.     main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement