mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-03 18:28:56 +00:00
[red-knot] Manually implement Debug
for VendoredFileSystem
(#11983)
This commit is contained in:
parent
715609663a
commit
92b145e56a
3 changed files with 132 additions and 3 deletions
|
@ -26,4 +26,5 @@ rustc-hash = { workspace = true }
|
|||
zip = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
insta = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::fmt::{self, Debug};
|
||||
use std::io::{self, Read};
|
||||
use std::sync::{Mutex, MutexGuard};
|
||||
|
||||
|
@ -16,7 +18,6 @@ type Result<T> = io::Result<T>;
|
|||
///
|
||||
/// "Files" in the `VendoredFileSystem` are read-only and immutable.
|
||||
/// Directories are supported, but symlinks and hardlinks cannot exist.
|
||||
#[derive(Debug)]
|
||||
pub struct VendoredFileSystem {
|
||||
inner: VendoredFileSystemInner,
|
||||
}
|
||||
|
@ -78,6 +79,74 @@ impl VendoredFileSystem {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for VendoredFileSystem {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let locked_inner = self.inner.lock();
|
||||
if f.alternate() {
|
||||
let mut paths: Vec<String> = locked_inner
|
||||
.borrow()
|
||||
.0
|
||||
.file_names()
|
||||
.map(String::from)
|
||||
.collect();
|
||||
paths.sort();
|
||||
let debug_info: BTreeMap<String, ZipFileDebugInfo> = paths
|
||||
.iter()
|
||||
.map(|path| {
|
||||
(
|
||||
path.to_owned(),
|
||||
ZipFileDebugInfo::from(locked_inner.borrow_mut().0.by_name(path).unwrap()),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
f.debug_struct("VendoredFileSystem")
|
||||
.field("inner_mutex_poisoned", &self.inner.0.is_poisoned())
|
||||
.field("paths", &paths)
|
||||
.field("data_by_path", &debug_info)
|
||||
.finish()
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"VendoredFileSystem(<{} paths>)",
|
||||
locked_inner.borrow().len()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Private struct only used in `Debug` implementations
|
||||
///
|
||||
/// This could possibly be unified with the `Metadata` struct,
|
||||
/// but that is deliberately kept small, and only exposes metadata
|
||||
/// that users of the `VendoredFileSystem` could realistically need.
|
||||
/// For debugging purposes, however, we want to have all information
|
||||
/// available.
|
||||
#[allow(unused)]
|
||||
#[derive(Debug)]
|
||||
struct ZipFileDebugInfo {
|
||||
crc32_hash: u32,
|
||||
compressed_size: u64,
|
||||
uncompressed_size: u64,
|
||||
compression_method: zip::CompressionMethod,
|
||||
kind: FileType,
|
||||
}
|
||||
|
||||
impl<'a> From<ZipFile<'a>> for ZipFileDebugInfo {
|
||||
fn from(value: ZipFile<'a>) -> Self {
|
||||
Self {
|
||||
crc32_hash: value.crc32(),
|
||||
compressed_size: value.compressed_size(),
|
||||
uncompressed_size: value.size(),
|
||||
compression_method: value.compression(),
|
||||
kind: if value.is_dir() {
|
||||
FileType::Directory
|
||||
} else {
|
||||
FileType::File
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum FileType {
|
||||
/// The path exists in the zip archive and represents a vendored file
|
||||
|
@ -126,7 +195,6 @@ impl Metadata {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct VendoredFileSystemInner(Mutex<RefCell<VendoredZipArchive>>);
|
||||
|
||||
type LockedZipArchive<'a> = MutexGuard<'a, RefCell<VendoredZipArchive>>;
|
||||
|
@ -160,6 +228,10 @@ impl VendoredZipArchive {
|
|||
fn lookup_path(&mut self, path: &NormalizedVendoredPath) -> Result<ZipFile> {
|
||||
Ok(self.0.by_name(path.as_str())?)
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
/// A path that has been normalized via the `normalize_vendored_path` function.
|
||||
|
@ -213,8 +285,10 @@ fn normalize_vendored_path(path: &VendoredPath) -> NormalizedVendoredPath {
|
|||
mod tests {
|
||||
use std::io::Write;
|
||||
|
||||
use insta::assert_snapshot;
|
||||
use once_cell::sync::Lazy;
|
||||
use zip::{write::FileOptions, CompressionMethod, ZipWriter};
|
||||
use zip::write::FileOptions;
|
||||
use zip::{CompressionMethod, ZipWriter};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -254,6 +328,59 @@ mod tests {
|
|||
VendoredFileSystem::new(&MOCK_ZIP_ARCHIVE).unwrap()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filesystem_debug_implementation() {
|
||||
assert_snapshot!(
|
||||
format!("{:?}", mock_typeshed()),
|
||||
@"VendoredFileSystem(<4 paths>)"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn filesystem_debug_implementation_alternate() {
|
||||
assert_snapshot!(format!("{:#?}", mock_typeshed()), @r###"
|
||||
VendoredFileSystem {
|
||||
inner_mutex_poisoned: false,
|
||||
paths: [
|
||||
"stdlib/",
|
||||
"stdlib/asyncio/",
|
||||
"stdlib/asyncio/tasks.pyi",
|
||||
"stdlib/functools.pyi",
|
||||
],
|
||||
data_by_path: {
|
||||
"stdlib/": ZipFileDebugInfo {
|
||||
crc32_hash: 0,
|
||||
compressed_size: 0,
|
||||
uncompressed_size: 0,
|
||||
compression_method: Stored,
|
||||
kind: Directory,
|
||||
},
|
||||
"stdlib/asyncio/": ZipFileDebugInfo {
|
||||
crc32_hash: 0,
|
||||
compressed_size: 0,
|
||||
uncompressed_size: 0,
|
||||
compression_method: Stored,
|
||||
kind: Directory,
|
||||
},
|
||||
"stdlib/asyncio/tasks.pyi": ZipFileDebugInfo {
|
||||
crc32_hash: 2826547428,
|
||||
compressed_size: 24,
|
||||
uncompressed_size: 15,
|
||||
compression_method: Zstd,
|
||||
kind: File,
|
||||
},
|
||||
"stdlib/functools.pyi": ZipFileDebugInfo {
|
||||
crc32_hash: 1099005079,
|
||||
compressed_size: 34,
|
||||
uncompressed_size: 25,
|
||||
compression_method: Zstd,
|
||||
kind: File,
|
||||
},
|
||||
},
|
||||
}
|
||||
"###);
|
||||
}
|
||||
|
||||
fn test_directory(dirname: &str) {
|
||||
let mock_typeshed = mock_typeshed();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue