Skip to content

Command

Command implementation for code documentation generation.

logger module-attribute

logger = getLogger(__name__)

show_error

show_error(message: str) -> None

Display an error message using the console.

Parameters:

Name Type Description Default
message str

The error message to display

required
Source code in src/codemap/gen/command.py
25
26
27
28
29
30
31
32
def show_error(message: str) -> None:
	"""
	Display an error message using the console.

	Args:
		message: The error message to display
	"""
	console.print(f"[red]Error:[/red] {message}")

process_codebase

process_codebase(
	target_path: Path,
	config: GenConfig,
	config_loader: ConfigLoader | None = None,
) -> tuple[list[LODEntity], dict]

Process a codebase using the LOD pipeline architecture.

Parameters:

Name Type Description Default
target_path Path

Path to the target codebase

required
config GenConfig

Generation configuration

required
config_loader ConfigLoader | None

Optional ConfigLoader instance to use

None

Returns:

Type Description
tuple[list[LODEntity], dict]

Tuple of (list of LOD entities, metadata dict)

Raises:

Type Description
RuntimeError

If processing fails

Source code in src/codemap/gen/command.py
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
def process_codebase(
	target_path: Path,
	config: GenConfig,
	config_loader: ConfigLoader | None = None,
) -> tuple[list[LODEntity], dict]:
	"""
	Process a codebase using the LOD pipeline architecture.

	Args:
	    target_path: Path to the target codebase
	    config: Generation configuration
	    config_loader: Optional ConfigLoader instance to use

	Returns:
	    Tuple of (list of LOD entities, metadata dict)

	Raises:
	    RuntimeError: If processing fails

	"""
	logger.info("Starting codebase processing for: %s", target_path)

	# Get processor configuration from ConfigLoader
	if config_loader is None:
		config_loader = ConfigLoader().get_instance()
		logger.debug("Created new ConfigLoader instance in process_codebase")

	processor_config = config_loader.get.processor
	max_workers = processor_config.max_workers
	logger.debug(f"Using max_workers: {max_workers} from configuration")

	try:
		# Need project root to correctly locate .gitignore
		project_root = Path.cwd()  # Assuming CWD is project root
		all_paths = list(target_path.rglob("*"))

		# Filter paths based on .gitignore patterns found in project_root
		filtered_paths: Sequence[Path] = filter_paths_by_gitignore(all_paths, project_root)

		# Filter out binary files
		processable_paths = []
		for path in filtered_paths:
			if path.is_file():
				if not is_binary_file(path):
					processable_paths.append(path)
				else:
					logger.debug(f"Skipping binary file: {path}")

		# Use the new utility function to process files and generate LOD entities
		# The utility function will handle parallel processing and progress updates
		entities = process_files_for_lod(
			paths=processable_paths,
			lod_level=config.lod_level,
			max_workers=max_workers,  # Get from configuration
		)
	except Exception as e:
		logger.exception("Error during LOD file processing")
		error_msg = f"LOD processing failed: {e}"
		raise RuntimeError(error_msg) from e

	# Update counts based on actual processed entities
	processed_files = len(entities)
	logger.info(f"LOD processing complete. Generated {processed_files} entities.")
	# total_files count is now handled within process_files_for_lod for progress

	# Generate repository metadata
	languages = {entity.language for entity in entities if entity.language}
	# Get total file count accurately from the filtered list *before* processing
	total_files_scanned = len(processable_paths)

	metadata: dict[str, Any] = {
		"name": target_path.name,
		"target_path": str(target_path.resolve()),  # Keep absolute target path for file path resolution
		"original_path": str(target_path),  # Store original path as provided in the command (could be relative)
		"stats": {
			"total_files_scanned": total_files_scanned,  # Total files scanned matching criteria
			"processed_files": processed_files,  # Files successfully processed for LOD
			"total_lines": sum(entity.end_line - entity.start_line + 1 for entity in entities),
			"languages": list(languages),
		},
	}

	# Generate directory tree if requested
	if config.include_tree:
		metadata["tree"] = generate_tree(target_path, filtered_paths)

	return entities, metadata

