Python parser plugin for CodeGraph - extracts code entities and relationships from Python source files into a queryable graph database.
- π Fast: Parse 1000 Python files in under 10 seconds
- π― Accurate: Extract functions, classes, methods, decorators, type hints
- π Relationships: Track function calls, imports, inheritance hierarchies
- βοΈ Configurable: Filter by visibility, file size, enable parallel processing
- π‘οΈ Safe: No panics, graceful error handling, continues on failures
- π Complete: 67 tests, 90%+ code coverage
- π Python 3.8+: Full support for async/await, decorators, type hints, match statements
- Functions: Names, signatures, parameters, return types, decorators, async flag
- Classes: Names, base classes, methods, fields, decorators, abstract flag
- Methods: Instance methods, static methods, class methods, properties
- Modules: File-level metadata and documentation
- Calls: Function and method call relationships (who calls whom)
- Imports: Module dependencies (import statements, from imports, wildcards)
- Inheritance: Class hierarchies (single and multiple inheritance)
- Implementations: Protocol/ABC implementations
Add to your Cargo.toml:
[dependencies]
codegraph = "0.1.1"
codegraph-python = "0.1.0"use codegraph_python::Parser;
use codegraph::CodeGraph;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut graph = CodeGraph::in_memory()?;
let parser = Parser::new();
let info = parser.parse_file(
std::path::Path::new("src/main.py"),
&mut graph
)?;
println!("Found {} functions", info.functions.len());
println!("Found {} classes", info.classes.len());
println!("Parsed in {:?}", info.parse_time);
Ok(())
}use codegraph_python::Parser;
use codegraph::CodeGraph;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut graph = CodeGraph::in_memory()?;
let parser = Parser::new();
let project_info = parser.parse_directory(
std::path::Path::new("src/"),
&mut graph
)?;
println!("Parsed {} files", project_info.files.len());
println!("Total functions: {}", project_info.total_functions);
println!("Total classes: {}", project_info.total_classes);
println!("Success rate: {:.1}%", project_info.success_rate());
Ok(())
}use codegraph_python::{Parser, ParserConfig};
use codegraph::CodeGraph;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut graph = CodeGraph::in_memory()?;
let config = ParserConfig {
include_private: false, // Skip private entities (_name)
include_tests: true, // Include test functions
parse_docs: true, // Extract docstrings
max_file_size: 10 * 1024 * 1024, // 10MB limit
file_extensions: vec!["py".to_string()],
exclude_dirs: vec![
"__pycache__".to_string(),
".venv".to_string(),
],
parallel: true, // Use parallel processing
num_threads: Some(4), // 4 threads
};
let parser = Parser::with_config(config);
let project_info = parser.parse_directory(
std::path::Path::new("src/"),
&mut graph
)?;
println!("Parsed {} files in {:?}",
project_info.files.len(),
project_info.total_time
);
Ok(())
}use codegraph_python::Parser;
use codegraph::CodeGraph;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut graph = CodeGraph::in_memory()?;
let parser = Parser::new();
let source = r#"
def greet(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
class Person:
def __init__(self, name: str):
self.name = name
def introduce(self) -> str:
return greet(self.name)
"#;
let info = parser.parse_source(
source,
std::path::Path::new("example.py"),
&mut graph
)?;
println!("Found {} entities", info.entity_count());
Ok(())
}
```rust
use codegraph_python::Parser;
use codegraph::CodeGraph;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut graph = CodeGraph::open("./project.graph")?;
let parser = Parser::new();
let info = parser.parse_project(&mut graph, "./src")?;
println!("Files parsed: {}", info.files.len());
println!("Total functions: {}", info.total_functions);
println!("Total classes: {}", info.total_classes);
println!("Parse time: {:?}", info.total_time);
Ok(())
}use codegraph_python::{Parser, ParserConfig};
let config = ParserConfig {
include_private: false,
include_tests: false,
parse_docs: true,
max_file_size: 5 * 1024 * 1024, // 5MB
parallel: true,
num_threads: Some(4),
..Default::default()
};
let parser = Parser::with_config(config);See the examples/ directory for more:
basic_parse.rs- Parse a single fileproject_stats.rs- Parse a project and show statisticscall_graph.rs- Extract function call relationshipsdependency_analysis.rs- Analyze import dependencies
Run examples with:
cargo run --example basic_parsePerformance targets (measured on modern hardware):
- Single file (<1000 lines): <10ms
- Single file (1000-10000 lines): <100ms
- Project (100 files): <1 second
- Project (1000 files): <10 seconds
- Memory usage (1000 files): <500MB
Supports Python 3.8+ syntax including:
- β Functions and async functions
- β Classes with inheritance
- β Decorators
- β Type hints
- β Match statements (Python 3.10+)
- β Protocols and Abstract Base Classes
- β Import statements (including wildcards)
Licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0).
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be licensed under the Apache-2.0 license, without any additional terms or conditions.