| Crates.io | pyimports |
| lib.rs | pyimports |
| version | 0.6.7 |
| created_at | 2023-12-10 19:30:55.279371+00 |
| updated_at | 2025-01-16 22:08:31.099364+00 |
| description | Parse and analyze the imports within a python package |
| homepage | |
| repository | https://github.com/Peter554/pyimports |
| max_upload_size | |
| id | 1064473 |
| size | 230,722 |
A rust crate for parsing and analyzing the imports within a python package.
A short example (for more information refer to the docs):
use anyhow::Result;
use maplit::{hashmap,hashset};
use pyimports::prelude::*;
use pyimports::package_info::{PackageInfo,PackageItemToken};
use pyimports::imports_info::{ImportsInfo,InternalImportsPathQueryBuilder};
// You shouldn't use `testpackage!`, it just creates a fake python package
// in a temporary directory. It's (unfortunately) included in the public API
// so that it can be used in the doctests.
use pyimports::{testpackage,testutils::TestPackage};
fn main() -> Result<()> {
let testpackage = testpackage! {
"__init__.py" => "from testpackage import a, b",
"a.py" => "from testpackage import b",
"b.py" => "from testpackage import c, d",
"c.py" => "from testpackage import d",
"d.py" => ""
};
let package_info = PackageInfo::build(testpackage.path())?;
let imports_info = ImportsInfo::build(package_info)?;
let item = |pypath: &str| -> Result<PackageItemToken> {
Ok(imports_info.package_info().get_item_by_pypath(&pypath.parse()?).unwrap().token())
};
let root_pkg = item("testpackage")?;
let root_init = item("testpackage.__init__")?;
let a = item("testpackage.a")?;
let b = item("testpackage.b")?;
let c = item("testpackage.c")?;
let d = item("testpackage.d")?;
assert_eq!(
imports_info.internal_imports().get_direct_imports(),
hashmap! {
root_pkg => hashset!{root_init},
root_init => hashset!{a, b},
a => hashset!{b},
b => hashset!{c, d},
c => hashset!{d},
d => hashset!{},
}
);
assert_eq!(
imports_info.internal_imports().get_items_directly_imported_by(root_init)?,
hashset! {a, b}
);
assert_eq!(
imports_info.internal_imports().get_items_that_directly_import(d)?,
hashset! {b, c}
);
assert_eq!(
imports_info.internal_imports().get_downstream_items(root_init)?,
hashset! {a, b, c, d}
);
assert_eq!(
imports_info.internal_imports().find_path(
&InternalImportsPathQueryBuilder::default()
.from(root_init)
.to(d)
.build()?
)?,
Some(vec![root_init, b, d])
);
Ok(())
}
This crate might be useful for something eventually, but right now it's mainly just a hobby project for me to learn about rust.
If you are looking for something more mature, try grimp/import-linter.
The python parser used within this crate does not currently support python 3.12+ - see the related GitHub issue here.
Some possible next steps that I may explore if/when I get time: