mod common;
use common::sqry_bin;
use assert_cmd::Command;
use predicates::prelude::*;
use tempfile::TempDir;
#[test]
fn cli_python_exports_functions_and_classes() {
let project = TempDir::new().unwrap();
let py_code = r#"
__all__ = ["greet", "User", "API_VERSION"]
def greet(name):
"""Greet a user by name."""
return f"Hello, {name}!"
def farewell(name):
"""Say goodbye to a user."""
return f"Goodbye, {name}!"
class User:
def __init__(self, name):
self.name = name
def get_name(self):
return self.name
API_VERSION = "1.0.0"
"#;
std::fs::write(project.path().join("module.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("exports:greet")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("module.py"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:User")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("module.py"));
}
#[test]
fn cli_python_exports_with_all() {
let project = TempDir::new().unwrap();
let py_code = r#"
__all__ = ['public_function', 'PublicClass']
def public_function():
return "public"
def _private_function():
return "private"
class PublicClass:
pass
class _PrivateClass:
pass
"#;
std::fs::write(project.path().join("exports.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("exports:public_function")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("exports.py"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:PublicClass")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("exports.py"));
Command::new(sqry_bin())
.arg("query")
.arg("exports:_private_function")
.arg(project.path())
.assert()
.success()
.stderr(predicate::str::contains("No matches found"));
}
#[test]
fn cli_python_callers_function_calls() {
let project = TempDir::new().unwrap();
let py_code = r#"
def validate(input_str):
return len(input_str) > 0
def process(data):
if validate(data):
return data.strip()
return None
process("test")
"#;
std::fs::write(project.path().join("processor.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:validate")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("process"));
}
#[test]
fn cli_python_callers_method_calls() {
let project = TempDir::new().unwrap();
let py_code = r"
class DataService:
def fetch_data(self):
return []
def transform_data(self, data):
return [x * 2 for x in data]
def process(self):
data = self.fetch_data()
return self.transform_data(data)
service = DataService()
service.process()
";
std::fs::write(project.path().join("service.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:fetch_data")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("process"));
Command::new(sqry_bin())
.arg("query")
.arg("callers:transform_data")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("process"));
}
#[test]
fn cli_python_callers_chained_method_calls() {
let project = TempDir::new().unwrap();
let py_code = r"
class QueryBuilder:
def where(self, condition):
return self
def order_by(self, field):
return self
def limit(self, count):
return self
def execute(self):
return []
def run_query():
return (QueryBuilder()
.where('active = true')
.order_by('created_at')
.limit(10)
.execute())
run_query()
";
std::fs::write(project.path().join("query.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:where")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("run_query"));
Command::new(sqry_bin())
.arg("query")
.arg("callers:execute")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("run_query"));
}
#[test]
fn cli_python_callees_function() {
let project = TempDir::new().unwrap();
let py_code = r#"
def log(message):
print(message)
def warn(message):
print(f"WARNING: {message}")
def handle_error(error):
log('Error occurred')
warn(str(error))
print(error)
handle_error(Exception('Test'))
"#;
std::fs::write(project.path().join("logger.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callees:handle_error")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("log"))
.stdout(predicate::str::contains("warn"));
}
#[test]
fn cli_python_callees_method() {
let project = TempDir::new().unwrap();
let py_code = r"
class UserService:
def find_user(self, user_id):
return {'id': user_id, 'name': 'Test'}
def validate_user(self, user):
return user['id'] > 0
def get_user(self, user_id):
user = self.find_user(user_id)
if self.validate_user(user):
return user
return None
service = UserService()
service.get_user(1)
";
std::fs::write(project.path().join("user_service.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callees:get_user")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("find_user"))
.stdout(predicate::str::contains("validate_user"));
}
#[test]
fn cli_python_imports_from_import() {
let project = TempDir::new().unwrap();
let py_code = r"
from utils import greet, farewell
from user import User
from helpers import *
def main():
user = User('Alice')
greet(user.get_name())
main()
";
std::fs::write(project.path().join("main.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("imports:user")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("main.py"));
Command::new(sqry_bin())
.arg("query")
.arg("imports:utils")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("main.py"));
}
#[test]
fn cli_python_imports_import_statement() {
let project = TempDir::new().unwrap();
let py_code = r"
import os
import sys
import json
def read_config():
config_path = os.path.join(os.getcwd(), 'config.json')
with open(config_path) as f:
return json.load(f)
read_config()
";
std::fs::write(project.path().join("config.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("imports:os")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("config.py"));
Command::new(sqry_bin())
.arg("query")
.arg("imports:json")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("config.py"));
}
#[test]
fn cli_python_decorators() {
let project = TempDir::new().unwrap();
let py_code = r#"
def log_decorator(func):
def wrapper(*args, **kwargs):
print(f"Calling {func.__name__}")
return func(*args, **kwargs)
return wrapper
class UserService:
@log_decorator
def create_user(self, name):
print(f"Creating user: {name}")
@log_decorator
def delete_user(self, user_id):
print(f"Deleting user: {user_id}")
service = UserService()
service.create_user("Alice")
"#;
std::fs::write(project.path().join("decorators.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:create_user")
.arg(project.path())
.assert()
.success();
}
#[test]
fn cli_python_async_await() {
let project = TempDir::new().unwrap();
let py_code = r"
async def fetch_user(user_id):
return {'id': user_id, 'name': 'Test'}
async def fetch_posts(user_id):
return []
async def get_user_data(user_id):
user = await fetch_user(user_id)
posts = await fetch_posts(user['id'])
return {'user': user, 'posts': posts}
import asyncio
asyncio.run(get_user_data(1))
";
std::fs::write(project.path().join("async_code.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callees:get_user_data")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("fetch_user"))
.stdout(predicate::str::contains("fetch_posts"));
}
#[test]
fn cli_python_class_methods_and_static_methods() {
let project = TempDir::new().unwrap();
let py_code = r"
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@classmethod
def multiply(cls, a, b):
return a * b
def divide(self, a, b):
return a / b
def calculate():
result1 = MathUtils.add(2, 3)
result2 = MathUtils.multiply(2, 3)
utils = MathUtils()
result3 = utils.divide(6, 2)
return result1 + result2 + result3
calculate()
";
std::fs::write(project.path().join("math_utils.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:add")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("calculate"));
Command::new(sqry_bin())
.arg("query")
.arg("callers:multiply")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("calculate"));
}
#[test]
fn cli_python_private_methods() {
let project = TempDir::new().unwrap();
let py_code = r"
class Service:
def execute(self):
self._validate()
def _validate(self):
# private method (by convention)
pass
";
std::fs::write(project.path().join("service.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:_validate")
.arg(project.path())
.assert()
.success()
.stdout(predicate::str::contains("execute"));
}
#[test]
fn cli_python_callers_no_results() {
let project = TempDir::new().unwrap();
let py_code = r"
def unused_function():
return 42
def main():
print('Hello')
main()
";
std::fs::write(project.path().join("unused.py"), py_code).unwrap();
Command::new(sqry_bin())
.arg("index")
.arg(project.path())
.assert()
.success();
Command::new(sqry_bin())
.arg("query")
.arg("callers:unused_function")
.arg(project.path())
.assert()
.success();
}