Extensible Code Annotation Parser
code-annotations provides extensible tools for parsing annotations within codebases. It allows users to define custom annotation contexts and search for specific patterns across various file types. The library is currently at version 3.0.0, with frequent dependency updates and regular minor/major releases.
Common errors
-
ModuleNotFoundError: No module named 'code_annotations'
cause The `code-annotations` library is not installed in the current Python environment.fixRun `pip install code-annotations` to install the library. -
ERROR: Package 'code-annotations' requires Python '>=3.12', but you have Python 3.11.0.
cause Attempting to install version 3.0.0 or later of `code-annotations` on an unsupported Python version.fixUpgrade your Python environment to 3.12 or newer, or install a compatible older version of `code-annotations` (e.g., `pip install 'code-annotations<3.0.0'`).
Warnings
- breaking Version 3.0.0 of `code-annotations` dropped support for Python 3.11. It now requires Python >=3.12.
- breaking Version 2.0.0 of `code-annotations` dropped support for Python 3.8. It moved to supporting Python 3.11 and 3.12 at that time.
- gotcha The core functionality relies on custom `AnnotationContext` implementations. Incorrectly defining `is_inline_annotation_context`, `get_inline_annotation_key`, or `get_inline_annotation_value` can lead to missed annotations or parsing errors.
Install
-
pip install code-annotations
Imports
- find_annotations
from code_annotations.find_annotations import find_annotations
- AnnotationContext
from code_annotations.annotation_contexts import AnnotationContext
Quickstart
import tempfile
import os
import shutil
from pathlib import Path
from code_annotations.find_annotations import find_annotations
from code_annotations.annotation_contexts import AnnotationContext
# 1. Define a custom AnnotationContext
class MyCustomAnnotationContext(AnnotationContext):
"""
A simple context to find annotations like:
# TODO: Finish this feature
# REVIEW: Check performance
"""
context_name = "MY_CUSTOM"
@staticmethod
def is_inline_annotation_context(line):
return "# TODO:" in line or "# REVIEW:" in line
@staticmethod
def get_inline_annotation_key(line):
if "# TODO:" in line:
return "TODO"
elif "# REVIEW:" in line:
return "REVIEW"
return None
@staticmethod
def get_inline_annotation_value(line):
if "# TODO:" in line:
return line.split("# TODO:", 1)[1].strip()
elif "# REVIEW:" in line:
return line.split("# REVIEW:", 1)[1].strip()
return None
# 2. Create a dummy file in a temporary directory
temp_dir = Path(tempfile.mkdtemp())
dummy_file = temp_dir / "example_code.py"
dummy_file.write_text("""
def my_function():
# TODO: Implement actual logic
print("Hello, World!")
# REVIEW: This might be slow for large inputs
pass
class MyClass:
# TODO: Add docstrings
def __init__(self):
pass
""")
try:
# 3. Find annotations
results = find_annotations(
src_dir=str(temp_dir),
annotation_contexts=[MyCustomAnnotationContext],
file_extensions=['.py'],
root_dir_to_scan=str(temp_dir),
)
# 4. Print results
print(f"Found annotations in: {temp_dir}")
for file_path, annotations in results.items():
print(f" File: {file_path}")
for annotation in annotations:
print(f" [{annotation.context_name}] {annotation.key}: {annotation.value} at line {annotation.line}")
finally:
# Clean up the temporary directory
shutil.rmtree(temp_dir)