Skip to content

Commit

Permalink
Merge pull request #103 from MEHRSHAD-MIRSHEKARY/feat/pretty-format
Browse files Browse the repository at this point in the history
✨ Feat/pretty format
  • Loading branch information
ARYAN-NIKNEZHAD authored Oct 4, 2024
2 parents c8a2bb2 + 980f28d commit a398786
Show file tree
Hide file tree
Showing 2 changed files with 180 additions and 0 deletions.
103 changes: 103 additions & 0 deletions django_logging/management/commands/generate_pretty_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import json
import os
from typing import Dict, Tuple

from django.conf import settings
from django.core.management.base import BaseCommand

from django_logging.constants import DefaultLoggingSettings
from django_logging.constants.config_types import LogDir
from django_logging.utils.command.process_file import process_files, setup_directories


class Command(BaseCommand):
"""A Django management command to find JSON files within a specified log
directory and generate pretty JSON.
The command looks for `.json` files inside the `json` subdirectory of the log directory, attempts to
parse multiple JSON objects from a single file, and then formats them into a valid JSON array.
The reformatted JSON content is saved in a `pretty` subdirectory with the prefix `formatted_`.
"""

help = "Find JSON files in log directory and generates pretty JSON"

def handle(self, *args: Tuple, **kwargs: Dict) -> None:
"""Main command handler. This method retrieves the log directory, sets
up necessary directories, processes each `.json` file, and reformats
the content.
Args:
*args: Additional positional arguments (not used).
**kwargs: Additional keyword arguments (not used).
"""
default_settings = DefaultLoggingSettings()
log_dir: LogDir = settings.DJANGO_LOGGING.get(
"LOG_DIR", os.path.join(os.getcwd(), default_settings.log_dir)
)

try:
json_dir, pretty_dir = setup_directories(log_dir, "json")
except FileNotFoundError as e:
self.stdout.write(self.style.ERROR(str(e)))
return

for file_path, filename in process_files(json_dir, ".json", self.reformat_json):
self.stdout.write(self.style.NOTICE(f"Processing file: {file_path}"))

new_file_path: str = os.path.join(pretty_dir, f"formatted_{filename}")
self.reformat_json(file_path, new_file_path)

self.stdout.write(
self.style.SUCCESS(
f"File {filename} reformatted and generated new pretty file successfully."
)
)

def reformat_json(self, file_path: str, new_file_path: str) -> None:
"""Parses multiple JSON objects from a file incrementally and writes
them to a new file as a valid JSON array.
Args:
file_path (str): The path to the original JSON file.
new_file_path (str): The path where the reformatted JSON file will be saved.
"""
with open(file_path, encoding="utf-8") as infile, open(
new_file_path, "w", encoding="utf-8"
) as outfile:
outfile.write("[\n") # Start the JSON array
first_object = True # Flag to handle commas

buffer = "" # This will accumulate the JSON content

for line in infile:
line = line.strip()

if not line:
continue # Skip empty lines

buffer += line

# Try to parse the current buffer as a complete JSON object
try:
json_object = json.loads(buffer)
json_line = json.dumps(json_object, indent=4)

if not first_object:
outfile.write(",\n") # Add a comma before subsequent objects
outfile.write(json_line)

first_object = False
buffer = "" # Clear the buffer after successful parsing
except json.JSONDecodeError:
# Keep accumulating if it's not a complete JSON object yet
continue

if buffer:
# If any partial JSON is left in the buffer, log an error
self.stdout.write(self.style.ERROR(f"Incomplete JSON object: {buffer}"))

outfile.write("\n]") # End the JSON array
77 changes: 77 additions & 0 deletions django_logging/management/commands/generate_pretty_xml.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import os
from typing import Any, Dict, Tuple

from django.conf import settings
from django.core.management.base import BaseCommand

from django_logging.constants import DefaultLoggingSettings
from django_logging.constants.config_types import LogDir
from django_logging.utils.command.process_file import process_files, setup_directories


class Command(BaseCommand):
"""Command to find and reformat XML files in a specified directory.
This command processes all XML files in the specified log directory, reformats
them by wrapping their content in a <logs> element, and saves the reformatted
files to a new directory. It handles parsing errors and logs the process steps.
Attributes:
help (str): A brief description of the command's functionality.
"""

help = "Find and reformat XML files in a directory"

def handle(self, *args: Tuple[Any], **kwargs: Dict[str, Any]) -> None:
"""Handles the command execution.
Args:
*args: Positional arguments passed to the command.
**kwargs: Keyword arguments passed to the command.
"""
default_settings = DefaultLoggingSettings()
log_dir: LogDir = settings.DJANGO_LOGGING.get(
"LOG_DIR", os.path.join(os.getcwd(), default_settings.log_dir)
)

try:
xml_dir, pretty_dir = setup_directories(log_dir, "xml")
except FileNotFoundError as e:
self.stdout.write(self.style.ERROR(str(e)))
return

for file_path, filename in process_files(
xml_dir, ".xml", self.reformat_and_write_xml
):
self.stdout.write(self.style.NOTICE(f"Processing file: {file_path}"))

new_file_path = os.path.join(pretty_dir, f"formatted_{filename}")
self.reformat_and_write_xml(file_path, new_file_path)
self.stdout.write(
self.style.SUCCESS(f"File {filename} reformatted successfully.")
)

def reformat_and_write_xml(self, file_path: str, new_file_path: str) -> None:
"""Reformats XML content by wrapping it in a <logs> element and writes
it to a new file.
Args:
file_path (str): The path of the original XML file to be reformatted.
new_file_path (str): The path where the reformatted XML file will be saved.
"""
with open(file_path, encoding="utf-8") as infile, open(
new_file_path, "w", encoding="utf-8"
) as outfile:
# Start the <logs> element
outfile.write("<logs>\n")

for line in infile:
# Write each line to the formatted file
if line.strip(): # Only process non-empty lines
outfile.write(line)

# End the <logs> element
outfile.write("</logs>\n")

0 comments on commit a398786

Please sign in to comment.