GenCommand

Main implementation of the gen command.

Source code in src/codemap/gen/command.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
class GenCommand:
	"""Main implementation of the gen command."""

	def __init__(self, config: GenConfig, config_loader: ConfigLoader | None = None) -> None:
		"""
		Initialize the gen command.

		Args:
		    config: Generation configuration
		    config_loader: Optional ConfigLoader instance to use

		"""
		self.config = config
		self.config_loader = config_loader or ConfigLoader()
		logger.debug("GenCommand initialized with ConfigLoader")

	def execute(self, target_path: Path, output_path: Path) -> bool:
		"""
		Execute the gen command.

		Args:
		    target_path: Path to the target codebase
		    output_path: Path to write the output

		Returns:
		    True if successful, False otherwise

		"""
		from .generator import CodeMapGenerator
		from .utils import write_documentation

		start_time = time.time()

		try:
			# Create generator
			generator = CodeMapGenerator(self.config, output_path)

			# Process codebase with progress tracking
			with progress_indicator("Processing codebase..."):
				# Process the codebase
				entities, metadata = process_codebase(target_path, self.config, config_loader=self.config_loader)

			# Generate documentation
			console.print("[green]Processing complete. Generating documentation...")
			content = generator.generate_documentation(entities, metadata)

			# Write documentation to output file
			write_documentation(output_path, content)

			# Show completion message with timing
			elapsed = time.time() - start_time
			console.print(f"[green]Generation completed in {elapsed:.2f} seconds.")

			return True

		except Exception as e:
			logger.exception("Error during gen command execution")
			show_error(f"Generation failed: {e}")
			return False

__init__

__init__(
	config: GenConfig,
	config_loader: ConfigLoader | None = None,
) -> None

Initialize the gen command.

Parameters:

Name Type Description Default
config GenConfig

Generation configuration

required
config_loader ConfigLoader | None

Optional ConfigLoader instance to use

None
Source code in src/codemap/gen/command.py
127
128
129
130
131
132
133
134
135
136
137
138
def __init__(self, config: GenConfig, config_loader: ConfigLoader | None = None) -> None:
	"""
	Initialize the gen command.

	Args:
	    config: Generation configuration
	    config_loader: Optional ConfigLoader instance to use

	"""
	self.config = config
	self.config_loader = config_loader or ConfigLoader()
	logger.debug("GenCommand initialized with ConfigLoader")

config instance-attribute

config = config

config_loader instance-attribute

config_loader = config_loader or ConfigLoader()

execute

execute(target_path: Path, output_path: Path) -> bool

Execute the gen command.

Parameters:

Name Type Description Default
target_path Path

Path to the target codebase

required
output_path Path

Path to write the output

required

Returns:

Type Description
bool

True if successful, False otherwise

Source code in src/codemap/gen/command.py
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
def execute(self, target_path: Path, output_path: Path) -> bool:
	"""
	Execute the gen command.

	Args:
	    target_path: Path to the target codebase
	    output_path: Path to write the output

	Returns:
	    True if successful, False otherwise

	"""
	from .generator import CodeMapGenerator
	from .utils import write_documentation

	start_time = time.time()

	try:
		# Create generator
		generator = CodeMapGenerator(self.config, output_path)

		# Process codebase with progress tracking
		with progress_indicator("Processing codebase..."):
			# Process the codebase
			entities, metadata = process_codebase(target_path, self.config, config_loader=self.config_loader)

		# Generate documentation
		console.print("[green]Processing complete. Generating documentation...")
		content = generator.generate_documentation(entities, metadata)

		# Write documentation to output file
		write_documentation(output_path, content)

		# Show completion message with timing
		elapsed = time.time() - start_time
		console.print(f"[green]Generation completed in {elapsed:.2f} seconds.")

		return True

	except Exception as e:
		logger.exception("Error during gen command execution")
		show_error(f"Generation failed: {e}")
		return False