diff --git a/Cargo.lock b/Cargo.lock index 6af780643..871089aad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,6 +1092,12 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "deunicode" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00" + [[package]] name = "dialoguer" version = "0.11.0" @@ -1358,6 +1364,16 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "fake" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c25829bde82205da46e1823b2259db6273379f626fc211f126f65654a2669be" +dependencies = [ + "deunicode", + "rand", +] + [[package]] name = "fancy_display" version = "0.1.0" @@ -3328,8 +3344,10 @@ dependencies = [ "distribution-filename", "distribution-types", "dunce", + "fake", "fancy_display", "flate2", + "fs-err", "fs_extra", "futures", "http 1.1.0", @@ -3542,6 +3560,7 @@ dependencies = [ "rattler_networking", "reqwest 0.12.5", "reqwest-middleware", + "rstest", "serde", "serde_json", "serde_yaml", @@ -5742,9 +5761,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", diff --git a/Cargo.toml b/Cargo.toml index be462c6fb..8fc333620 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ distribution-types = { git = "https://github.com/astral-sh/uv", tag = "0.4.0" } dunce = "1.0.4" fd-lock = "4.0.2" flate2 = "1.0.28" +fs-err = { version = "2.11.0" } fs_extra = "1.3.0" futures = "0.3.30" http = "1.1.0" @@ -229,6 +230,7 @@ rattler_repodata_gateway = { workspace = true, features = [ rattler_shell = { workspace = true, features = ["sysinfo"] } rattler_solve = { workspace = true, features = ["resolvo", "serde"] } +fs-err = { workspace = true, features = ["tokio"] } pixi_config = { workspace = true, features = ["rattler_repodata_gateway"] } pixi_consts = { workspace = true } pixi_default_versions = { workspace = true } @@ -302,6 +304,7 @@ strip = false [dev-dependencies] async-trait = { workspace = true } +fake = "2.9.2" http = { workspace = true } insta = { workspace = true, features = ["yaml", "glob"] } rstest = { workspace = true } diff --git a/crates/pixi_consts/src/consts.rs b/crates/pixi_consts/src/consts.rs index 6b8c6690f..78608db9f 100644 --- a/crates/pixi_consts/src/consts.rs +++ b/crates/pixi_consts/src/consts.rs @@ -22,6 +22,8 @@ pub const TASK_CACHE_DIR: &str = "task-cache-v0"; pub const PIXI_UV_INSTALLER: &str = "uv-pixi"; pub const CONDA_PACKAGE_CACHE_DIR: &str = rattler_cache::PACKAGE_CACHE_DIR; pub const CONDA_REPODATA_CACHE_DIR: &str = rattler_cache::REPODATA_CACHE_DIR; +// TODO: move to rattler +pub const CONDA_META_DIR: &str = "conda-meta"; pub const PYPI_CACHE_DIR: &str = "uv-cache"; pub const CONDA_PYPI_MAPPING_CACHE_DIR: &str = "conda-pypi-mapping"; pub const CACHED_ENVS_DIR: &str = "cached-envs-v0"; @@ -39,6 +41,7 @@ lazy_static! { pub static ref TASK_STYLE: Style = Style::new().blue(); pub static ref PLATFORM_STYLE: Style = Style::new().yellow(); pub static ref ENVIRONMENT_STYLE: Style = Style::new().magenta(); + pub static ref EXPOSED_NAME_STYLE: Style = Style::new().yellow(); pub static ref FEATURE_STYLE: Style = Style::new().cyan(); pub static ref SOLVE_GROUP_STYLE: Style = Style::new().cyan(); pub static ref DEFAULT_PYPI_INDEX_URL: Url = Url::parse("https://pypi.org/simple").unwrap(); diff --git a/crates/pixi_manifest/src/channel.rs b/crates/pixi_manifest/src/channel.rs index b777433a3..7841dd2d4 100644 --- a/crates/pixi_manifest/src/channel.rs +++ b/crates/pixi_manifest/src/channel.rs @@ -1,7 +1,8 @@ use std::str::FromStr; +use itertools::Itertools; use rattler_conda_types::NamedChannelOrUrl; -use serde::{de::Error, Deserialize, Deserializer}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use serde_with::serde_as; use toml_edit::{Table, Value}; @@ -9,12 +10,32 @@ use toml_edit::{Table, Value}; /// If the priority is not specified, it is assumed to be 0. /// The higher the priority, the more important the channel is. #[serde_as] -#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] pub struct PrioritizedChannel { pub channel: NamedChannelOrUrl, pub priority: Option, } +impl PrioritizedChannel { + /// The prioritized channels contain a priority, sort on this priority. + /// Higher priority comes first. [-10, 1, 0 ,2] -> [2, 1, 0, -10] + pub fn sort_channels_by_priority<'a, I>( + channels: I, + ) -> impl Iterator + where + I: IntoIterator, + { + channels + .into_iter() + .sorted_by(|a, b| { + let a = a.priority.unwrap_or(0); + let b = b.priority.unwrap_or(0); + b.cmp(&a) + }) + .map(|prioritized_channel| &prioritized_channel.channel) + } +} + impl From for PrioritizedChannel { fn from(value: NamedChannelOrUrl) -> Self { Self { @@ -64,6 +85,19 @@ impl TomlPrioritizedChannelStrOrMap { } } +impl From for TomlPrioritizedChannelStrOrMap { + fn from(channel: PrioritizedChannel) -> Self { + if let Some(priority) = channel.priority { + TomlPrioritizedChannelStrOrMap::Map(PrioritizedChannel { + channel: channel.channel, + priority: Some(priority), + }) + } else { + TomlPrioritizedChannelStrOrMap::Str(channel.channel) + } + } +} + impl<'de> Deserialize<'de> for TomlPrioritizedChannelStrOrMap { fn deserialize(deserializer: D) -> Result where @@ -81,8 +115,20 @@ impl<'de> Deserialize<'de> for TomlPrioritizedChannelStrOrMap { } } +impl Serialize for TomlPrioritizedChannelStrOrMap { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + TomlPrioritizedChannelStrOrMap::Map(map) => map.serialize(serializer), + TomlPrioritizedChannelStrOrMap::Str(str) => str.serialize(serializer), + } + } +} + /// Helper so that we can deserialize -/// [`crate::project::manifest::serde::PrioritizedChannel`] from a string or a +/// [`crate::channel::PrioritizedChannel`] from a string or a /// map. impl<'de> serde_with::DeserializeAs<'de, PrioritizedChannel> for TomlPrioritizedChannelStrOrMap { fn deserialize_as(deserializer: D) -> Result @@ -93,3 +139,16 @@ impl<'de> serde_with::DeserializeAs<'de, PrioritizedChannel> for TomlPrioritized Ok(prioritized_channel.into_prioritized_channel()) } } + +/// Helper so that we can serialize +/// [`crate::channel::PrioritizedChannel`] to a string or a +/// map. +impl serde_with::SerializeAs for TomlPrioritizedChannelStrOrMap { + fn serialize_as(source: &PrioritizedChannel, serializer: S) -> Result + where + S: Serializer, + { + let toml_prioritized_channel: TomlPrioritizedChannelStrOrMap = source.clone().into(); + toml_prioritized_channel.serialize(serializer) + } +} diff --git a/crates/pixi_manifest/src/features_ext.rs b/crates/pixi_manifest/src/features_ext.rs index 0b47f4f7c..a0723d80c 100644 --- a/crates/pixi_manifest/src/features_ext.rs +++ b/crates/pixi_manifest/src/features_ext.rs @@ -4,7 +4,7 @@ use indexmap::IndexSet; use rattler_conda_types::{NamedChannelOrUrl, Platform}; use rattler_solve::ChannelPriority; -use crate::{HasManifestRef, SpecType}; +use crate::{HasManifestRef, PrioritizedChannel, SpecType}; use crate::has_features_iter::HasFeaturesIter; use crate::{pypi::pypi_options::PypiOptions, SystemRequirements}; @@ -35,24 +35,12 @@ pub trait FeaturesExt<'source>: HasManifestRef<'source> + HasFeaturesIter<'sourc fn channels(&self) -> IndexSet<&'source NamedChannelOrUrl> { // Collect all the channels from the features in one set, // deduplicate them and sort them on feature index, default feature comes last. - let channels: IndexSet<_> = self - .features() - .flat_map(|feature| match &feature.channels { - Some(channels) => channels, - None => &self.manifest().parsed.project.channels, - }) - .collect(); + let channels = self.features().flat_map(|feature| match &feature.channels { + Some(channels) => channels, + None => &self.manifest().parsed.project.channels, + }); - // The prioritized channels contain a priority, sort on this priority. - // Higher priority comes first. [-10, 1, 0 ,2] -> [2, 1, 0, -10] - channels - .sorted_by(|a, b| { - let a = a.priority.unwrap_or(0); - let b = b.priority.unwrap_or(0); - b.cmp(&a) - }) - .map(|prioritized_channel| &prioritized_channel.channel) - .collect() + PrioritizedChannel::sort_channels_by_priority(channels).collect() } /// Returns the channel priority, error on multiple values, return None if no value is set. diff --git a/crates/pixi_manifest/src/lib.rs b/crates/pixi_manifest/src/lib.rs index 09d0ff64b..326de2259 100644 --- a/crates/pixi_manifest/src/lib.rs +++ b/crates/pixi_manifest/src/lib.rs @@ -24,13 +24,15 @@ mod validation; pub use dependencies::{CondaDependencies, Dependencies, PyPiDependencies}; pub use manifests::manifest::{Manifest, ManifestKind}; +pub use manifests::TomlManifest; pub use crate::environments::Environments; -pub use crate::parsed_manifest::ParsedManifest; +pub use crate::parsed_manifest::{deserialize_package_map, ParsedManifest}; pub use crate::solve_group::{SolveGroup, SolveGroups}; pub use activation::Activation; -pub use channel::PrioritizedChannel; +pub use channel::{PrioritizedChannel, TomlPrioritizedChannelStrOrMap}; pub use environment::{Environment, EnvironmentName}; +pub use error::TomlError; pub use feature::{Feature, FeatureName}; use itertools::Itertools; pub use metadata::ProjectMetadata; diff --git a/crates/pixi_manifest/src/manifests/mod.rs b/crates/pixi_manifest/src/manifests/mod.rs index 6a8f78a47..ac3cc3c5a 100644 --- a/crates/pixi_manifest/src/manifests/mod.rs +++ b/crates/pixi_manifest/src/manifests/mod.rs @@ -1,3 +1,5 @@ +use std::fmt; + use toml_edit::{self, Array, Item, Table, TableLike, Value}; pub mod project; @@ -20,10 +22,15 @@ impl TomlManifest { Self(document) } + /// Get or insert a top-level item + pub fn get_or_insert<'a>(&'a mut self, key: &str, item: Item) -> &'a Item { + self.0.entry(key).or_insert(item) + } + /// Retrieve a mutable reference to a target table `table_name` /// in dotted form (e.g. `table1.table2`) from the root of the document. /// If the table is not found, it is inserted into the document. - fn get_or_insert_nested_table<'a>( + pub fn get_or_insert_nested_table<'a>( &'a mut self, table_name: &str, ) -> Result<&'a mut dyn TableLike, TomlError> { @@ -45,6 +52,49 @@ impl TomlManifest { Ok(current_table) } + /// Inserts a value into a certain table + /// If the most inner table doesn't exist, an inline table will be created. + /// If it already exists, the formatting of the table will be preserved + pub fn insert_into_inline_table<'a>( + &'a mut self, + table_name: &str, + key: &str, + value: Value, + ) -> Result<&'a mut dyn TableLike, TomlError> { + let mut parts: Vec<&str> = table_name.split('.').collect(); + + let last = parts.pop(); + + let mut current_table = self.0.as_table_mut() as &mut dyn TableLike; + + for part in parts { + let entry = current_table.entry(part); + let item = entry.or_insert(Item::Table(Table::new())); + if let Some(table) = item.as_table_mut() { + // Avoid creating empty tables + table.set_implicit(true); + } + current_table = item + .as_table_like_mut() + .ok_or_else(|| TomlError::table_error(part, table_name))?; + } + + // Add dependency as inline table if it doesn't exist + if let Some(last) = last { + if let Some(dependency) = current_table.get_mut(last) { + dependency + .as_table_like_mut() + .map(|table| table.insert(key, Item::Value(value))); + } else { + let mut dependency = toml_edit::InlineTable::new(); + dependency.insert(key, value); + current_table.insert(last, toml_edit::value(dependency)); + } + } + + Ok(current_table) + } + /// Retrieves a mutable reference to a target array `array_name` /// in table `table_name` in dotted form (e.g. `table1.table2.array`). /// @@ -78,6 +128,12 @@ impl TomlManifest { } } +impl fmt::Display for TomlManifest { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/crates/pixi_utils/Cargo.toml b/crates/pixi_utils/Cargo.toml index 5f1158cff..ea3feb0f9 100644 --- a/crates/pixi_utils/Cargo.toml +++ b/crates/pixi_utils/Cargo.toml @@ -46,3 +46,4 @@ url = { workspace = true } [dev-dependencies] insta = { workspace = true } +rstest = { workspace = true } diff --git a/crates/pixi_utils/src/executable_utils.rs b/crates/pixi_utils/src/executable_utils.rs new file mode 100644 index 000000000..ab70c7548 --- /dev/null +++ b/crates/pixi_utils/src/executable_utils.rs @@ -0,0 +1,124 @@ +use std::path::Path; + +/// Strips known Windows executable extensions from a file name. +pub(crate) fn strip_windows_executable_extension(file_name: String) -> String { + let file_name = file_name.to_lowercase(); + // Attempt to retrieve the PATHEXT environment variable + let extensions_list: Vec = if let Ok(pathext) = std::env::var("PATHEXT") { + pathext.split(';').map(|s| s.to_lowercase()).collect() + } else { + // Fallback to a default list if PATHEXT is not set + tracing::debug!("Could not find 'PATHEXT' variable, using a default list"); + [ + ".COM", ".EXE", ".BAT", ".CMD", ".VBS", ".VBE", ".JS", ".JSE", ".WSF", ".WSH", ".MSC", + ".CPL", + ] + .iter() + .map(|s| s.to_lowercase()) + .collect() + }; + + // Attempt to strip any known Windows executable extension + extensions_list + .iter() + .find_map(|ext| file_name.strip_suffix(ext)) + .map(|f| f.to_string()) + .unwrap_or(file_name) +} + +/// Strips known Unix executable extensions from a file name. +pub(crate) fn strip_unix_executable_extension(file_name: String) -> String { + let file_name = file_name.to_lowercase(); + + // Define a list of common Unix executable extensions + let extensions_list: Vec<&str> = vec![ + ".sh", ".bash", ".zsh", ".csh", ".tcsh", ".ksh", ".fish", ".py", ".pl", ".rb", ".lua", + ".php", ".tcl", ".awk", ".sed", + ]; + + // Attempt to strip any known Unix executable extension + extensions_list + .iter() + .find_map(|&ext| file_name.strip_suffix(ext)) + .map(|f| f.to_string()) + .unwrap_or(file_name) +} + +/// Strips known executable extensions from a file name based on the target operating system. +/// +/// This function acts as a wrapper that calls either `strip_windows_executable_extension` +/// or `strip_unix_executable_extension` depending on the target OS. +pub fn executable_from_path(path: &Path) -> String { + let file_name = path + .iter() + .last() + .unwrap_or(path.as_os_str()) + .to_string_lossy() + .to_string(); + strip_executable_extension(file_name) +} + +/// Strips known executable extensions from a file name based on the target operating system. +pub fn strip_executable_extension(file_name: String) -> String { + if cfg!(target_family = "windows") { + strip_windows_executable_extension(file_name) + } else { + strip_unix_executable_extension(file_name) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case::python312_linux("python3.12", "python3.12")] + #[case::python3_linux("python3", "python3")] + #[case::python_linux("python", "python")] + #[case::python3121_linux("python3.12.1", "python3.12.1")] + #[case::bash_script("bash.sh", "bash")] + #[case::zsh59("zsh-5.9", "zsh-5.9")] + #[case::python_312config("python3.12-config", "python3.12-config")] + #[case::python3_config("python3-config", "python3-config")] + #[case::x2to3("2to3", "2to3")] + #[case::x2to3312("2to3-3.12", "2to3-3.12")] + fn test_strip_executable_unix(#[case] path: &str, #[case] expected: &str) { + let path = Path::new(path); + let result = strip_unix_executable_extension(path.to_string_lossy().to_string()); + assert_eq!(result, expected); + } + + #[rstest] + #[case::python_windows("python.exe", "python")] + #[case::python3_windows("python3.exe", "python3")] + #[case::python312_windows("python3.12.exe", "python3.12")] + #[case::package010_windows("package0.1.0.bat", "package0.1.0")] + #[case::bash("bash", "bash")] + #[case::zsh59("zsh-5.9", "zsh-5.9")] + #[case::python_312config("python3.12-config", "python3.12-config")] + #[case::python3_config("python3-config", "python3-config")] + #[case::x2to3("2to3", "2to3")] + #[case::x2to3312("2to3-3.12", "2to3-3.12")] + fn test_strip_executable_windows(#[case] path: &str, #[case] expected: &str) { + let path = Path::new(path); + let result = strip_windows_executable_extension(path.to_string_lossy().to_string()); + assert_eq!(result, expected); + } + + #[rstest] + #[case::bash("bash", "bash")] + #[case::zsh59("zsh-5.9", "zsh-5.9")] + #[case::python_312config("python3.12-config", "python3.12-config")] + #[case::python3_config("python3-config", "python3-config")] + #[case::package010("package0.1.0", "package0.1.0")] + #[case::x2to3("2to3", "2to3")] + #[case::x2to3312("2to3-3.12", "2to3-3.12")] + fn test_strip_executable_extension(#[case] path: &str, #[case] expected: &str) { + let result = strip_executable_extension(path.into()); + assert_eq!(result, expected); + // Make sure running it twice doesn't break it + let result = strip_executable_extension(result); + assert_eq!(result, expected); + } +} diff --git a/crates/pixi_utils/src/lib.rs b/crates/pixi_utils/src/lib.rs index c67cde51a..19fd869de 100644 --- a/crates/pixi_utils/src/lib.rs +++ b/crates/pixi_utils/src/lib.rs @@ -3,4 +3,7 @@ pub mod indicatif; mod prefix_guard; pub mod reqwest; +mod executable_utils; +pub use executable_utils::{executable_from_path, strip_executable_extension}; + pub use prefix_guard::{PrefixGuard, WriteGuard}; diff --git a/docs/basic_usage.md b/docs/basic_usage.md index 4d7bfabdf..6051eca3d 100644 --- a/docs/basic_usage.md +++ b/docs/basic_usage.md @@ -85,23 +85,10 @@ pixi global install fish # Install other prefix.dev tools pixi global install rattler-build -# Install a linter you want to use in multiple projects. -pixi global install ruff +# Install a multi package environment +pixi global install python jupyter numpy pandas --environment data-science-env --expose python --expose jupyter ``` -### Using the --no-activation option - -When installing packages globally, you can use the `--no-activation` option to prevent the insertion of environment activation code into the installed executable scripts. This means that when you run the installed executable, it won't modify the `PATH` or `CONDA_PREFIX` environment variables beforehand. - -Example: - -```shell -# Install a package without inserting activation code -pixi global install ruff --no-activation -``` - -This option can be useful in scenarios where you want more control over the environment activation or if you're using the installed executables in contexts where automatic activation might interfere with other processes. - ## Use pixi in GitHub Actions You can use pixi in GitHub Actions to install dependencies and run commands. diff --git a/docs/design_proposals/pixi_global_manifest.md b/docs/design_proposals/pixi_global_manifest.md index bcf3fe142..f194eedbe 100644 --- a/docs/design_proposals/pixi_global_manifest.md +++ b/docs/design_proposals/pixi_global_manifest.md @@ -80,9 +80,8 @@ Update `PACKAGE` if `--package` is given. If not, all packages in environments ` If the update leads to executables being removed, it will offer to remove the mappings. If the user declines the update process will stop. If the update leads to executables being added, it will offer for each binary individually to expose it. -`--assume-yes` will assume yes as answer for every question that would otherwise be asked interactively. ``` -pixi global update [--package PACKAGE] [--assume-yes] ... +pixi global update [--package PACKAGE] ... ``` Updates all packages in all environments. diff --git a/docs/features/global_tools.md b/docs/features/global_tools.md new file mode 100644 index 000000000..11ca5cba5 --- /dev/null +++ b/docs/features/global_tools.md @@ -0,0 +1,180 @@ +# Pixi Global Tool Environment Installation + +With `pixi global`, users can manage globally installed tools in a way that makes them available from any directory. +This means that the pixi environment will be placed in a global location, and the tools will be exposed to the system `PATH`, allowing you to run them from the command line. + +!!! note + The design for global tools is still in progress, and the commands and behavior may change in future releases. + The proposal for the global tools feature can be found [here](../design_proposals/pixi_global_manifest.md). + +## The Global Manifest +Since `v0.33.0` pixi has a new manifest file that will be created in the global directory (default: `$HOME/.pixi/manifests/pixi-global.toml`). +This file will contain the list of environments that are installed globally, their dependencies and exposed binaries. +The manifest can be edited, synced, checked in to a version control system, and shared with others. + +A simple version looks like this: +```toml +[envs.vim] +channels = ["conda-forge"] +dependencies = { vim = "*" } # (1)! +exposed = { vimdiff = "vimdiff", vim = "vim" } # (2)! + +[envs.gh] +channels = ["conda-forge"] +dependencies = { gh = "*" } +exposed = { gh = "gh" } + +[envs.python] +channels = ["conda-forge"] +dependencies = { python = ">=3.10,<3.11" } +exposed = { python310 = "python" } # (3)! +``` + +1. Dependencies are the packages that will be installed in the environment. You can specify the version or use a wildcard. +2. The exposed binaries are the ones that will be available in the system path. `vim` has multiple and all of them are exposed. +3. Here python is exposed as `python310` to avoid conflicts with other python installations. You can give it any name you want. + +### Channels +The channels are the conda channels that will be used to search for the packages. +There is a priority to these, so the first one will have the highest priority, if a package is not found in that channel the next one will be used. +For example, running: +``` +pixi global install --channel conda-forge --channel bioconda snakemake +``` +Results in the following entry in the manifest: +```toml +[envs.snakemake] +channels = ["conda-forge", "bioconda"] +dependencies = { snakemake = "*" } +exposed = { snakemake = "snakemake" } +``` + +More information on channels can be found [here](../advanced/channel_priority.md). + +### Exposed +The exposed binaries are the ones that will be available in the system `PATH`. +This is useful when the package has multiple binaries, but you want to get a select few, or you want to expose it with a different name. +For example, the `python` package has multiple binaries, but you only want to expose the interpreter as `py3`. +Running: +``` +pixi global expose add --environment python py3=python3 +``` +will create the following entry in the manifest: +```toml +[envs.python] +channels = ["conda-forge"] +dependencies = { python = ">=3.10,<3.11" } +exposed = { py3 = "python3" } +``` +Now you can run `py3` to start the python interpreter. +```shell +py3 -c "print('Hello World')" +``` + +There is some added automatic behavior, if you install a package with the same name as the environment, it will be exposed with the same name. +Even if the binary name is only exposed through dependencies of the package +For example, running: +``` +pixi global install ansible +``` +will create the following entry in the manifest: +```toml +[envs.ansible] +channels = ["conda-forge"] +dependencies = { ansible = "*" } +exposed = { ansible = "ansible" } # (1)! +``` + +1. The `ansible` binary is exposed even though it is installed by a dependency of `ansible`, the `ansible-core` package. + +### Dependencies +Dependencies are the **Conda** packages that will be installed into your environment. For example, running: +``` +pixi global install "python<3.12" +``` +creates the following entry in the manifest: +```toml +[envs.vim] +channels = ["conda-forge"] +dependencies = { python = "<3.12" } +# ... +``` +Typically, you'd specify just the tool you're installing, but you can add more packages if needed. +Defining the environment to install into will allow you to add multiple dependencies at once. +For example, running: +```shell +pixi global install --environment my-env git vim python +``` +will create the following entry in the manifest: +```toml +[envs.my-env] +channels = ["conda-forge"] +dependencies = { git = "*", vim = "*", python = "*" } +# ... +``` + +You can `add` a dependency to an existing environment by running: +```shell +pixi global install --environment my-env package-a package-b +``` +This will be added as dependencies to the `my-env` environment but won't auto expose the binaries from the new packages. + +You can `remove` dependencies by running: +```shell +pixi global remove --environment my-env package-a package-b +``` + +### Example: Adding a series of tools at once +Without specifying an environment, you can add multiple tools at once: +```shell +pixi global install pixi-pack rattler-build +``` +This command generates the following entry in the manifest: +```toml +[envs.pixi-pack] +channels = ["conda-forge"] +dependencies= { pixi-pack = "*" } +exposed = { pixi-pack = "pixi-pack" } + +[envs.rattler-build] +channels = ["conda-forge"] +dependencies = { rattler-build = "*" } +exposed = { rattler-build = "rattler-build" } +``` +Creating two separate non-interfering environments, while exposing only the minimum required binaries. + +### Example: Creating a Data Science Sandbox Environment +You can create an environment with multiple tools using the following command: +```shell +pixi global install --environment data-science --expose jupyter=jupyter --expose ipython=ipython jupyter numpy pandas matplotlib ipython +``` +This command generates the following entry in the manifest: +```toml +[envs.data-science] +channels = ["conda-forge"] +dependencies = { jupyter = "*", ipython = "*" } +exposed = { jupyter = "jupyter", ipython = "ipython" } +``` +In this setup, both `jupyter` and `ipython` are exposed from the `data-science` environment, allowing you to run: +```shell +> ipython +# Or +> jupyter lab +``` +These commands will be available globally, making it easy to access your preferred tools without switching environments. + +### Example: Install packages for a different platform +You can install packages for a different platform using the `--platform` flag. +This is useful when you want to install packages for a different platform, such as `osx-64` packages on `osx-arm64`. +For example, running this on `osx-arm64`: +```shell +pixi global install --platform osx-64 python +``` +will create the following entry in the manifest: +```toml +[envs.python] +channels = ["conda-forge"] +platforms = ["osx-64"] +dependencies = { python = "*" } +# ... +``` diff --git a/docs/reference/cli.md b/docs/reference/cli.md index 1c3faf72e..6f3b8906d 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -831,10 +831,17 @@ Checkout the [pixi configuration](./pixi_configuration.md) for more information Edit the configuration file in the default editor. + +##### Arguments + +1. `[EDITOR]`: The editor to use, defaults to `EDITOR` environment variable or `nano` on Unix and `notepad` on Windows + ```shell pixi config edit --system pixi config edit --local pixi config edit -g +pixi config edit --global code +pixi config edit --system vim ``` ### `config list` @@ -916,27 +923,61 @@ pixi config unset repodata-config.disable-zstd --system ## `global` -Global is the main entry point for the part of pixi that executes on the -global(system) level. +Global is the main entry point for the part of pixi that executes on the global(system) level. +All commands in this section are used to manage global installations of packages and environments through the global manifest. +More info on the global manifest can be found [here](../features/global_tools.md). !!! tip Binaries and environments installed globally are stored in `~/.pixi` by default, this can be changed by setting the `PIXI_HOME` environment variable. +### `global add` + +Adds dependencies to a global environment. +Without exposing the binaries of that package to the system by default. + +##### Arguments +1. `[PACKAGE]`: The packages to add, this excepts the matchspec format. (e.g. `python=3.9.*`, `python [version='3.11.0', build_number=1]`) + +##### Options +- `--environment (-e)`: The environment to install the package into. +- `--expose `: A mapping from name to the binary to expose to the system. + +```shell +pixi global add python=3.9.* --environment my-env +pixi global add python=3.9.* --expose py39=python3.9 --environment my-env +pixi global add numpy matplotlib --environment my-env +pixi global add numpy matplotlib --expose np=python3.9 --environment my-env +``` + +### `global edit` +Edit the global manifest file in the default editor. + +Will try to use the `EDITOR` environment variable, if not set it will use `nano` on Unix systems and `notepad` on Windows. + +##### Arguments +1. ``: The editor to use. (optional) +```shell +pixi global edit +pixi global edit code +pixi global edit vim +``` ### `global install` -This command installs package(s) into its own environment and adds the binary to `PATH`, allowing you to access it anywhere on your system without activating the environment. +This command installs package(s) into its own environment and adds the binary to `PATH`. +Allowing you to access it anywhere on your system without activating the environment. ##### Arguments -1.``: The package(s) to install, this can also be a version constraint. +1.`[PACKAGE]`: The package(s) to install, this can also be a version constraint. ##### Options - `--channel (-c)`: specify a channel that the project uses. Defaults to `conda-forge`. (Allowed to be used more than once) - `--platform (-p)`: specify a platform that you want to install the package for. (default: current platform) -- `--no-activation`: Do not insert conda_prefix, path modifications, and activation script into the installed executable script. +- `--environment (-e)`: The environment to install the package into. (default: name of the tool) +- `--expose `: A mapping from name to the binary to expose to the system. (default: name of the tool) ```shell pixi global install ruff @@ -956,8 +997,11 @@ pixi global install python=3.11.0=h10a6764_1_cpython # Install for a specific platform, only useful on osx-arm64 pixi global install --platform osx-64 ruff -# Install without inserting activation code into the executable script -pixi global install ruff --no-activation +# Install into a specific environment name +pixi global install --environment data-science python numpy matplotlib ipython + +# Expose the binary under a different name +pixi global install --expose "py39=python3.9" "python=3.9.*" ``` !!! tip @@ -968,87 +1012,141 @@ pixi global install ruff --no-activation After using global install, you can use the package you installed anywhere on your system. -### `global list` +### `global uninstall` +Uninstalls environments from the global environment. +This will remove the environment and all its dependencies from the global environment. +It will also remove the related binaries from the system. -This command shows the current installed global environments including what binaries come with it. -A global installed package/environment can possibly contain multiple binaries and -they will be listed out in the command output. Here is an example of a few installed packages: +##### Arguments +1. `[ENVIRONMENT]`: The environments to uninstall. -``` -> pixi global list -Global install location: /home/hanabi/.pixi -├── bat 0.24.0 -| └─ exec: bat -├── conda-smithy 3.31.1 -| └─ exec: feedstocks, conda-smithy -├── rattler-build 0.13.0 -| └─ exec: rattler-build -├── ripgrep 14.1.0 -| └─ exec: rg -└── uv 0.1.17 - └─ exec: uv +```shell +pixi global uninstall my-env +pixi global uninstall pixi-pack rattler-build ``` -### `global upgrade` +### `global remove` -This command upgrades a globally installed package (to the latest version by default). +Removes a package from a global environment. ##### Arguments -1. ``: The package to upgrade. +1. `[PACKAGE]`: The packages to remove. ##### Options -- `--channel (-c)`: specify a channel that the project uses. - Defaults to `conda-forge`. Note the channel the package was installed from - will be always used for upgrade. (Allowed to be used more than once) -- `--platform (-p)`: specify a platform that you want to upgrade the package for. (default: current platform) +- `--environment (-e)`: The environment to remove the package from. ```shell -pixi global upgrade ruff -pixi global upgrade --channel conda-forge --channel bioconda trackplot -# Or in a more concise form -pixi global upgrade -c conda-forge -c bioconda trackplot - -# Conda matchspec is supported -# You can specify the version to upgrade to when you don't want the latest version -# or you can even use it to downgrade a globally installed package -pixi global upgrade python=3.10 +pixi global remove -e my-env package1 package2 ``` -### `global upgrade-all` -This command upgrades all globally installed packages to their latest version. +### `global list` + +This command shows the current installed global environments including what binaries come with it. +A global installed package/environment can possibly contain multiple exposed binaries and they will be listed out in the command output. ##### Options +- `--environment (-e)`: The environment to install the package into. (default: name of the tool) -- `--channel (-c)`: specify a channel that the project uses. - Defaults to `conda-forge`. Note the channel the package was installed from - will be always used for upgrade. (Allowed to be used more than once) +We'll only show the dependencies and exposed binaries of the environment if they differ from the environment name. +Here is an example of a few installed packages: -```shell -pixi global upgrade-all -pixi global upgrade-all --channel conda-forge --channel bioconda -# Or in a more concise form -pixi global upgrade-all -c conda-forge -c bioconda trackplot +``` +pixi global list +``` +Results in: +``` +Global environments at /home/user/.pixi: +├── gh: 2.57.0 +├── pixi-pack: 0.1.8 +├── python: 3.11.0 +│ └─ exposes: 2to3, 2to3-3.11, idle3, idle3.11, pydoc, pydoc3, pydoc3.11, python, python3, python3-config, python3.1, python3.11, python3.11-config +├── rattler-build: 0.22.0 +├── ripgrep: 14.1.0 +│ └─ exposes: rg +├── vim: 9.1.0611 +│ └─ exposes: ex, rview, rvim, view, vim, vimdiff, vimtutor, xxd +└── zoxide: 0.9.6 ``` -### `global remove` +Here is an example of list of a single environment: +``` +pixi g list -e pixi-pack +``` +Results in: +``` +The 'pixi-pack' environment has 8 packages: +Package Version Build Size +_libgcc_mutex 0.1 conda_forge 2.5 KiB +_openmp_mutex 4.5 2_gnu 23.1 KiB +ca-certificates 2024.8.30 hbcca054_0 155.3 KiB +libgcc 14.1.0 h77fa898_1 826.5 KiB +libgcc-ng 14.1.0 h69a702a_1 50.9 KiB +libgomp 14.1.0 h77fa898_1 449.4 KiB +openssl 3.3.2 hb9d3cd8_0 2.8 MiB +pixi-pack 0.1.8 hc762bcd_0 4.3 MiB +Package Version Build Size + +Exposes: +pixi-pack +Channels: +conda-forge +Platform: linux-64 +``` + + +### `global sync` +As the global manifest can be manually edited, this command will sync the global manifest with the current state of the global environment. +You can modify the manifest in `$HOME/manifests/pixi_global.toml`. + +```shell +pixi global sync +``` -Removes a package previously installed into a globally accessible location via -`pixi global install` +### `global expose` +Modify the exposed binaries of a global environment. -Use `pixi global info` to find out what the package name is that belongs to the tool you want to remove. +#### `global expose add` +Add exposed binaries from an environment to your global environment. ##### Arguments +1. `[MAPPING]`: The binaries to expose (`python`), or give a map to expose a binary under a different name. (e.g. `py310=python3.10`) +The mapping is mapped as `exposed_name=binary_name`. +Where the exposed name is the one you will be able to use in the terminal, and the binary name is the name of the binary in the environment. -1. ``: The package(s) to remove. +##### Options +- `--environment (-e)`: The environment to expose the binaries from. + +```shell +pixi global expose add python --environment my-env +pixi global expose add py310=python3.10 --environment python +``` + +#### `global expose remove` +Remove exposed binaries from the global environment. + +##### Arguments +1. `[EXPOSED_NAME]`: The binaries to remove from the main global environment. ```shell -pixi global remove pre-commit +pixi global expose remove python +pixi global expose remove py310 python3 +``` + +### `global update` -# multiple packages can be removed at once -pixi global remove pre-commit starship +Update all environments or specify an environment to update to the version. + +##### Arguments + +1. `[ENVIRONMENT]`: The environment(s) to update. + +```shell +pixi global update +pixi global update pixi-pack +pixi global update bat rattler-build ``` ## `project` diff --git a/mkdocs.yml b/mkdocs.yml index c7f4d81da..4b7e3ca4c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -122,6 +122,7 @@ nav: - Multi Environment: features/multi_environment.md - Lockfile: features/lockfile.md - System Requirements: features/system_requirements.md + - Global Tools: features/global_tools.md - Design Proposals: - Pixi Global Manifest: design_proposals/pixi_global_manifest.md - Advanced: diff --git a/pixi.toml b/pixi.toml index f29a213b9..35c3d1804 100644 --- a/pixi.toml +++ b/pixi.toml @@ -41,8 +41,11 @@ test-common-wheels-ci = { cmd = "pytest --numprocesses=auto --verbose tests/whee test-common-wheels-dev = { cmd = "pytest --numprocesses=auto tests/wheel_tests/", depends-on = [ "build", ] } -test-integration-ci = "pytest --numprocesses=auto --verbose tests/integration" -test-integration-dev = { cmd = "pytest --numprocesses=auto tests/integration", depends-on = [ +test-integration-ci = "pytest --numprocesses=auto --durations=10 --verbose tests/integration" +test-integration-dev = { cmd = "pytest --numprocesses=auto --durations=10 tests/integration", depends-on = [ + "build", +] } +test-integration-global = { cmd = "pytest --numprocesses=auto --durations=10 tests/integration/test_global.py", depends-on = [ "build", ] } typecheck-integration = "mypy --strict tests/integration" diff --git a/src/cli/config.rs b/src/cli/config.rs index 5250606d2..7735d14f7 100644 --- a/src/cli/config.rs +++ b/src/cli/config.rs @@ -66,6 +66,10 @@ struct CommonArgs { struct EditArgs { #[clap(flatten)] common: CommonArgs, + + /// The editor to use, defaults to `EDITOR` environment variable or `nano` on Unix and `notepad` on Windows + #[arg(env = "EDITOR")] + pub editor: Option, } #[derive(Parser, Debug, Clone)] @@ -132,22 +136,29 @@ pub struct Args { pub async fn execute(args: Args) -> miette::Result<()> { match args.subcommand { Subcommand::Edit(args) => { - let editor = std::env::var("EDITOR").unwrap_or_else(|_| { - #[cfg(not(target_os = "windows"))] - { - "nano".to_string() - } - #[cfg(target_os = "windows")] - { + let config_path = determine_config_write_path(&args.common)?; + + let editor = args.editor.unwrap_or_else(|| { + if cfg!(windows) { "notepad".to_string() + } else { + "nano".to_string() } }); - let config_path = determine_config_write_path(&args.common)?; - let mut child = std::process::Command::new(editor.as_str()) - .arg(config_path) - .spawn() - .into_diagnostic()?; + let mut child = if cfg!(windows) { + std::process::Command::new("cmd") + .arg("/C") + .arg(editor.as_str()) + .arg(&config_path) + .spawn() + .into_diagnostic()? + } else { + std::process::Command::new(editor.as_str()) + .arg(&config_path) + .spawn() + .into_diagnostic()? + }; child.wait().into_diagnostic()?; } Subcommand::List(args) => { diff --git a/src/cli/global/add.rs b/src/cli/global/add.rs new file mode 100644 index 000000000..d3be12807 --- /dev/null +++ b/src/cli/global/add.rs @@ -0,0 +1,114 @@ +use crate::cli::global::revert_environment_after_error; +use crate::cli::has_specs::HasSpecs; +use crate::global::{EnvironmentName, Mapping, Project, StateChanges}; +use clap::Parser; +use itertools::Itertools; +use miette::Context; +use pixi_config::{Config, ConfigCli}; +use rattler_conda_types::MatchSpec; + +/// Adds dependencies to an environment +/// +/// Example: +/// - pixi global add --environment python numpy +/// - pixi global add --environment my_env pytest pytest-cov --expose pytest=pytest +#[derive(Parser, Debug, Clone)] +#[clap(arg_required_else_help = true, verbatim_doc_comment)] +pub struct Args { + /// Specifies the packages that are to be added to the environment. + #[arg(num_args = 1.., required = true)] + packages: Vec, + + /// Specifies the environment that the dependencies need to be added to. + #[clap(short, long, required = true)] + environment: EnvironmentName, + + /// Add one or more mapping which describe which executables are exposed. + /// The syntax is `exposed_name=executable_name`, so for example `python3.10=python`. + /// Alternatively, you can input only an executable_name and `executable_name=executable_name` is assumed. + #[arg(long)] + expose: Vec, + + #[clap(flatten)] + config: ConfigCli, +} + +impl HasSpecs for Args { + fn packages(&self) -> Vec<&str> { + self.packages.iter().map(AsRef::as_ref).collect() + } +} + +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + if project_original.environment(&args.environment).is_none() { + miette::bail!("Environment {} doesn't exist. You can create a new environment with `pixi global install`.", &args.environment); + } + + async fn apply_changes( + env_name: &EnvironmentName, + specs: &[MatchSpec], + expose: &[Mapping], + project: &mut Project, + ) -> miette::Result { + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + + // Add specs to the manifest + for spec in specs { + project.manifest.add_dependency( + env_name, + spec, + project.clone().config().global_channel_config(), + )?; + } + + // Add expose mappings to the manifest + for mapping in expose { + project.manifest.add_exposed_mapping(env_name, mapping)?; + } + + // Sync environment + state_changes |= project.sync_environment(env_name).await?; + + // Figure out added packages and their corresponding versions + state_changes |= project.added_packages(specs, env_name).await?; + + project.manifest.save().await?; + + Ok(state_changes) + } + + let mut project_modified = project_original.clone(); + let specs = args + .specs()? + .into_iter() + .map(|(_, specs)| specs) + .collect_vec(); + + match apply_changes( + &args.environment, + specs.as_slice(), + args.expose.as_slice(), + &mut project_modified, + ) + .await + { + Ok(ref mut state_changes) => { + state_changes.report(); + Ok(()) + } + Err(err) => { + revert_environment_after_error(&args.environment, &project_original) + .await + .wrap_err(format!( + "Couldn't add {:?}. Reverting also failed.", + args.packages + ))?; + Err(err) + } + } +} diff --git a/src/cli/global/common.rs b/src/cli/global/common.rs deleted file mode 100644 index 616cfa18c..000000000 --- a/src/cli/global/common.rs +++ /dev/null @@ -1,145 +0,0 @@ -use std::path::PathBuf; - -use miette::IntoDiagnostic; -use rattler_conda_types::{Channel, ChannelConfig, PackageName, PrefixRecord}; - -use crate::{prefix::Prefix, repodata}; -use pixi_config::home_path; - -/// Global binaries directory, default to `$HOME/.pixi/bin` -pub struct BinDir(pub PathBuf); - -impl BinDir { - /// Create the Binary Executable directory - pub async fn create() -> miette::Result { - let bin_dir = bin_dir().ok_or(miette::miette!( - "could not determine global binary executable directory" - ))?; - tokio::fs::create_dir_all(&bin_dir) - .await - .into_diagnostic()?; - Ok(Self(bin_dir)) - } - - /// Get the Binary Executable directory, erroring if it doesn't already - /// exist. - pub async fn from_existing() -> miette::Result { - let bin_dir = bin_dir().ok_or(miette::miette!( - "could not find global binary executable directory" - ))?; - if tokio::fs::try_exists(&bin_dir).await.into_diagnostic()? { - Ok(Self(bin_dir)) - } else { - Err(miette::miette!( - "binary executable directory does not exist" - )) - } - } -} - -/// Global binary environments directory, default to `$HOME/.pixi/envs` -pub struct BinEnvDir(pub PathBuf); - -impl BinEnvDir { - /// Construct the path to the env directory for the binary package - /// `package_name`. - fn package_bin_env_dir(package_name: &PackageName) -> miette::Result { - Ok(bin_env_dir() - .ok_or(miette::miette!( - "could not find global binary environment directory" - ))? - .join(package_name.as_normalized())) - } - - /// Get the Binary Environment directory, erroring if it doesn't already - /// exist. - pub async fn from_existing(package_name: &PackageName) -> miette::Result { - let bin_env_dir = Self::package_bin_env_dir(package_name)?; - if tokio::fs::try_exists(&bin_env_dir) - .await - .into_diagnostic()? - { - Ok(Self(bin_env_dir)) - } else { - Err(miette::miette!( - "could not find environment for package {}", - package_name.as_source() - )) - } - } - - /// Create the Binary Environment directory - pub async fn create(package_name: &PackageName) -> miette::Result { - let bin_env_dir = Self::package_bin_env_dir(package_name)?; - tokio::fs::create_dir_all(&bin_env_dir) - .await - .into_diagnostic()?; - Ok(Self(bin_env_dir)) - } -} - -/// Global binaries directory, default to `$HOME/.pixi/bin` -/// -/// # Returns -/// -/// The global binaries directory -pub(crate) fn bin_dir() -> Option { - home_path().map(|path| path.join("bin")) -} - -/// Global binary environments directory, default to `$HOME/.pixi/envs` -/// -/// # Returns -/// -/// The global binary environments directory -pub(crate) fn bin_env_dir() -> Option { - home_path().map(|path| path.join("envs")) -} - -/// Get the friendly channel name of a [`PrefixRecord`] -/// -/// # Returns -/// -/// The friendly channel name of the given prefix record -pub(super) fn channel_name_from_prefix( - prefix_package: &PrefixRecord, - channel_config: &ChannelConfig, -) -> String { - Channel::from_str(&prefix_package.repodata_record.channel, channel_config) - .map(|ch| repodata::friendly_channel_name(&ch)) - .unwrap_or_else(|_| prefix_package.repodata_record.channel.clone()) -} - -/// Find the globally installed package with the given [`PackageName`] -/// -/// # Returns -/// -/// The PrefixRecord of the installed package -pub(super) async fn find_installed_package( - package_name: &PackageName, -) -> miette::Result { - let BinEnvDir(bin_prefix) = BinEnvDir::from_existing(package_name).await.or_else(|_| { - miette::bail!( - "Package {} is not globally installed", - package_name.as_source() - ) - })?; - let prefix = Prefix::new(bin_prefix); - find_designated_package(&prefix, package_name).await -} - -/// Find the designated package in the given [`Prefix`] -/// -/// # Returns -/// -/// The PrefixRecord of the designated package -pub async fn find_designated_package( - prefix: &Prefix, - package_name: &PackageName, -) -> miette::Result { - let prefix_records = prefix.find_installed_packages(None).await?; - prefix_records - .into_iter() - .find(|r| r.repodata_record.package_record.name == *package_name) - .ok_or_else(|| miette::miette!("could not find {} in prefix", package_name.as_source())) -} diff --git a/src/cli/global/edit.rs b/src/cli/global/edit.rs new file mode 100644 index 000000000..ec6250fa2 --- /dev/null +++ b/src/cli/global/edit.rs @@ -0,0 +1,42 @@ +use crate::global::Project; +use clap::Parser; +use miette::IntoDiagnostic; + +/// Edit the global manifest file +/// +/// Opens your editor to edit the global manifest file. +#[derive(Parser, Debug)] +#[clap(verbatim_doc_comment)] +pub struct Args { + /// The editor to use, defaults to `EDITOR` environment variable or `nano` on Unix and `notepad` on Windows + #[arg(env = "EDITOR")] + pub editor: Option, +} + +pub async fn execute(args: Args) -> miette::Result<()> { + let manifest_path = Project::default_manifest_path()?; + + let editor = args.editor.unwrap_or_else(|| { + if cfg!(windows) { + "notepad".to_string() + } else { + "nano".to_string() + } + }); + + let mut child = if cfg!(windows) { + std::process::Command::new("cmd") + .arg("/C") + .arg(editor.as_str()) + .arg(&manifest_path) + .spawn() + .into_diagnostic()? + } else { + std::process::Command::new(editor.as_str()) + .arg(&manifest_path) + .spawn() + .into_diagnostic()? + }; + child.wait().into_diagnostic()?; + Ok(()) +} diff --git a/src/cli/global/expose.rs b/src/cli/global/expose.rs new file mode 100644 index 000000000..22fb98b65 --- /dev/null +++ b/src/cli/global/expose.rs @@ -0,0 +1,168 @@ +use clap::Parser; +use itertools::Itertools; +use miette::Context; +use pixi_config::{Config, ConfigCli}; + +use crate::{ + cli::global::revert_environment_after_error, + global::{self, EnvironmentName, ExposedName, Mapping, StateChanges}, +}; + +/// Add exposed binaries from an environment to your global environment +/// +/// Example: +/// - pixi global expose add python310=python3.10 python3=python3 --environment myenv +/// - pixi global add --environment my_env pytest pytest-cov --expose pytest=pytest +#[derive(Parser, Debug)] +#[clap(arg_required_else_help = true, verbatim_doc_comment)] +pub struct AddArgs { + /// Add one or more mapping which describe which executables are exposed. + /// The syntax is `exposed_name=executable_name`, so for example `python3.10=python`. + /// Alternatively, you can input only an executable_name and `executable_name=executable_name` is assumed. + #[arg(num_args = 1..)] + mappings: Vec, + + /// The environment to which the binaries should be exposed + #[clap(short, long)] + environment: EnvironmentName, + + #[clap(flatten)] + config: ConfigCli, +} + +/// Remove exposed binaries from the global environment +/// +/// `pixi global expose remove python310 python3 --environment myenv` +/// will remove the exposed names `python310` and `python3` from the environment `myenv` +#[derive(Parser, Debug)] +pub struct RemoveArgs { + /// The exposed names that should be removed + #[arg(num_args = 1..)] + exposed_names: Vec, + + #[clap(flatten)] + config: ConfigCli, +} + +/// Interact with the exposure of binaries in the global environment +/// +/// `pixi global expose add python310=python3.10 --environment myenv` +/// will expose the `python3.10` executable as `python310` from the environment `myenv` +/// +/// `pixi global expose remove python310 --environment myenv` +/// will remove the exposed name `python310` from the environment `myenv` +#[derive(Parser, Debug)] +#[clap(group(clap::ArgGroup::new("command")))] +pub enum SubCommand { + #[clap(name = "add")] + Add(AddArgs), + #[clap(name = "remove")] + Remove(RemoveArgs), +} + +/// Expose some binaries +pub async fn execute(args: SubCommand) -> miette::Result<()> { + match args { + SubCommand::Add(args) => add(args).await?, + SubCommand::Remove(args) => remove(args).await?, + } + Ok(()) +} + +pub async fn add(args: AddArgs) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + async fn apply_changes( + args: &AddArgs, + project: &mut global::Project, + ) -> Result { + let env_name = &args.environment; + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + for mapping in &args.mappings { + project.manifest.add_exposed_mapping(env_name, mapping)?; + } + state_changes |= project.sync_environment(env_name).await?; + project.manifest.save().await?; + Ok(state_changes) + } + + let mut project_modified = project_original.clone(); + match apply_changes(&args, &mut project_modified).await { + Ok(mut state_changes) => { + project_modified.manifest.save().await?; + state_changes.report(); + Ok(()) + } + Err(err) => { + revert_environment_after_error(&args.environment, &project_original) + .await + .wrap_err("Couldn't add exposed mappings. Reverting also failed.")?; + Err(err) + } + } +} + +pub async fn remove(args: RemoveArgs) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + async fn apply_changes( + exposed_name: &ExposedName, + env_name: &EnvironmentName, + project: &mut global::Project, + ) -> Result { + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + project + .manifest + .remove_exposed_name(env_name, exposed_name)?; + state_changes |= project.sync_environment(env_name).await?; + project.manifest.save().await?; + Ok(state_changes) + } + + let exposed_mappings = args + .exposed_names + .iter() + .map(|exposed_name| { + project_original + .manifest + .match_exposed_name_to_environment(exposed_name) + .map(|env_name| (exposed_name.clone(), env_name)) + }) + .collect_vec(); + + let mut last_updated_project = project_original; + let mut state_changes = StateChanges::default(); + for mapping in exposed_mappings { + let (exposed_name, env_name) = mapping?; + let mut project = last_updated_project.clone(); + match apply_changes(&exposed_name, &env_name, &mut project) + .await + .wrap_err_with(|| format!("Couldn't remove exposed name {exposed_name}")) + { + Ok(sc) => { + state_changes |= sc; + } + Err(err) => { + state_changes.report(); + revert_environment_after_error(&env_name, &last_updated_project) + .await + .wrap_err_with(|| { + format!( + "Couldn't remove exposed name {exposed_name}. Reverting also failed." + ) + })?; + + return Err(err); + } + } + last_updated_project = project; + } + state_changes.report(); + Ok(()) +} diff --git a/src/cli/global/install.rs b/src/cli/global/install.rs index d1508592d..fe3c2ed16 100644 --- a/src/cli/global/install.rs +++ b/src/cli/global/install.rs @@ -1,58 +1,61 @@ -use std::{ - collections::HashMap, - ffi::OsStr, - path::{Path, PathBuf}, -}; +use std::str::FromStr; use clap::Parser; +use fancy_display::FancyDisplay; use indexmap::IndexMap; use itertools::Itertools; use miette::{Context, IntoDiagnostic}; -use pixi_config::{self, Config, ConfigCli}; -use pixi_progress::{await_in_progress, global_multi_progress, wrap_in_progress}; -use pixi_utils::reqwest::build_reqwest_clients; -use rattler::{ - install::{DefaultProgressFormatter, IndicatifReporter, Installer}, - package_cache::PackageCache, -}; -use rattler_conda_types::{ - GenericVirtualPackage, MatchSpec, PackageName, Platform, PrefixRecord, RepoDataRecord, -}; -use rattler_shell::{ - activation::{ActivationVariables, Activator, PathModificationBehavior}, - shell::{Shell, ShellEnum}, -}; -use rattler_solve::{resolvo::Solver, SolverImpl, SolverTask}; -use rattler_virtual_packages::{VirtualPackage, VirtualPackageOverrides}; -use reqwest_middleware::ClientWithMiddleware; +use rattler_conda_types::{MatchSpec, NamedChannelOrUrl, PackageName, Platform}; -use super::common::{channel_name_from_prefix, find_designated_package, BinDir, BinEnvDir}; use crate::{ - cli::{cli_config::ChannelsConfig, has_specs::HasSpecs}, + cli::{global::revert_environment_after_error, has_specs::HasSpecs}, + global::{self, EnvironmentName, ExposedName, Mapping, Project, StateChange, StateChanges}, prefix::Prefix, - rlimit::try_increase_rlimit_to_sensible, }; +use pixi_config::{self, Config, ConfigCli}; -/// Installs the defined package in a global accessible location. -#[derive(Parser, Debug)] -#[clap(arg_required_else_help = true)] +/// Installs the defined packages in a globally accessible location and exposes their command line applications. +/// +/// Example: +/// - pixi global install starship nushell ripgrep bat +/// - pixi global install --environment science jupyter polars +/// - pixi global install --expose python3.8=python python=3.8 +#[derive(Parser, Debug, Clone)] +#[clap(arg_required_else_help = true, verbatim_doc_comment)] pub struct Args { /// Specifies the packages that are to be installed. - #[arg(num_args = 1..)] + #[arg(num_args = 1.., required = true)] packages: Vec, - #[clap(flatten)] - channels: ChannelsConfig, - - #[clap(short, long, default_value_t = Platform::current())] - platform: Platform, + /// The channels to consider as a name or a url. + /// Multiple channels can be specified by using this field multiple times. + /// + /// When specifying a channel, it is common that the selected channel also + /// depends on the `conda-forge` channel. + /// + /// By default, if no channel is provided, `conda-forge` is used. + #[clap(long = "channel", short = 'c', value_name = "CHANNEL")] + channels: Vec, + + #[clap(short, long)] + platform: Option, + + /// Ensures that all packages will be installed in the same environment + #[clap(short, long)] + environment: Option, + + /// Add one or more mapping which describe which executables are exposed. + /// The syntax is `exposed_name=executable_name`, so for example `python3.10=python`. + /// Alternatively, you can input only an executable_name and `executable_name=executable_name` is assumed. + #[arg(long)] + expose: Vec, #[clap(flatten)] config: ConfigCli, - /// Do not insert `CONDA_PREFIX`, `PATH` modifications into the installed executable script. - #[clap(long)] - no_activation: bool, + /// Specifies that the packages should be reinstalled even if they are already installed. + #[arg(action, long)] + force_reinstall: bool, } impl HasSpecs for Args { @@ -61,466 +64,181 @@ impl HasSpecs for Args { } } -/// Create the environment activation script -fn create_activation_script(prefix: &Prefix, shell: ShellEnum) -> miette::Result { - let activator = - Activator::from_path(prefix.root(), shell, Platform::current()).into_diagnostic()?; - let result = activator - .activation(ActivationVariables { - conda_prefix: None, - path: None, - path_modification_behavior: PathModificationBehavior::Prepend, - }) - .into_diagnostic()?; - - // Add a shebang on unix based platforms - let script = if cfg!(unix) { - format!("#!/bin/sh\n{}", result.script.contents().into_diagnostic()?) - } else { - result.script.contents().into_diagnostic()? - }; - - Ok(script) -} - -fn is_executable(prefix: &Prefix, relative_path: &Path) -> bool { - // Check if the file is in a known executable directory. - let binary_folders = if cfg!(windows) { - &([ - "", - "Library/mingw-w64/bin/", - "Library/usr/bin/", - "Library/bin/", - "Scripts/", - "bin/", - ][..]) - } else { - &(["bin"][..]) - }; - - let parent_folder = match relative_path.parent() { - Some(dir) => dir, - None => return false, - }; - - if !binary_folders - .iter() - .any(|bin_path| Path::new(bin_path) == parent_folder) - { - return false; - } - - // Check if the file is executable - let absolute_path = prefix.root().join(relative_path); - is_executable::is_executable(absolute_path) -} - -/// Find the executable scripts within the specified package installed in this -/// conda prefix. -fn find_executables<'a>(prefix: &Prefix, prefix_package: &'a PrefixRecord) -> Vec<&'a Path> { - prefix_package - .files - .iter() - .filter(|relative_path| is_executable(prefix, relative_path)) - .map(|buf| buf.as_ref()) - .collect() -} - -/// Mapping from an executable in a package environment to its global binary -/// script location. -#[derive(Debug)] -pub struct BinScriptMapping<'a> { - pub original_executable: &'a Path, - pub global_binary_path: PathBuf, -} - -/// For each executable provided, map it to the installation path for its global -/// binary script. -async fn map_executables_to_global_bin_scripts<'a>( - package_executables: &[&'a Path], - bin_dir: &BinDir, -) -> miette::Result>> { - #[cfg(target_family = "windows")] - let extensions_list: Vec = if let Ok(pathext) = std::env::var("PATHEXT") { - pathext.split(';').map(|s| s.to_lowercase()).collect() - } else { - tracing::debug!("Could not find 'PATHEXT' variable, using a default list"); - [ - ".COM", ".EXE", ".BAT", ".CMD", ".VBS", ".VBE", ".JS", ".JSE", ".WSF", ".WSH", ".MSC", - ".CPL", - ] - .iter() - .map(|&s| s.to_lowercase()) - .collect() - }; - - #[cfg(target_family = "unix")] - // TODO: Find if there are more relevant cases, these cases are generated by our big friend - // GPT-4 - let extensions_list: Vec = vec![ - ".sh", ".bash", ".zsh", ".csh", ".tcsh", ".ksh", ".fish", ".py", ".pl", ".rb", ".lua", - ".php", ".tcl", ".awk", ".sed", - ] - .iter() - .map(|&s| s.to_owned()) - .collect(); - - let BinDir(bin_dir) = bin_dir; - let mut mappings = vec![]; - - for exec in package_executables.iter() { - // Remove the extension of a file if it is in the list of known extensions. - let Some(file_name) = exec - .file_name() - .and_then(OsStr::to_str) - .map(str::to_lowercase) - else { - continue; - }; - let file_name = extensions_list +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + let env_names = match &args.environment { + Some(env_name) => Vec::from([env_name.clone()]), + None => args + .specs()? .iter() - .find_map(|ext| file_name.strip_suffix(ext)) - .unwrap_or(file_name.as_str()); + .map(|(package_name, _)| package_name.as_normalized().parse().into_diagnostic()) + .collect::>>()?, + }; - let mut executable_script_path = bin_dir.join(file_name); + let multiple_envs = env_names.len() > 1; - if cfg!(windows) { - executable_script_path.set_extension("bat"); - }; - mappings.push(BinScriptMapping { - original_executable: exec, - global_binary_path: executable_script_path, - }); + if !args.expose.is_empty() && env_names.len() != 1 { + miette::bail!("Can't add exposed mappings for more than one environment"); } - Ok(mappings) -} - -/// Find all executable scripts in a package and map them to their global -/// install paths. -/// -/// (Convenience wrapper around `find_executables` and -/// `map_executables_to_global_bin_scripts` which are generally used together.) -pub(super) async fn find_and_map_executable_scripts<'a>( - prefix: &Prefix, - prefix_package: &'a PrefixRecord, - bin_dir: &BinDir, -) -> miette::Result>> { - let executables = find_executables(prefix, prefix_package); - map_executables_to_global_bin_scripts(&executables, bin_dir).await -} -/// Create the executable scripts by modifying the activation script -/// to activate the environment and run the executable. -pub(super) async fn create_executable_scripts( - mapped_executables: &[BinScriptMapping<'_>], - prefix: &Prefix, - shell: &ShellEnum, - activation_script: String, - no_activation: bool, -) -> miette::Result<()> { - for BinScriptMapping { - original_executable: exec, - global_binary_path: executable_script_path, - } in mapped_executables - { - let mut script = if no_activation { - if cfg!(unix) { - "#!/bin/sh\n".to_string() - } else { - String::new() - } + let mut state_changes = StateChanges::default(); + let mut last_updated_project = project_original; + let specs = args.specs()?; + for env_name in &env_names { + let specs = if multiple_envs { + specs + .clone() + .into_iter() + .filter(|(package_name, _)| env_name.as_str() == package_name.as_source()) + .collect() } else { - activation_script.clone() + specs.clone() }; - - shell - .run_command( - &mut script, - [ - format!("\"{}\"", prefix.root().join(exec).to_string_lossy()).as_str(), - get_catch_all_arg(shell), - ], - ) - .expect("should never fail"); - - if matches!(shell, ShellEnum::CmdExe(_)) { - // wrap the script contents in `@echo off` and `setlocal` to prevent echoing the - // script and to prevent leaking environment variables into the - // parent shell (e.g. PATH would grow longer and longer) - script = format!("@echo off\nsetlocal\n{}\nendlocal", script); - } - - tokio::fs::write(&executable_script_path, script) + let mut project = last_updated_project.clone(); + match setup_environment(env_name, &args, specs, &mut project) .await - .into_diagnostic()?; - - #[cfg(unix)] + .wrap_err_with(|| format!("Couldn't install {}", env_name.fancy_display())) { - use std::os::unix::fs::PermissionsExt; - std::fs::set_permissions( - executable_script_path, - std::fs::Permissions::from_mode(0o755), - ) - .into_diagnostic()?; - } - } - Ok(()) -} - -/// Warn user on dangerous package installations, interactive yes no prompt -pub(crate) fn prompt_user_to_continue( - packages: &IndexMap, -) -> miette::Result { - let dangerous_packages = HashMap::from([ - ("pixi", "Installing `pixi` globally doesn't work as expected.\nUse `pixi self-update` to update pixi and `pixi self-update --version x.y.z` for a specific version."), - ("pip", "Installing `pip` with `pixi global` won't make pip-installed packages globally available.\nInstead, use a pixi project and add PyPI packages with `pixi add --pypi`, which is recommended. Alternatively, `pixi add pip` and use it within the project.") - ]); - - // Check if any of the packages are dangerous, and prompt the user to ask if - // they want to continue, including the advice. - for (name, _spec) in packages { - if let Some(advice) = dangerous_packages.get(&name.as_normalized()) { - let prompt = format!( - "{}\nDo you want to continue?", - console::style(advice).yellow() - ); - if !dialoguer::Confirm::new() - .with_prompt(prompt) - .default(false) - .show_default(true) - .interact() - .into_diagnostic()? - { - return Ok(false); + Ok(sc) => { + state_changes |= sc; + } + Err(err) => { + state_changes.report(); + revert_environment_after_error(env_name, &last_updated_project) + .await + .wrap_err("Couldn't install packages. Reverting also failed.")?; + return Err(err); } } + last_updated_project = project; } + state_changes.report(); - Ok(true) + Ok(()) } -/// Install a global command -pub async fn execute(args: Args) -> miette::Result<()> { - // Figure out what channels we are using - let config = Config::with_cli_config(&args.config); - let channels = args.channels.resolve_from_config(&config)?; +async fn setup_environment( + env_name: &EnvironmentName, + args: &Args, + specs: IndexMap, + project: &mut Project, +) -> miette::Result { + let mut state_changes = StateChanges::new_with_env(env_name.clone()); - let specs = args.specs()?; + let channels = if args.channels.is_empty() { + project.config().default_channels() + } else { + args.channels.clone() + }; - // Warn user on dangerous package installations, interactive yes no prompt - if !prompt_user_to_continue(&specs)? { - return Ok(()); + // Modify the project to include the new environment + if !project.manifest.parsed.envs.contains_key(env_name) { + project.manifest.add_environment(env_name, Some(channels))?; + state_changes.insert_change(env_name, StateChange::AddedEnvironment); } - // Fetch the repodata - let (_, auth_client) = build_reqwest_clients(Some(&config)); - - let gateway = config.gateway(auth_client.clone()); - - let repodata = gateway - .query( - channels, - [args.platform, Platform::NoArch], - specs.values().cloned().collect_vec(), - ) - .recursive(true) - .await - .into_diagnostic()?; - - // Determine virtual packages of the current platform - let virtual_packages = VirtualPackage::detect(&VirtualPackageOverrides::from_env()) - .into_diagnostic() - .context("failed to determine virtual packages")? - .iter() - .cloned() - .map(GenericVirtualPackage::from) - .collect(); - - // Solve the environment - let solver_specs = specs.clone(); - let solved_records = wrap_in_progress("solving environment", move || { - Solver.solve(SolverTask { - specs: solver_specs.values().cloned().collect_vec(), - virtual_packages, - ..SolverTask::from_iter(&repodata) - }) - }) - .into_diagnostic() - .context("failed to solve environment")?; + if let Some(platform) = args.platform { + project.manifest.set_platform(env_name, platform)?; + } - // Install the package(s) - let mut executables = vec![]; - for (package_name, _) in specs { - let (prefix_package, scripts, _) = globally_install_package( - &package_name, - solved_records.clone(), - auth_client.clone(), - args.platform, - args.no_activation, - ) - .await?; - let channel_name = - channel_name_from_prefix(&prefix_package, config.global_channel_config()); - let record = &prefix_package.repodata_record.package_record; + // Add the dependencies to the environment + for (_package_name, spec) in &specs { + project.manifest.add_dependency( + env_name, + spec, + project.clone().config().global_channel_config(), + )?; + } - // Warn if no executables were created for the package - if scripts.is_empty() { - eprintln!( - "{}No executable entrypoint found in package {}, are you sure it exists?", - console::style(console::Emoji("⚠️", "")).yellow().bold(), - console::style(record.name.as_source()).bold() - ); + if !args.expose.is_empty() { + project.manifest.remove_all_exposed_mappings(env_name)?; + // Only add the exposed mappings that were requested + for mapping in &args.expose { + project.manifest.add_exposed_mapping(env_name, mapping)?; } - - eprintln!( - "{}Installed package {} {} {} from {}", - console::style(console::Emoji("✔ ", "")).green(), - console::style(record.name.as_source()).bold(), - console::style(record.version.version()).bold(), - console::style(record.build.as_str()).bold(), - channel_name, - ); - - executables.extend(scripts); } - if !executables.is_empty() { - print_executables_available(executables).await?; + if !args.force_reinstall && project.environment_in_sync(env_name).await? { + return Ok(StateChanges::new_with_env(env_name.clone())); } - Ok(()) -} + // Installing the environment to be able to find the bin paths later + project.install_environment(env_name).await?; + + // Cleanup removed executables + state_changes |= project.remove_broken_expose_names(env_name).await?; + + if args.expose.is_empty() { + // Add the expose binaries for all the packages that were requested to the manifest + for (package_name, _spec) in &specs { + let prefix = project.environment_prefix(env_name).await?; + let prefix_package = prefix.find_designated_package(package_name).await?; + let package_executables = prefix.find_executables(&[prefix_package]); + for (executable_name, _) in &package_executables { + let mapping = Mapping::new( + ExposedName::from_str(executable_name)?, + executable_name.clone(), + ); + project.manifest.add_exposed_mapping(env_name, &mapping)?; + } + // If no executables were found, automatically expose the package name itself from the other packages. + // This is useful for packages like `ansible` and `jupyter` which don't ship executables their own executables. + if !package_executables + .iter() + .any(|(name, _)| name.as_str() == package_name.as_normalized()) + { + if let Some((mapping, source_package_name)) = + find_binary_by_name(&prefix, package_name).await? + { + project.manifest.add_exposed_mapping(env_name, &mapping)?; + tracing::warn!( + "Automatically exposed `{}` from `{}`", + console::style(mapping.exposed_name()).yellow(), + console::style(source_package_name.as_normalized()).green() + ); + } + } + } + } -async fn print_executables_available(executables: Vec) -> miette::Result<()> { - let BinDir(bin_dir) = BinDir::from_existing().await?; - let whitespace = console::Emoji(" ", "").to_string(); - let executable = executables - .into_iter() - .map(|path| { - path.strip_prefix(&bin_dir) - .expect("script paths were constructed by joining onto BinDir") - .to_string_lossy() - .to_string() - }) - .join(&format!("\n{whitespace} - ")); + // Figure out added packages and their corresponding versions + let specs = specs.values().cloned().collect_vec(); + state_changes |= project.added_packages(specs.as_slice(), env_name).await?; - if is_bin_folder_on_path().await { - eprintln!( - "{whitespace}These executables are now globally available:\n{whitespace} - {executable}", - ) - } else { - eprintln!("{whitespace}These executables have been added to {}\n{whitespace} - {executable}\n\n{} To use them, make sure to add {} to your PATH", - console::style(&bin_dir.display()).bold(), - console::style("!").yellow().bold(), - console::style(&bin_dir.display()).bold() - ) - } + // Expose executables of the new environment + state_changes |= project + .expose_executables_from_environment(env_name) + .await?; - Ok(()) + project.manifest.save().await?; + Ok(state_changes) } -/// Install given package globally, with all its dependencies -pub(super) async fn globally_install_package( +/// Finds the package name in the prefix and automatically exposes it if an executable is found. +/// This is useful for packages like `ansible` and `jupyter` which don't ship executables their own executables. +/// This function will return the mapping and the package name of the package in which the binary was found. +async fn find_binary_by_name( + prefix: &Prefix, package_name: &PackageName, - records: Vec, - authenticated_client: ClientWithMiddleware, - platform: Platform, - no_activation: bool, -) -> miette::Result<(PrefixRecord, Vec, bool)> { - try_increase_rlimit_to_sensible(); - - // Create the binary environment prefix where we install or update the package - let BinEnvDir(bin_prefix) = BinEnvDir::create(package_name).await?; - let prefix = Prefix::new(bin_prefix); - - // Install the environment - let package_cache = PackageCache::new( - pixi_config::get_cache_dir()?.join(pixi_consts::consts::CONDA_PACKAGE_CACHE_DIR), - ); - - let result = await_in_progress("creating virtual environment", |pb| { - Installer::new() - .with_download_client(authenticated_client) - .with_io_concurrency_limit(100) - .with_execute_link_scripts(false) - .with_package_cache(package_cache) - .with_target_platform(platform) - .with_reporter( - IndicatifReporter::builder() - .with_multi_progress(global_multi_progress()) - .with_placement(rattler::install::Placement::After(pb)) - .with_formatter(DefaultProgressFormatter::default().with_prefix(" ")) - .clear_when_done(true) - .finish(), - ) - .install(prefix.root(), records) - }) - .await - .into_diagnostic()?; - - // Find the installed package in the environment - let prefix_package = find_designated_package(&prefix, package_name).await?; - - // Determine the shell to use for the invocation script - let shell: ShellEnum = if cfg!(windows) { - rattler_shell::shell::CmdExe.into() - } else { - rattler_shell::shell::Bash.into() - }; - - // Construct the reusable activation script for the shell and generate an - // invocation script for each executable added by the package to the - // environment. - let activation_script = create_activation_script(&prefix, shell.clone())?; - - let bin_dir = BinDir::create().await?; - let script_mapping = - find_and_map_executable_scripts(&prefix, &prefix_package, &bin_dir).await?; - create_executable_scripts( - &script_mapping, - &prefix, - &shell, - activation_script, - no_activation, - ) - .await?; - - let scripts: Vec<_> = script_mapping - .into_iter() - .map( - |BinScriptMapping { - global_binary_path: path, - .. - }| path, - ) - .collect(); +) -> miette::Result> { + let installed_packages = prefix.find_installed_packages(None).await?; + for package in &installed_packages { + let executables = prefix.find_executables(&[package.clone()]); - Ok(( - prefix_package, - scripts, - result.transaction.operations.is_empty(), - )) -} - -/// Returns the string to add for all arguments passed to the script -fn get_catch_all_arg(shell: &ShellEnum) -> &str { - match shell { - ShellEnum::CmdExe(_) => "%*", - ShellEnum::PowerShell(_) => "@args", - _ => "\"$@\"", + // Check if any of the executables match the package name + if let Some(executable) = executables + .iter() + .find(|(name, _)| name.as_str() == package_name.as_normalized()) + { + return Ok(Some(( + Mapping::new(ExposedName::from_str(&executable.0)?, executable.0.clone()), + package.repodata_record.package_record.name.clone(), + ))); + } } -} - -/// Returns true if the bin folder is available on the PATH. -async fn is_bin_folder_on_path() -> bool { - let bin_path = match BinDir::from_existing().await.ok() { - Some(BinDir(bin_dir)) => bin_dir, - None => return false, - }; - - std::env::var_os("PATH") - .map(|path| std::env::split_paths(&path).collect_vec()) - .unwrap_or_default() - .into_iter() - .contains(&bin_path) + Ok(None) } diff --git a/src/cli/global/list.rs b/src/cli/global/list.rs index ea6212a63..5fa1e141d 100644 --- a/src/cli/global/list.rs +++ b/src/cli/global/list.rs @@ -1,159 +1,408 @@ -use std::collections::HashSet; -use std::str::FromStr; - +use crate::global::common::find_package_records; +use crate::global::project::ParsedEnvironment; +use crate::global::{EnvironmentName, Mapping, Project}; use clap::Parser; +use fancy_display::FancyDisplay; +use human_bytes::human_bytes; +use indexmap::{IndexMap, IndexSet}; use itertools::Itertools; -use miette::IntoDiagnostic; -use rattler_conda_types::PackageName; - -use crate::prefix::Prefix; -use pixi_config::home_path; - -use super::common::{bin_env_dir, find_designated_package, BinDir, BinEnvDir}; -use super::install::{find_and_map_executable_scripts, BinScriptMapping}; +use miette::{miette, IntoDiagnostic}; +use pixi_config::{Config, ConfigCli}; +use pixi_consts::consts; +use pixi_spec::PixiSpec; +use rattler_conda_types::{PackageName, PackageRecord, PrefixRecord, Version}; +use serde::Serialize; +use std::io::{stdout, Write}; +use std::str::FromStr; /// Lists all packages previously installed into a globally accessible location via `pixi global install`. +/// +/// All environments: +/// - Yellow: the binaries that are exposed. +/// - Green: the packages that are explicit dependencies of the environment. +/// - Blue: the version of the installed package. +/// - Cyan: the name of the environment. +/// +/// Per environment: +/// - Green: packages that are explicitly installed. #[derive(Parser, Debug)] -pub struct Args {} +#[clap(verbatim_doc_comment)] +pub struct Args { + /// List only packages matching a regular expression. + /// Without regex syntax it acts like a `contains` filter. + #[arg()] + pub regex: Option, -#[derive(Debug)] -struct InstalledPackageInfo { - /// The name of the installed package - name: PackageName, + #[clap(flatten)] + config: ConfigCli, - /// The binaries installed by this package - binaries: Vec, + /// The name of the environment to list. + #[clap(short, long)] + environment: Option, - /// The version of the installed package - version: String, + /// Sorting strategy for the package table of an environment + #[arg(long, default_value = "name", value_enum, requires = "environment")] + sort_by: GlobalSortBy, } -fn print_no_packages_found_message() { - eprintln!( - "{} No globally installed binaries found", - console::style("!").yellow().bold() - ) +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project = Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + if let Some(environment) = args.environment { + let env_name = EnvironmentName::from_str(environment.as_str())?; + // Verify that the environment is in sync with the manifest and report to the user otherwise + if !project.environment_in_sync(&env_name).await? { + tracing::warn!("The environment {} is not in sync with the manifest, to sync run\n\tpixi global sync", env_name.fancy_display()); + } + list_environment(project, &env_name, args.sort_by, args.regex).await?; + } else { + // Verify that the environments are in sync with the manifest and report to the user otherwise + if !project.environments_in_sync().await? { + tracing::warn!("The environments are not in sync with the manifest, to sync run\n\tpixi global sync"); + } + list_global_environments(project, args.regex).await?; + } + + Ok(()) } -pub async fn execute(_args: Args) -> miette::Result<()> { - let packages = list_global_packages().await?; - - let mut package_info = vec![]; - - for package_name in packages { - let Ok(BinEnvDir(bin_env_prefix)) = BinEnvDir::from_existing(&package_name).await else { - print_no_packages_found_message(); - return Ok(()); - }; - let prefix = Prefix::new(bin_env_prefix); - - let Ok(bin_prefix) = BinDir::from_existing().await else { - print_no_packages_found_message(); - return Ok(()); - }; - - // Find the installed package in the environment - let prefix_package = find_designated_package(&prefix, &package_name).await?; - - let binaries: Vec<_> = - find_and_map_executable_scripts(&prefix, &prefix_package, &bin_prefix) - .await? - .into_iter() - .map( - |BinScriptMapping { - global_binary_path: path, - .. - }| { - path.strip_prefix(&bin_prefix.0) - .expect("script paths were constructed by joining onto BinDir") - .to_string_lossy() - .to_string() - }, - ) - // Collecting to a HashSet first is a workaround for issue #317 and can be removed - // once that is fixed. - .collect::>() - .into_iter() - .collect(); - - let version = prefix_package - .repodata_record - .package_record - .version - .to_string(); - package_info.push(InstalledPackageInfo { - name: package_name, - binaries, - version, - }); +/// Sorting strategy for the package table +#[derive(clap::ValueEnum, Clone, Debug, Serialize)] +pub enum GlobalSortBy { + Size, + Name, +} + +#[derive(Serialize, Hash, Eq, PartialEq)] +struct PackageToOutput { + name: PackageName, + version: Version, + build: Option, + size_bytes: Option, + is_explicit: bool, +} + +impl PackageToOutput { + fn new(record: &PackageRecord, is_explicit: bool) -> Self { + Self { + name: record.name.clone(), + version: record.version.version().clone(), + build: Some(record.build.clone()), + size_bytes: record.size, + is_explicit, + } } +} + +/// List package and binaries in environment +async fn list_environment( + project: Project, + environment_name: &EnvironmentName, + sort_by: GlobalSortBy, + regex: Option, +) -> miette::Result<()> { + let env = project + .environments() + .get(environment_name) + .ok_or_else(|| miette!("Environment {} not found", environment_name.fancy_display()))?; + + let records = find_package_records( + &project + .env_root + .path() + .join(environment_name.as_str()) + .join(consts::CONDA_META_DIR), + ) + .await?; + + let mut packages_to_output: Vec = records + .iter() + .map(|record| { + PackageToOutput::new( + &record.repodata_record.package_record, + env.dependencies() + .contains_key(&record.repodata_record.package_record.name), + ) + }) + .collect(); - if package_info.is_empty() { - print_no_packages_found_message(); + // Filter according to the regex + if let Some(ref regex) = regex { + let regex = regex::Regex::new(regex).into_diagnostic()?; + packages_to_output.retain(|package| regex.is_match(package.name.as_normalized())); + } + + let output_message = if let Some(ref regex) = regex { + format!( + "The {} environment has {} packages filtered by regex `{}`:", + environment_name.fancy_display(), + console::style(packages_to_output.len()).bold(), + regex + ) } else { - let path = home_path().ok_or(miette::miette!("Could not determine home directory"))?; - let len = package_info.len(); - let mut message = String::new(); - for (idx, pkgi) in package_info.into_iter().enumerate() { - let last = (idx + 1) == len; - let no_binary = pkgi.binaries.is_empty(); - - if last { - message.push_str("└──"); + format!( + "The {} environment has {} packages:", + environment_name.fancy_display(), + console::style(packages_to_output.len()).bold() + ) + }; + + // Sort according to the sorting strategy + match sort_by { + GlobalSortBy::Size => { + packages_to_output + .sort_by(|a, b| a.size_bytes.unwrap_or(0).cmp(&b.size_bytes.unwrap_or(0))); + } + GlobalSortBy::Name => { + packages_to_output.sort_by(|a, b| a.name.cmp(&b.name)); + } + } + println!("{}", output_message); + print_package_table(packages_to_output).into_diagnostic()?; + println!(); + print_meta_info(env); + + Ok(()) +} + +fn print_meta_info(environment: &ParsedEnvironment) { + // Print exposed binaries, if binary similar to path only print once. + let formatted_exposed = environment.exposed.iter().map(format_mapping).join(", "); + println!( + "{}\n{}", + console::style("Exposes:").bold().cyan(), + if !formatted_exposed.is_empty() { + formatted_exposed + } else { + "Nothing".to_string() + } + ); + + // Print channels + if !environment.channels().is_empty() { + println!( + "{}\n{}", + console::style("Channels:").bold().cyan(), + environment.channels().iter().join(", ") + ); + } + + // Print platform + if let Some(platform) = environment.platform() { + println!("{} {}", console::style("Platform:").bold().cyan(), platform); + } +} + +/// Create a human-readable representation of the global environment. +/// Using a tabwriter to align the columns. +fn print_package_table(packages: Vec) -> Result<(), std::io::Error> { + let mut writer = tabwriter::TabWriter::new(stdout()); + let header_style = console::Style::new().bold().cyan(); + let header = format!( + "{}\t{}\t{}\t{}", + header_style.apply_to("Package"), + header_style.apply_to("Version"), + header_style.apply_to("Build"), + header_style.apply_to("Size"), + ); + writeln!(writer, "{}", &header)?; + + for package in packages { + // Convert size to human-readable format + let size_human = package + .size_bytes + .map(|size| human_bytes(size as f64)) + .unwrap_or_default(); + + let package_info = format!( + "{}\t{}\t{}\t{}", + package.name.as_normalized(), + &package.version, + package.build.as_deref().unwrap_or(""), + size_human + ); + + writeln!( + writer, + "{}", + if package.is_explicit { + console::style(package_info).green().to_string() } else { - message.push_str("├──"); + package_info } + )?; + } - message.push_str(&format!( - " {} {}", - console::style(&pkgi.name.as_source()).bold().magenta(), - console::style(&pkgi.version).bright().black() - )); + writeln!(writer, "{}", header)?; + + writer.flush() +} + +/// List all environments in the global environment +async fn list_global_environments(project: Project, regex: Option) -> miette::Result<()> { + let mut envs = project.environments().clone(); + envs.sort_by(|a, _, b, _| a.to_string().cmp(&b.to_string())); + + if let Some(regex) = regex { + let regex = regex::Regex::new(®ex).into_diagnostic()?; + envs.retain(|env_name, _| regex.is_match(env_name.as_str())); + } - if !no_binary { - let p = if last { " " } else { "|" }; + let mut message = String::new(); + + let len = envs.len(); + for (idx, (env_name, env)) in envs.iter().enumerate() { + let env_dir = project.env_root.path().join(env_name.as_str()); + let records = find_package_records(&env_dir.join(consts::CONDA_META_DIR)).await?; + + let last = (idx + 1) == len; + + if last { + message.push_str("└──"); + } else { + message.push_str("├──"); + } + + if !env + .dependencies() + .iter() + .any(|(pkg_name, _spec)| pkg_name.as_normalized() != env_name.as_str()) + { + if let Some(env_package) = records.iter().find(|rec| { + rec.repodata_record.package_record.name.as_normalized() == env_name.as_str() + }) { message.push_str(&format!( - "\n{} └─ exec: {}", - p, - pkgi.binaries - .iter() - .map(|x| console::style(x).green()) - .join(", ") + " {}: {}", + env_name.fancy_display(), + console::style(env_package.repodata_record.package_record.version.clone()) + .blue() )); + } else { + message.push_str(&format!(" {}", env_name.fancy_display())); } + } else { + message.push_str(&format!(" {}", env_name.fancy_display())); + } - if !last { - message.push('\n'); - } + // Write dependencies + if let Some(dep_message) = format_dependencies( + env_name.as_str(), + &env.dependencies, + &records, + last, + !env.exposed.is_empty(), + ) { + message.push_str(&dep_message); + } + + // Write exposed binaries + if let Some(exp_message) = format_exposed(env_name.as_str(), env.exposed(), last) { + message.push_str(&exp_message); } - eprintln!("Global install location: {}\n{}", path.display(), message); + if !last { + message.push('\n'); + } + } + if message.is_empty() { + println!("No global environments found."); + } else { + println!( + "Global environments as specified in '{}'\n{}", + console::style(project.manifest.path.display()).bold(), + message + ); } Ok(()) } -/// List all globally installed packages -/// -/// # Returns -/// -/// A list of all globally installed packages represented as [`PackageName`]s -pub(super) async fn list_global_packages() -> miette::Result> { - let mut packages = vec![]; - let bin_env_dir = - bin_env_dir().ok_or(miette::miette!("Could not determine global envs directory"))?; - let Ok(mut dir_contents) = tokio::fs::read_dir(bin_env_dir).await else { - return Ok(vec![]); - }; +/// Display a dependency in a human-readable format. +fn display_dependency(name: &PackageName, version: Option) -> String { + if let Some(version) = version { + format!( + "{} {}", + console::style(name.as_normalized()).green(), + console::style(version).blue() + ) + } else { + console::style(name.as_normalized()).green().to_string() + } +} - while let Some(entry) = dir_contents.next_entry().await.into_diagnostic()? { - if entry.file_type().await.into_diagnostic()?.is_dir() { - if let Ok(name) = PackageName::from_str(entry.file_name().to_string_lossy().as_ref()) { - packages.push(name); - } - } +/// Creating the ASCII art representation of a section. +fn format_asciiart_section(label: &str, content: String, last: bool, more: bool) -> String { + let prefix = if last { " " } else { "│" }; + let symbol = if more { "├" } else { "└" }; + format!("\n{} {}─ {}: {}", prefix, symbol, label, content) +} + +fn format_dependencies( + env_name: &str, + dependencies: &IndexMap, + records: &[PrefixRecord], + last: bool, + more: bool, +) -> Option { + if dependencies + .iter() + .any(|(pkg_name, _spec)| pkg_name.as_normalized() != env_name) + { + let content = dependencies + .iter() + .map(|(name, _spec)| { + let version = records + .iter() + .find(|rec| { + rec.repodata_record.package_record.name.as_normalized() + == name.as_normalized() + }) + .map(|rec| rec.repodata_record.package_record.version.version().clone()); + display_dependency(name, version) + }) + .join(", "); + Some(format_asciiart_section("dependencies", content, last, more)) + } else { + None + } +} + +fn format_exposed(env_name: &str, exposed: &IndexSet, last: bool) -> Option { + if exposed.is_empty() { + Some(format_asciiart_section( + "exposes", + console::style("Nothing").dim().red().to_string(), + last, + false, + )) + } else if exposed + .iter() + .any(|mapping| mapping.exposed_name().to_string() != env_name) + { + let formatted_exposed = exposed.iter().map(format_mapping).join(", "); + Some(format_asciiart_section( + "exposes", + formatted_exposed, + last, + false, + )) + } else { + None } +} - packages.sort(); - Ok(packages) +fn format_mapping(mapping: &Mapping) -> String { + let exp = mapping.exposed_name().to_string(); + if exp == mapping.executable_name() { + console::style(exp).yellow().to_string() + } else { + format!( + "{} -> {}", + console::style(exp).yellow(), + console::style(mapping.executable_name()).yellow() + ) + } } diff --git a/src/cli/global/mod.rs b/src/cli/global/mod.rs index 0bc94513f..5d5cc683a 100644 --- a/src/cli/global/mod.rs +++ b/src/cli/global/mod.rs @@ -1,23 +1,39 @@ use clap::Parser; -mod common; +use crate::global::{self, EnvironmentName}; + +mod add; +mod edit; +mod expose; mod install; mod list; mod remove; +mod sync; +mod uninstall; +mod update; mod upgrade; mod upgrade_all; #[derive(Debug, Parser)] pub enum Command { + #[clap(visible_alias = "a")] + Add(add::Args), + Edit(edit::Args), #[clap(visible_alias = "i")] Install(install::Args), + Uninstall(uninstall::Args), #[clap(visible_alias = "rm")] Remove(remove::Args), #[clap(visible_alias = "ls")] List(list::Args), - #[clap(visible_alias = "u")] + #[clap(visible_alias = "s")] + Sync(sync::Args), + #[clap(visible_alias = "e")] + #[command(subcommand)] + Expose(expose::SubCommand), + Update(update::Args), Upgrade(upgrade::Args), - #[clap(visible_alias = "ua")] + #[clap(alias = "ua")] UpgradeAll(upgrade_all::Args), } @@ -35,11 +51,29 @@ pub struct Args { pub async fn execute(cmd: Args) -> miette::Result<()> { match cmd.command { + Command::Add(args) => add::execute(args).await?, + Command::Edit(args) => edit::execute(args).await?, Command::Install(args) => install::execute(args).await?, + Command::Uninstall(args) => uninstall::execute(args).await?, Command::Remove(args) => remove::execute(args).await?, Command::List(args) => list::execute(args).await?, + Command::Sync(args) => sync::execute(args).await?, + Command::Expose(subcommand) => expose::execute(subcommand).await?, + Command::Update(args) => update::execute(args).await?, Command::Upgrade(args) => upgrade::execute(args).await?, Command::UpgradeAll(args) => upgrade_all::execute(args).await?, }; Ok(()) } + +/// Reverts the changes made to the project for a specific environment after an error occurred. +async fn revert_environment_after_error( + env_name: &EnvironmentName, + project_to_revert_to: &global::Project, +) -> miette::Result<()> { + if project_to_revert_to.environment(env_name).is_some() { + // We don't want to report on changes done by the reversion + let _ = project_to_revert_to.sync_environment(env_name).await?; + } + Ok(()) +} diff --git a/src/cli/global/remove.rs b/src/cli/global/remove.rs index 020574d41..0e33f625e 100644 --- a/src/cli/global/remove.rs +++ b/src/cli/global/remove.rs @@ -1,27 +1,32 @@ -use std::collections::HashSet; - +use crate::cli::global::revert_environment_after_error; +use crate::cli::has_specs::HasSpecs; +use crate::global::{EnvironmentName, ExposedName, Project, StateChanges}; use clap::Parser; -use clap_verbosity_flag::{Level, Verbosity}; use itertools::Itertools; -use miette::IntoDiagnostic; -use rattler_conda_types::PackageName; - -use crate::cli::has_specs::HasSpecs; -use crate::prefix::Prefix; - -use super::common::{find_designated_package, BinDir, BinEnvDir}; -use super::install::{find_and_map_executable_scripts, BinScriptMapping}; - -/// Removes a package previously installed into a globally accessible location via `pixi global install`. +use miette::Context; +use pixi_config::{Config, ConfigCli}; +use rattler_conda_types::MatchSpec; +use std::str::FromStr; + +/// Removes dependencies from an environment +/// +/// Use `pixi global uninstall` to remove the whole environment +/// +/// Example: +/// - pixi global remove --environment python numpy #[derive(Parser, Debug)] -#[clap(arg_required_else_help = true)] +#[clap(arg_required_else_help = true, verbatim_doc_comment)] pub struct Args { /// Specifies the packages that are to be removed. - #[arg(num_args = 1..)] + #[arg(num_args = 1.., required = true)] packages: Vec, - #[command(flatten)] - verbose: Verbosity, + /// Specifies the environment that the dependencies need to be removed from. + #[clap(short, long)] + environment: Option, + + #[clap(flatten)] + config: ConfigCli, } impl HasSpecs for Args { @@ -31,89 +36,80 @@ impl HasSpecs for Args { } pub async fn execute(args: Args) -> miette::Result<()> { - for (package_name, _) in args.specs()? { - remove_global_package(package_name, &args.verbose).await?; + let Some(env_name) = &args.environment else { + miette::bail!("`--environment` is required. Try `pixi global uninstall {}` if you want to delete whole environments", args.packages.join(" ")); + }; + let config = Config::with_cli_config(&args.config); + let project_original = Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + if project_original.environment(env_name).is_none() { + miette::bail!("Environment {} doesn't exist. You can create a new environment with `pixi global install`.", env_name); } - Ok(()) -} - -async fn remove_global_package( - package_name: PackageName, - verbose: &Verbosity, -) -> miette::Result<()> { - let BinEnvDir(bin_prefix) = BinEnvDir::from_existing(&package_name).await?; - let prefix = Prefix::new(bin_prefix.clone()); - - // Find the installed package in the environment - let prefix_package = find_designated_package(&prefix, &package_name).await?; - - // Construct the paths to all the installed package executables, which are what we need to remove. - let paths_to_remove: Vec<_> = - find_and_map_executable_scripts(&prefix, &prefix_package, &BinDir::from_existing().await?) - .await? - .into_iter() - .map( - |BinScriptMapping { - global_binary_path: path, - .. - }| path, - ) - // Collecting to a HashSet first is a workaround for issue #317 and can be removed - // once that is fixed. - .collect::>() - .into_iter() - .collect(); + async fn apply_changes( + env_name: &EnvironmentName, + specs: &[MatchSpec], + project: &mut Project, + ) -> miette::Result { + // Remove specs from the manifest + for spec in specs { + project.manifest.remove_dependency(env_name, spec)?; + } - let dirs_to_remove: Vec<_> = vec![bin_prefix]; + // Figure out which package the exposed binaries belong to + let prefix = project.environment_prefix(env_name).await?; + + for spec in specs { + if let Some(name) = spec.clone().name { + // If the package is not existent, don't try to remove executables + if let Ok(record) = prefix.find_designated_package(&name).await { + prefix + .find_executables(&[record]) + .into_iter() + .filter_map(|(name, _path)| ExposedName::from_str(name.as_str()).ok()) + .for_each(|exposed_name| { + project + .manifest + .remove_exposed_name(env_name, &exposed_name) + .ok(); + }); + } + } + } - if verbose.log_level().unwrap_or(Level::Error) >= Level::Warn { - let whitespace = console::Emoji(" ", "").to_string(); - let names_to_remove = dirs_to_remove - .iter() - .map(|dir| dir.to_string_lossy()) - .chain(paths_to_remove.iter().map(|path| path.to_string_lossy())) - .join(&format!("\n{whitespace} - ")); + // Sync environment + let state_changes = project.sync_environment(env_name).await?; - eprintln!( - "{} Removing the following files and directories:\n{whitespace} - {names_to_remove}", - console::style("!").yellow().bold(), - ) + project.manifest.save().await?; + Ok(state_changes) } - let mut errors = vec![]; - - for file in paths_to_remove { - if let Err(e) = tokio::fs::remove_file(&file).await.into_diagnostic() { - errors.push((file, e)) + let mut project = project_original.clone(); + let specs = args + .specs()? + .into_iter() + .map(|(_, specs)| specs) + .collect_vec(); + + match apply_changes(env_name, specs.as_slice(), &mut project) + .await + .wrap_err(format!("Couldn't remove packages from {}", env_name)) + { + Ok(ref mut state_changes) => { + state_changes.report(); } - } - - for dir in dirs_to_remove { - if let Err(e) = tokio::fs::remove_dir_all(&dir).await.into_diagnostic() { - errors.push((dir, e)) + Err(err) => { + revert_environment_after_error(env_name, &project_original) + .await + .wrap_err(format!( + "Could not remove {:?}. Reverting also failed.", + args.packages + ))?; + return Err(err); } } - if errors.is_empty() { - eprintln!( - "{}Successfully removed global package {}", - console::style(console::Emoji("✔ ", "")).green(), - console::style(package_name.as_source()).bold(), - ); - } else { - let whitespace = console::Emoji(" ", "").to_string(); - let error_string = errors - .into_iter() - .map(|(file, e)| format!("{} (on {})", e, file.to_string_lossy())) - .join(&format!("\n{whitespace} - ")); - miette::bail!( - "got multiple errors trying to remove global package {}:\n{} - {}", - package_name.as_source(), - whitespace, - error_string, - ); - } - Ok(()) } diff --git a/src/cli/global/sync.rs b/src/cli/global/sync.rs new file mode 100644 index 000000000..947425033 --- /dev/null +++ b/src/cli/global/sync.rs @@ -0,0 +1,31 @@ +use crate::global; +use clap::Parser; +use pixi_config::{Config, ConfigCli}; + +/// Sync global manifest with installed environments +#[derive(Parser, Debug)] +pub struct Args { + #[clap(flatten)] + config: ConfigCli, +} + +/// Sync global manifest with installed environments +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + let mut state_changes = project.sync().await?; + + if state_changes.has_changed() { + state_changes.report(); + } else { + eprintln!( + "{}Nothing to do. The pixi global installation is already up-to-date.", + console::style(console::Emoji("✔ ", "")).green() + ); + } + + Ok(()) +} diff --git a/src/cli/global/uninstall.rs b/src/cli/global/uninstall.rs new file mode 100644 index 000000000..bdb01da8a --- /dev/null +++ b/src/cli/global/uninstall.rs @@ -0,0 +1,70 @@ +use crate::cli::global::revert_environment_after_error; +use crate::global::{self, StateChanges}; +use crate::global::{EnvironmentName, Project}; +use clap::Parser; +use fancy_display::FancyDisplay; +use miette::Context; +use pixi_config::{Config, ConfigCli}; + +/// Uninstalls environments from the global environment. +/// +/// Example: +/// pixi global uninstall pixi-pack rattler-build +#[derive(Parser, Debug, Clone)] +#[clap(arg_required_else_help = true, verbatim_doc_comment)] +pub struct Args { + /// Specifies the environments that are to be removed. + #[arg(num_args = 1.., required = true)] + environment: Vec, + + #[clap(flatten)] + config: ConfigCli, +} + +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + async fn apply_changes( + env_name: &EnvironmentName, + project_modified: &mut Project, + ) -> miette::Result { + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + state_changes |= project_modified.remove_environment(env_name).await?; + + project_modified.manifest.save().await?; + Ok(state_changes) + } + + let mut last_updated_project = project_original; + let mut state_changes = StateChanges::default(); + for env_name in &args.environment { + let mut project = last_updated_project.clone(); + match apply_changes(env_name, &mut project) + .await + .wrap_err_with(|| format!("Couldn't remove {}", env_name.fancy_display())) + { + Ok(sc) => { + state_changes |= sc; + } + Err(err) => { + state_changes.report(); + revert_environment_after_error(env_name, &last_updated_project) + .await + .wrap_err_with(|| { + format!( + "Couldn't uninstall environment {}. Reverting also failed.", + env_name.fancy_display() + ) + })?; + + return Err(err); + } + } + last_updated_project = project; + } + state_changes.report(); + Ok(()) +} diff --git a/src/cli/global/update.rs b/src/cli/global/update.rs new file mode 100644 index 000000000..20be901d7 --- /dev/null +++ b/src/cli/global/update.rs @@ -0,0 +1,63 @@ +use crate::cli::global::revert_environment_after_error; +use crate::global::{self, StateChanges}; +use crate::global::{EnvironmentName, Project}; +use clap::Parser; +use pixi_config::{Config, ConfigCli}; + +/// Updates environments in the global environment. +#[derive(Parser, Debug, Clone)] +pub struct Args { + /// Specifies the environments that are to be updated. + environments: Option>, + + #[clap(flatten)] + config: ConfigCli, +} + +pub async fn execute(args: Args) -> miette::Result<()> { + let config = Config::with_cli_config(&args.config); + let project_original = global::Project::discover_or_create() + .await? + .with_cli_config(config.clone()); + + async fn apply_changes( + env_name: &EnvironmentName, + project: &mut Project, + ) -> miette::Result { + let mut state_changes = StateChanges::default(); + // Reinstall the environment + project.install_environment(env_name).await?; + + // Remove broken executables + state_changes |= project.remove_broken_expose_names(env_name).await?; + + state_changes.insert_change(env_name, global::StateChange::UpdatedEnvironment); + + Ok(state_changes) + } + + // Update all environments if the user did not specify any + let env_names = match args.environments { + Some(env_names) => env_names, + None => project_original.environments().keys().cloned().collect(), + }; + + // Apply changes to each environment, only revert changes if an error occurs + let mut last_updated_project = project_original; + let mut state_changes = StateChanges::default(); + for env_name in env_names { + let mut project = last_updated_project.clone(); + match apply_changes(&env_name, &mut project).await { + Ok(sc) => state_changes |= sc, + Err(err) => { + state_changes.report(); + revert_environment_after_error(&env_name, &last_updated_project).await?; + return Err(err); + } + } + last_updated_project = project; + } + last_updated_project.manifest.save().await?; + state_changes.report(); + Ok(()) +} diff --git a/src/cli/global/upgrade.rs b/src/cli/global/upgrade.rs index 8177bbcba..91ed8f31d 100644 --- a/src/cli/global/upgrade.rs +++ b/src/cli/global/upgrade.rs @@ -1,27 +1,16 @@ -use std::{collections::HashMap, sync::Arc, time::Duration}; - use clap::Parser; -use indexmap::IndexMap; -use indicatif::ProgressBar; -use itertools::Itertools; -use miette::{Context, IntoDiagnostic, Report}; -use pixi_utils::reqwest::build_reqwest_clients; -use rattler_conda_types::{Channel, GenericVirtualPackage, MatchSpec, PackageName, Platform}; -use rattler_solve::{resolvo::Solver, SolverImpl, SolverTask}; -use rattler_virtual_packages::{VirtualPackage, VirtualPackageOverrides}; -use tokio::task::JoinSet; +use rattler_conda_types::Platform; -use super::{common::find_installed_package, install::globally_install_package}; use crate::cli::{cli_config::ChannelsConfig, has_specs::HasSpecs}; -use pixi_config::Config; -use pixi_progress::{global_multi_progress, long_running_progress_style, wrap_in_progress}; /// Upgrade specific package which is installed globally. #[derive(Parser, Debug)] -#[clap(arg_required_else_help = true)] +// TODO: Uncomment as soon we implement this +//#[clap(arg_required_else_help = true)] pub struct Args { /// Specifies the packages to upgrade. - #[arg(required = true)] + // TODO: Uncomment as soon we implement this + //#[arg(required = true)] pub specs: Vec, #[clap(flatten)] @@ -38,179 +27,10 @@ impl HasSpecs for Args { } } -pub async fn execute(args: Args) -> miette::Result<()> { - let config = Config::load_global(); - let specs = args.specs()?; - upgrade_packages(specs, config, args.channels, args.platform).await -} - -pub(super) async fn upgrade_packages( - specs: IndexMap, - config: Config, - cli_channels: ChannelsConfig, - platform: Platform, -) -> miette::Result<()> { - let channel_cli = cli_channels.resolve_from_config(&config)?; - - // Get channels and version of globally installed packages in parallel - let mut channels = HashMap::with_capacity(specs.len()); - let mut versions = HashMap::with_capacity(specs.len()); - let mut set: JoinSet> = JoinSet::new(); - for package_name in specs.keys().cloned() { - let channel_config = config.global_channel_config().clone(); - set.spawn(async move { - let p = find_installed_package(&package_name).await?; - let channel = - Channel::from_str(p.repodata_record.channel, &channel_config).into_diagnostic()?; - let version = p.repodata_record.package_record.version.into_version(); - Ok((package_name, channel, version)) - }); - } - while let Some(data) = set.join_next().await { - let (package_name, channel, version) = data.into_diagnostic()??; - channels.insert(package_name.clone(), channel); - versions.insert(package_name, version); - } - - // Fetch repodata across all channels - - // Start by aggregating all channels that we need to iterate - let all_channels: Vec = channels - .values() - .cloned() - .chain(channel_cli.iter().cloned()) - .unique() - .collect(); - - // Now ask gateway to query repodata for these channels - let (_, authenticated_client) = build_reqwest_clients(Some(&config)); - let gateway = config.gateway(authenticated_client.clone()); - let repodata = gateway - .query( - all_channels, - [platform, Platform::NoArch], - specs.values().cloned().collect_vec(), - ) - .recursive(true) - .await - .into_diagnostic()?; - - // Resolve environments in parallel - let mut set: JoinSet> = JoinSet::new(); - - // Create arcs for these structs - // as they later will be captured by closure - let repodata = Arc::new(repodata); - let config = Arc::new(config); - let channel_cli = Arc::new(channel_cli); - let channels = Arc::new(channels); - - for (package_name, package_matchspec) in specs { - let repodata = repodata.clone(); - let config = config.clone(); - let channel_cli = channel_cli.clone(); - let channels = channels.clone(); - - set.spawn_blocking(move || { - // Filter repodata based on channels specific to the package (and from the CLI) - let specific_repodata: Vec<_> = repodata - .iter() - .filter_map(|repodata| { - let filtered: Vec<_> = repodata - .iter() - .filter(|item| { - let item_channel = - Channel::from_str(&item.channel, config.global_channel_config()) - .expect("should be parseable"); - channel_cli.contains(&item_channel) - || channels - .get(&package_name) - .map_or(false, |c| c == &item_channel) - }) - .collect(); - - (!filtered.is_empty()).then_some(filtered) - }) - .collect(); - - // Determine virtual packages of the current platform - let virtual_packages = VirtualPackage::detect(&VirtualPackageOverrides::from_env()) - .into_diagnostic() - .context("failed to determine virtual packages")? - .iter() - .cloned() - .map(GenericVirtualPackage::from) - .collect(); - - // Solve the environment - let solver_matchspec = package_matchspec.clone(); - let solved_records = wrap_in_progress("solving environment", move || { - Solver.solve(SolverTask { - specs: vec![solver_matchspec], - virtual_packages, - ..SolverTask::from_iter(specific_repodata) - }) - }) - .into_diagnostic() - .context("failed to solve environment")?; - - Ok((package_name, package_matchspec.clone(), solved_records)) - }); - } - - // Upgrade each package when relevant - let mut upgraded = false; - while let Some(data) = set.join_next().await { - let (package_name, package_matchspec, records) = data.into_diagnostic()??; - let toinstall_version = records - .iter() - .find(|r| r.package_record.name == package_name) - .map(|p| p.package_record.version.version().to_owned()) - .ok_or_else(|| { - miette::miette!( - "Package {} not found in the specified channels", - package_name.as_normalized() - ) - })?; - let installed_version = versions - .get(&package_name) - .expect("should have the installed version") - .to_owned(); - - // Perform upgrade if a specific version was requested - // OR if a more recent version is available - if package_matchspec.version.is_some() || toinstall_version > installed_version { - let message = format!( - "{} v{} -> v{}", - package_name.as_normalized(), - installed_version, - toinstall_version - ); - - let pb = global_multi_progress().add(ProgressBar::new_spinner()); - pb.enable_steady_tick(Duration::from_millis(100)); - pb.set_style(long_running_progress_style()); - pb.set_message(format!( - "{} {}", - console::style("Updating").green(), - message - )); - globally_install_package( - &package_name, - records, - authenticated_client.clone(), - platform, - false, - ) - .await?; - pb.finish_with_message(format!("{} {}", console::style("Updated").green(), message)); - upgraded = true; - } - } - - if !upgraded { - eprintln!("Nothing to upgrade"); - } - - Ok(()) +pub async fn execute(_args: Args) -> miette::Result<()> { + Err( + miette::miette!("You can use `pixi global update` for most use cases").wrap_err( + "`pixi global upgrade` has been removed, and will be re-added in future releases", + ), + ) } diff --git a/src/cli/global/upgrade_all.rs b/src/cli/global/upgrade_all.rs index be72d5565..bab7c772f 100644 --- a/src/cli/global/upgrade_all.rs +++ b/src/cli/global/upgrade_all.rs @@ -1,42 +1,34 @@ use clap::Parser; -use indexmap::IndexMap; +use rattler_conda_types::Platform; -use rattler_conda_types::{MatchSpec, Platform}; +use crate::cli::{cli_config::ChannelsConfig, has_specs::HasSpecs}; -use pixi_config::{Config, ConfigCli}; - -use crate::cli::cli_config::ChannelsConfig; - -use super::{list::list_global_packages, upgrade::upgrade_packages}; - -/// Upgrade all globally installed packages +/// Upgrade specific package which is installed globally. #[derive(Parser, Debug)] +#[clap(arg_required_else_help = true)] pub struct Args { - #[clap(flatten)] - channels: ChannelsConfig, + /// Specifies the packages to upgrade. + //#[arg(required = true)] + pub specs: Vec, #[clap(flatten)] - config: ConfigCli, + channels: ChannelsConfig, /// The platform to install the package for. #[clap(long, default_value_t = Platform::current())] platform: Platform, } -pub async fn execute(args: Args) -> miette::Result<()> { - let config = Config::with_cli_config(&args.config); - - let names = list_global_packages().await?; - let mut specs = IndexMap::with_capacity(names.len()); - for name in names { - specs.insert( - name.clone(), - MatchSpec { - name: Some(name), - ..Default::default() - }, - ); +impl HasSpecs for Args { + fn packages(&self) -> Vec<&str> { + self.specs.iter().map(AsRef::as_ref).collect() } +} - upgrade_packages(specs, config, args.channels, args.platform).await +pub async fn execute(_args: Args) -> miette::Result<()> { + Err( + miette::miette!("You can use `pixi global update` for most use cases").wrap_err( + "`pixi global upgrade-all` has been removed, and will be re-added in future releases", + ), + ) } diff --git a/src/cli/info.rs b/src/cli/info.rs index 5c52e4607..540d2b077 100644 --- a/src/cli/info.rs +++ b/src/cli/info.rs @@ -18,7 +18,12 @@ use tokio::task::spawn_blocking; use crate::cli::cli_config::ProjectConfig; -use crate::{task::TaskName, Project}; +use crate::{ + global, + global::{BinDir, EnvRoot}, + task::TaskName, + Project, +}; use fancy_display::FancyDisplay; static WIDTH: usize = 18; @@ -158,6 +163,38 @@ impl Display for EnvironmentInfo { } } +/// Information about `pixi global` +#[derive(Serialize)] +struct GlobalInfo { + bin_dir: PathBuf, + env_dir: PathBuf, + manifest: PathBuf, +} +impl Display for GlobalInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let bold = console::Style::new().bold(); + writeln!( + f, + "{:>WIDTH$}: {}", + bold.apply_to("Bin dir"), + self.bin_dir.to_string_lossy() + )?; + writeln!( + f, + "{:>WIDTH$}: {}", + bold.apply_to("Environment dir"), + self.env_dir.to_string_lossy() + )?; + writeln!( + f, + "{:>WIDTH$}: {}", + bold.apply_to("Manifest dir"), + self.manifest.to_string_lossy() + )?; + Ok(()) + } +} + #[serde_as] #[derive(Serialize)] pub struct Info { @@ -168,6 +205,7 @@ pub struct Info { cache_dir: Option, cache_size: Option, auth_dir: PathBuf, + global_info: Option, project_info: Option, environments_info: Vec, config_locations: Vec, @@ -180,6 +218,7 @@ impl Display for Info { None => "None".to_string(), }; + writeln!(f, "{}", bold.apply_to("System\n------------").cyan())?; writeln!( f, "{:>WIDTH$}: {}", @@ -230,8 +269,15 @@ impl Display for Info { } )?; + // Pixi global information + if let Some(gi) = self.global_info.as_ref() { + writeln!(f, "\n{}", bold.apply_to("Global\n------------").cyan())?; + write!(f, "{}", gi)?; + } + + // Project information if let Some(pi) = self.project_info.as_ref() { - writeln!(f, "\n{}", bold.apply_to("Project\n------------"))?; + writeln!(f, "\n{}", bold.apply_to("Project\n------------").cyan())?; writeln!(f, "{:>WIDTH$}: {}", bold.apply_to("Name"), pi.name)?; if let Some(version) = pi.version.clone() { writeln!(f, "{:>WIDTH$}: {}", bold.apply_to("Version"), version)?; @@ -254,7 +300,11 @@ impl Display for Info { } if !self.environments_info.is_empty() { - writeln!(f, "\n{}", bold.apply_to("Environments\n------------"))?; + writeln!( + f, + "\n{}", + bold.apply_to("Environments\n------------").cyan() + )?; for e in &self.environments_info { writeln!(f, "{}", e)?; } @@ -360,6 +410,12 @@ pub async fn execute(args: Args) -> miette::Result<()> { }) .unwrap_or_default(); + let global_info = Some(GlobalInfo { + bin_dir: BinDir::from_env().await?.path().to_path_buf(), + env_dir: EnvRoot::from_env().await?.path().to_path_buf(), + manifest: global::Project::manifest_dir()?.join(global::project::MANIFEST_DEFAULT_NAME), + }); + let virtual_packages = VirtualPackage::detect(&VirtualPackageOverrides::from_env()) .into_diagnostic()? .iter() @@ -389,6 +445,7 @@ pub async fn execute(args: Args) -> miette::Result<()> { auth_dir: auth_file, project_info, environments_info, + global_info, config_locations: config.loaded_from.clone(), }; diff --git a/src/global/common.rs b/src/global/common.rs new file mode 100644 index 000000000..77f8edd30 --- /dev/null +++ b/src/global/common.rs @@ -0,0 +1,667 @@ +use super::{extract_executable_from_script, EnvironmentName, ExposedName, Mapping}; +use fancy_display::FancyDisplay; +use fs_err as fs; +use fs_err::tokio as tokio_fs; +use indexmap::IndexSet; +use is_executable::IsExecutable; +use itertools::Itertools; +use miette::{Context, IntoDiagnostic}; +use pixi_config::home_path; +use pixi_manifest::PrioritizedChannel; +use pixi_utils::executable_from_path; +use rattler_conda_types::{Channel, ChannelConfig, NamedChannelOrUrl, PackageRecord, PrefixRecord}; +use std::collections::HashMap; +use std::ffi::OsStr; +use std::str::FromStr; +use std::{ + io::Read, + path::{Path, PathBuf}, +}; +use url::Url; + +/// Global binaries directory, default to `$HOME/.pixi/bin` +#[derive(Debug, Clone)] +pub struct BinDir(PathBuf); + +impl BinDir { + /// Create the binary executable directory from path + #[cfg(test)] + pub fn new(root: PathBuf) -> miette::Result { + let path = root.join("bin"); + std::fs::create_dir_all(&path).into_diagnostic()?; + Ok(Self(path)) + } + + /// Create the binary executable directory from environment variables + pub async fn from_env() -> miette::Result { + let bin_dir = home_path() + .map(|path| path.join("bin")) + .ok_or(miette::miette!( + "Couldn't determine global binary executable directory" + ))?; + tokio_fs::create_dir_all(&bin_dir).await.into_diagnostic()?; + Ok(Self(bin_dir)) + } + + /// Asynchronously retrieves all files in the binary executable directory. + /// + /// This function reads the directory specified by `self.0` and collects all + /// file paths into a vector. It returns a `miette::Result` containing the + /// vector of file paths or an error if the directory can't be read. + pub(crate) async fn files(&self) -> miette::Result> { + let mut files = Vec::new(); + let mut entries = tokio_fs::read_dir(&self.0).await.into_diagnostic()?; + + while let Some(entry) = entries.next_entry().await.into_diagnostic()? { + let path = entry.path(); + if path.is_file() && path.is_executable() && is_text(&path)? { + files.push(path); + } + } + + Ok(files) + } + + /// Returns the path to the binary directory + pub fn path(&self) -> &Path { + &self.0 + } + + /// Returns the path to the executable script for the given exposed name. + /// + /// This function constructs the path to the executable script by joining the + /// `bin_dir` with the provided `exposed_name`. If the target platform is + /// Windows, it sets the file extension to `.bat`. + pub(crate) fn executable_script_path(&self, exposed_name: &ExposedName) -> PathBuf { + // Add .bat to the windows executable + let exposed_name = if cfg!(windows) { + // Not using `.set_extension()` because it will break the `.` in the name for cases like `python3.9.1` + format!("{}.bat", exposed_name) + } else { + exposed_name.to_string() + }; + self.path().join(exposed_name) + } +} + +/// Global environments directory, default to `$HOME/.pixi/envs` +#[derive(Debug, Clone)] +pub struct EnvRoot(PathBuf); + +impl EnvRoot { + /// Create the environment root directory + #[cfg(test)] + pub fn new(root: PathBuf) -> miette::Result { + let path = root.join("envs"); + std::fs::create_dir_all(&path).into_diagnostic()?; + Ok(Self(path)) + } + + /// Create the environment root directory from environment variables + pub(crate) async fn from_env() -> miette::Result { + let path = home_path() + .map(|path| path.join("envs")) + .ok_or_else(|| miette::miette!("Couldn't get home path"))?; + tokio_fs::create_dir_all(&path).await.into_diagnostic()?; + Ok(Self(path)) + } + + pub fn path(&self) -> &Path { + &self.0 + } + + /// Get all directories in the env root + pub(crate) async fn directories(&self) -> miette::Result> { + let mut directories = Vec::new(); + let mut entries = tokio_fs::read_dir(&self.path()).await.into_diagnostic()?; + + while let Some(entry) = entries.next_entry().await.into_diagnostic()? { + let path = entry.path(); + if path.is_dir() { + directories.push(path); + } + } + + Ok(directories) + } +} + +/// A global environment directory +pub(crate) struct EnvDir { + pub(crate) path: PathBuf, +} + +impl EnvDir { + // Create EnvDir from path + pub(crate) fn from_path(path: PathBuf) -> Self { + Self { path } + } + + /// Create a global environment directory based on passed global environment root + pub(crate) async fn from_env_root( + env_root: EnvRoot, + environment_name: &EnvironmentName, + ) -> miette::Result { + let path = env_root.path().join(environment_name.as_str()); + tokio_fs::create_dir_all(&path).await.into_diagnostic()?; + + Ok(Self { path }) + } + + /// Construct the path to the env directory for the environment + /// `environment_name`. + pub(crate) fn path(&self) -> &Path { + &self.path + } +} + +/// Checks if a file is binary by reading the first 1024 bytes and checking for null bytes. +pub(crate) fn is_binary(file_path: impl AsRef) -> miette::Result { + let mut file = fs::File::open(file_path.as_ref()).into_diagnostic()?; + let mut buffer = [0; 1024]; + let bytes_read = file.read(&mut buffer).into_diagnostic()?; + + Ok(buffer[..bytes_read].contains(&0)) +} + +/// Checks if given path points to a text file by calling `is_binary`. +/// If that returns `false`, then it is a text file and vice-versa. +pub(crate) fn is_text(file_path: impl AsRef) -> miette::Result { + Ok(!is_binary(file_path)?) +} + +/// Finds the package record from the `conda-meta` directory. +pub(crate) async fn find_package_records(conda_meta: &Path) -> miette::Result> { + let mut read_dir = tokio_fs::read_dir(conda_meta).await.into_diagnostic()?; + let mut records = Vec::new(); + + while let Some(entry) = read_dir.next_entry().await.into_diagnostic()? { + let path = entry.path(); + // Check if the entry is a file and has a .json extension + if path.is_file() && path.extension().and_then(OsStr::to_str) == Some("json") { + let prefix_record = PrefixRecord::from_path(&path) + .into_diagnostic() + .wrap_err_with(|| format!("Couldn't parse json from {}", path.display()))?; + + records.push(prefix_record); + } + } + + if records.is_empty() { + miette::bail!("No package records found in {}", conda_meta.display()); + } + + Ok(records) +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[must_use] +pub(crate) enum StateChange { + AddedExposed(ExposedName), + RemovedExposed(ExposedName), + UpdatedExposed(ExposedName), + AddedPackage(PackageRecord), + AddedEnvironment, + RemovedEnvironment, + UpdatedEnvironment, +} + +#[must_use] +#[derive(Debug, Default)] +pub(crate) struct StateChanges { + changes: HashMap>, +} + +impl StateChanges { + /// Creates a new `StateChanges` instance with a single environment name and an empty vector as its value. + pub(crate) fn new_with_env(env_name: EnvironmentName) -> Self { + Self { + changes: HashMap::from([(env_name, Vec::new())]), + } + } + + pub(crate) fn has_changed(&self) -> bool { + !self.changes.values().all(Vec::is_empty) + } + + pub(crate) fn insert_change(&mut self, env_name: &EnvironmentName, change: StateChange) { + if let Some(entry) = self.changes.get_mut(env_name) { + entry.push(change); + } else { + self.changes.insert(env_name.clone(), Vec::from([change])); + } + } + + pub(crate) fn push_changes( + &mut self, + env_name: &EnvironmentName, + changes: impl IntoIterator, + ) { + if let Some(entry) = self.changes.get_mut(env_name) { + entry.extend(changes); + } else { + self.changes + .insert(env_name.clone(), changes.into_iter().collect()); + } + } + + #[cfg(test)] + pub fn changes(self) -> HashMap> { + self.changes + } + + /// Remove changes that cancel each other out + fn prune(&mut self) { + self.changes = self + .changes + .iter() + .map(|(env, changes_for_env)| { + // Remove changes if the environment is removed afterwards + let mut pruned_changes: Vec = Vec::new(); + for change in changes_for_env { + if let StateChange::RemovedEnvironment = change { + pruned_changes.clear(); + } + pruned_changes.push(change.clone()); + } + (env.clone(), pruned_changes) + }) + .collect() + } + + pub(crate) fn report(&mut self) { + self.prune(); + + for (env_name, changes_for_env) in &self.changes { + if changes_for_env.is_empty() { + eprintln!( + "{}The environment {} was already up-to-date", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + } + + let mut iter = changes_for_env.iter().peekable(); + + while let Some(change) = iter.next() { + match change { + StateChange::AddedExposed(exposed) => { + let mut exposed_names = vec![exposed.clone()]; + while let Some(StateChange::AddedExposed(next_exposed)) = iter.peek() { + exposed_names.push(next_exposed.clone()); + iter.next(); + } + if exposed_names.len() == 1 { + eprintln!( + "{}Exposed executable {} from environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + exposed_names[0].fancy_display(), + env_name.fancy_display() + ); + } else { + eprintln!( + "{}Exposed executables from environment {}:", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + for exposed_name in exposed_names { + eprintln!(" - {}", exposed_name.fancy_display()); + } + } + } + StateChange::RemovedExposed(exposed) => { + eprintln!( + "{}Removed exposed executable {} from environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + exposed.fancy_display(), + env_name.fancy_display() + ); + } + StateChange::UpdatedExposed(exposed) => { + let mut exposed_names = vec![exposed.clone()]; + while let Some(StateChange::AddedExposed(next_exposed)) = iter.peek() { + exposed_names.push(next_exposed.clone()); + iter.next(); + } + if exposed_names.len() == 1 { + eprintln!( + "{}Updated executable {} of environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + exposed_names[0].fancy_display(), + env_name.fancy_display() + ); + } else { + eprintln!( + "{}Updated executables of environment {}:", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + for exposed_name in exposed_names { + eprintln!(" - {}", exposed_name.fancy_display()); + } + } + } + StateChange::AddedPackage(pkg) => { + eprintln!( + "{}Added package {}={} to environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + console::style(pkg.name.as_normalized()).green(), + console::style(&pkg.version).blue(), + env_name.fancy_display() + ); + } + StateChange::AddedEnvironment => { + eprintln!( + "{}Added environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + } + StateChange::RemovedEnvironment => { + eprintln!( + "{}Removed environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + } + StateChange::UpdatedEnvironment => { + eprintln!( + "{}Updated environment {}.", + console::style(console::Emoji("✔ ", "")).green(), + env_name.fancy_display() + ); + } + } + } + } + } +} + +impl std::ops::BitOrAssign for StateChanges { + fn bitor_assign(&mut self, rhs: Self) { + for (env_name, changes_for_env) in rhs.changes { + self.changes + .entry(env_name) + .or_default() + .extend(changes_for_env); + } + } +} + +/// converts a channel url string to a PrioritizedChannel +pub(crate) fn channel_url_to_prioritized_channel( + channel: &str, + channel_config: &ChannelConfig, +) -> miette::Result { + // If channel url contains channel config alias as a substring, don't use it as a URL + if channel.contains(channel_config.channel_alias.as_str()) { + // Create channel from URL for parsing + let channel = Channel::from_url(Url::from_str(channel).expect("channel should be url")); + // If it has a name return as named channel + if let Some(name) = channel.name { + // If the channel has a name, use it as the channel + return Ok(NamedChannelOrUrl::from_str(&name).into_diagnostic()?.into()); + } + } + // If channel doesn't contain the alias or has no name, use it as a URL + Ok(NamedChannelOrUrl::from_str(channel) + .into_diagnostic()? + .into()) +} + +/// Figures out what the status is of the exposed binaries of the environment. +/// +/// Returns a tuple of the exposed binaries to remove and the exposed binaries to add. +pub(crate) async fn get_expose_scripts_sync_status( + bin_dir: &BinDir, + env_dir: &EnvDir, + mappings: &IndexSet, +) -> miette::Result<(IndexSet, IndexSet)> { + // Get all paths to the binaries from the scripts in the bin directory. + let locally_exposed = bin_dir.files().await?; + let executable_paths = futures::future::join_all(locally_exposed.iter().map(|path| { + let path = path.clone(); + async move { + extract_executable_from_script(&path) + .await + .ok() + .map(|exec| (path, exec)) + } + })) + .await + .into_iter() + .flatten() + .collect_vec(); + + // Filter out all binaries that are related to the environment + let related = executable_paths + .into_iter() + .filter(|(_, exec)| exec.starts_with(env_dir.path())) + .collect_vec(); + + fn match_mapping(mapping: &Mapping, exposed: &Path, executable: &Path) -> bool { + executable_from_path(exposed) == mapping.exposed_name().to_string() + && executable_from_path(executable) == mapping.executable_name() + } + + // Get all related expose scripts not required by the environment manifest + let to_remove = related + .iter() + .filter_map(|(exposed, executable)| { + if mappings + .iter() + .any(|mapping| match_mapping(mapping, exposed, executable)) + { + None + } else { + Some(exposed) + } + }) + .cloned() + .collect::>(); + + // Get all required exposed binaries that are not yet exposed + let to_add = mappings + .iter() + .filter_map(|mapping| { + if related + .iter() + .any(|(exposed, executable)| match_mapping(mapping, exposed, executable)) + { + None + } else { + Some(mapping.exposed_name().clone()) + } + }) + .collect::>(); + + Ok((to_remove, to_add)) +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + use std::str::FromStr; + use tempfile::tempdir; + + #[tokio::test] + async fn test_create() { + // Create a temporary directory + let temp_dir = tempdir().unwrap(); + + // Set the env root to the temporary directory + let env_root = EnvRoot::new(temp_dir.path().to_owned()).unwrap(); + + // Define a test environment name + let environment_name = &EnvironmentName::from_str("test-env").unwrap(); + + // Create a new binary env dir + let bin_env_dir = EnvDir::from_env_root(env_root, environment_name) + .await + .unwrap(); + + // Verify that the directory was created + assert!(bin_env_dir.path().exists()); + assert!(bin_env_dir.path().is_dir()); + } + + #[tokio::test] + async fn test_find_package_record() { + // Get meta file from test data folder relative to the current file + let dummy_conda_meta_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src") + .join("global") + .join("test_data") + .join("conda-meta"); + // Find the package record + let records = find_package_records(&dummy_conda_meta_path).await.unwrap(); + + // Verify that the package record was found + assert!(records + .iter() + .any(|rec| rec.repodata_record.package_record.name.as_normalized() == "python")); + } + + #[test] + fn test_channel_url_to_prioritized_channel() { + let channel_config = ChannelConfig { + channel_alias: Url::from_str("https://conda.anaconda.org").unwrap(), + root_dir: PathBuf::from("/tmp"), + }; + // Same host as alias + let channel = "https://conda.anaconda.org/conda-forge"; + let prioritized_channel = + channel_url_to_prioritized_channel(channel, &channel_config).unwrap(); + assert_eq!( + PrioritizedChannel::from(NamedChannelOrUrl::from_str("conda-forge").unwrap()), + prioritized_channel + ); + + // Different host + let channel = "https://prefix.dev/conda-forge"; + let prioritized_channel = + channel_url_to_prioritized_channel(channel, &channel_config).unwrap(); + assert_eq!( + PrioritizedChannel::from( + NamedChannelOrUrl::from_str("https://prefix.dev/conda-forge").unwrap() + ), + prioritized_channel + ); + + // File URL + let channel = "file:///C:/Users/user/channel/output"; + let prioritized_channel = + channel_url_to_prioritized_channel(channel, &channel_config).unwrap(); + assert_eq!( + PrioritizedChannel::from( + NamedChannelOrUrl::from_str("file:///C:/Users/user/channel/output").unwrap() + ), + prioritized_channel + ); + } + + #[rstest] + #[case("python3.9.1")] + #[case("python3.9")] + #[case("python3")] + #[case("python")] + fn test_executable_script_path(#[case] exposed_name: &str) { + let path = PathBuf::from("/home/user/.pixi/bin"); + let bin_dir = BinDir(path.clone()); + let exposed_name = ExposedName::from_str(exposed_name).unwrap(); + let executable_script_path = bin_dir.executable_script_path(&exposed_name); + + if cfg!(windows) { + let expected = format!("{}.bat", exposed_name); + assert_eq!(executable_script_path, path.join(expected)); + } else { + assert_eq!(executable_script_path, path.join(exposed_name.to_string())); + } + } + + #[tokio::test] + async fn test_get_expose_scripts_sync_status() { + let tmp_home_dir = tempfile::tempdir().unwrap(); + let tmp_home_dir_path = tmp_home_dir.path().to_path_buf(); + let env_root = EnvRoot::new(tmp_home_dir_path.clone()).unwrap(); + let env_name = EnvironmentName::from_str("test").unwrap(); + let env_dir = EnvDir::from_env_root(env_root, &env_name).await.unwrap(); + let bin_dir = BinDir::new(tmp_home_dir_path.clone()).unwrap(); + + // Test empty + let exposed = IndexSet::new(); + let (to_remove, to_add) = get_expose_scripts_sync_status(&bin_dir, &env_dir, &exposed) + .await + .unwrap(); + assert!(to_remove.is_empty()); + assert!(to_add.is_empty()); + + // Test with exposed + let mut exposed = IndexSet::new(); + exposed.insert(Mapping::new( + ExposedName::from_str("test").unwrap(), + "test".to_string(), + )); + let (to_remove, to_add) = get_expose_scripts_sync_status(&bin_dir, &env_dir, &exposed) + .await + .unwrap(); + assert!(to_remove.is_empty()); + assert_eq!(to_add.len(), 1); + + // Add a script to the bin directory + let script_path = if cfg!(windows) { + bin_dir.path().join("test.bat") + } else { + bin_dir.path().join("test") + }; + + #[cfg(windows)] + { + let script = format!( + r#" + @"{}" %* + "#, + env_dir + .path() + .join("bin") + .join("test.exe") + .to_string_lossy() + ); + tokio_fs::write(&script_path, script).await.unwrap(); + } + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + + let script = format!( + r#"#!/bin/sh + "{}" "$@" + "#, + env_dir.path().join("bin").join("test").to_string_lossy() + ); + tokio_fs::write(&script_path, script).await.unwrap(); + // Set the file permissions to make it executable + let metadata = tokio_fs::metadata(&script_path).await.unwrap(); + let mut permissions = metadata.permissions(); + permissions.set_mode(0o755); // rwxr-xr-x + tokio_fs::set_permissions(&script_path, permissions) + .await + .unwrap(); + }; + + let (to_remove, to_add) = get_expose_scripts_sync_status(&bin_dir, &env_dir, &exposed) + .await + .unwrap(); + assert!(to_remove.is_empty()); + assert!(to_add.is_empty()); + + // Test to_remove + let (to_remove, to_add) = + get_expose_scripts_sync_status(&bin_dir, &env_dir, &IndexSet::new()) + .await + .unwrap(); + assert_eq!(to_remove.len(), 1); + assert!(to_add.is_empty()); + } +} diff --git a/src/global/install.rs b/src/global/install.rs new file mode 100644 index 000000000..e9156f697 --- /dev/null +++ b/src/global/install.rs @@ -0,0 +1,515 @@ +use super::{EnvDir, EnvironmentName, ExposedName, StateChanges}; +use crate::{ + global::{BinDir, StateChange}, + prefix::Prefix, +}; +use fs_err::tokio as tokio_fs; +use indexmap::{IndexMap, IndexSet}; +use itertools::Itertools; +use miette::IntoDiagnostic; +use once_cell::sync::Lazy; +use pixi_utils::executable_from_path; +use rattler_conda_types::{ + MatchSpec, Matches, PackageName, ParseStrictness, Platform, RepoDataRecord, +}; +use rattler_shell::{ + activation::{ActivationVariables, Activator, PathModificationBehavior}, + shell::{Shell, ShellEnum}, +}; +use regex::Regex; +use std::path::Path; +use std::{collections::HashMap, path::PathBuf, str::FromStr}; + +/// Maps an entry point in the environment to a concrete `ScriptExecMapping`. +/// +/// This function takes an entry point and a list of executable names and paths, +/// and returns a `ScriptExecMapping` that contains the path to the script and +/// the original executable. +/// # Returns +/// +/// A `miette::Result` containing the `ScriptExecMapping` if the entry point is +/// found, or an error if it is not. +/// +/// # Errors +/// +/// Returns an error if the entry point is not found in the list of executable names. +pub(crate) fn script_exec_mapping<'a>( + exposed_name: &ExposedName, + entry_point: &str, + mut executables: impl Iterator, + bin_dir: &BinDir, + env_dir: &EnvDir, +) -> miette::Result { + executables + .find(|(executable_name, _)| *executable_name == entry_point) + .map(|(_, executable_path)| ScriptExecMapping { + global_script_path: bin_dir.executable_script_path(exposed_name), + original_executable: executable_path.clone(), + }) + .ok_or_else(|| { + miette::miette!( + "Couldn't find executable {entry_point} in {}, found these executables: {:?}", + env_dir.path().display(), + executables.map(|(name, _)| name).collect_vec() + ) + }) +} + +/// Create the environment activation script +pub(crate) fn create_activation_script( + prefix: &Prefix, + shell: ShellEnum, +) -> miette::Result { + let activator = + Activator::from_path(prefix.root(), shell, Platform::current()).into_diagnostic()?; + let result = activator + .activation(ActivationVariables { + conda_prefix: None, + path: None, + path_modification_behavior: PathModificationBehavior::Prepend, + }) + .into_diagnostic()?; + + // Add a shebang on unix based platforms + let script = if cfg!(unix) { + format!("#!/bin/sh\n{}", result.script.contents().into_diagnostic()?) + } else { + result.script.contents().into_diagnostic()? + }; + + Ok(script) +} + +/// Mapping from the global script location to an executable in a package +/// environment . +#[derive(Debug)] +pub struct ScriptExecMapping { + pub global_script_path: PathBuf, + pub original_executable: PathBuf, +} + +/// Returns the string to add for all arguments passed to the script +fn get_catch_all_arg(shell: &ShellEnum) -> &str { + match shell { + ShellEnum::CmdExe(_) => "%*", + ShellEnum::PowerShell(_) => "@args", + _ => "\"$@\"", + } +} + +/// Create the executable scripts by modifying the activation script +/// to activate the environment and run the executable. +pub(crate) async fn create_executable_scripts( + mapped_executables: &[ScriptExecMapping], + prefix: &Prefix, + shell: &ShellEnum, + activation_script: String, + env_name: &EnvironmentName, +) -> miette::Result { + enum AddedOrChanged { + Unchanged, + Added, + Changed, + } + + let mut state_changes = StateChanges::default(); + + for ScriptExecMapping { + global_script_path, + original_executable, + } in mapped_executables + { + let mut script = activation_script.clone(); + shell + .run_command( + &mut script, + [ + format!( + "\"{}\"", + prefix.root().join(original_executable).to_string_lossy() + ) + .as_str(), + get_catch_all_arg(shell), + ], + ) + .expect("should never fail"); + + if matches!(shell, ShellEnum::CmdExe(_)) { + // wrap the script contents in `@echo off` and `setlocal` to prevent echoing the + // script and to prevent leaking environment variables into the + // parent shell (e.g. PATH would grow longer and longer) + script = format!( + "@echo off\nsetlocal\n{}\nset exitcode=%ERRORLEVEL%\nendlocal\nexit %exitcode%", + script.trim() + ); + } + + let added_or_changed = if global_script_path.exists() { + match tokio_fs::read_to_string(global_script_path).await { + Ok(previous_script) if previous_script != script => AddedOrChanged::Changed, + Ok(_) => AddedOrChanged::Unchanged, + Err(_) => AddedOrChanged::Changed, + } + } else { + AddedOrChanged::Added + }; + + if matches!( + added_or_changed, + AddedOrChanged::Changed | AddedOrChanged::Added + ) { + tokio_fs::write(&global_script_path, script) + .await + .into_diagnostic()?; + } + + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + std::fs::set_permissions(global_script_path, std::fs::Permissions::from_mode(0o755)) + .into_diagnostic()?; + } + + let executable_name = executable_from_path(global_script_path); + let exposed_name = ExposedName::from_str(&executable_name)?; + match added_or_changed { + AddedOrChanged::Unchanged => {} + AddedOrChanged::Added => { + state_changes.insert_change(env_name, StateChange::AddedExposed(exposed_name)); + } + AddedOrChanged::Changed => { + state_changes.insert_change(env_name, StateChange::UpdatedExposed(exposed_name)); + } + } + } + Ok(state_changes) +} + +/// Extracts the executable path from a script file. +/// +/// This function reads the content of the script file and attempts to extract +/// the path of the executable it references. It is used to determine +/// the actual binary path from a wrapper script. +pub(crate) async fn extract_executable_from_script(script: &Path) -> miette::Result { + // Read the script file into a string + let script_content = tokio_fs::read_to_string(script).await.into_diagnostic()?; + + // Compile the regex pattern + #[cfg(unix)] + const PATTERN: &str = r#""([^"]+)" "\$@""#; + // The pattern includes `"?` to also find old pixi global installations. + #[cfg(windows)] + const PATTERN: &str = r#"@"?([^"]+)"? %/*"#; + static RE: Lazy = Lazy::new(|| Regex::new(PATTERN).expect("Failed to compile regex")); + + // Apply the regex to the script content + if let Some(caps) = RE.captures(&script_content) { + if let Some(matched) = caps.get(1) { + return Ok(PathBuf::from(matched.as_str())); + } + } + tracing::debug!( + "Failed to extract executable path from script {}", + script_content + ); + + // Return an error if the executable path couldn't be extracted + miette::bail!( + "Failed to extract executable path from script {}", + script.display() + ) +} + +/// Warn user on dangerous package installations, interactive yes no prompt +#[allow(unused)] +pub(crate) fn prompt_user_to_continue( + packages: &IndexMap, +) -> miette::Result { + let dangerous_packages = HashMap::from([ + ("pixi", "Installing `pixi` globally doesn't work as expected.\nUse `pixi self-update` to update pixi and `pixi self-update --version x.y.z` for a specific version."), + ("pip", "Installing `pip` with `pixi global` won't make pip-installed packages globally available.\nInstead, use a pixi project and add PyPI packages with `pixi add --pypi`, which is recommended. Alternatively, `pixi add pip` and use it within the project.") + ]); + + // Check if any of the packages are dangerous, and prompt the user to ask if + // they want to continue, including the advice. + for (name, _spec) in packages { + if let Some(advice) = dangerous_packages.get(&name.as_normalized()) { + let prompt = format!( + "{}\nDo you want to continue?", + console::style(advice).yellow() + ); + if !dialoguer::Confirm::new() + .with_prompt(prompt) + .default(false) + .show_default(true) + .interact() + .into_diagnostic()? + { + return Ok(false); + } + } + } + + Ok(true) +} + +/// Checks if the local environment matches the given specifications. +/// +/// This function verifies that all the given specifications are present in the +/// local environment's prefix records and that there are no extra entries in +/// the prefix records that do not match any of the specifications. +pub(crate) fn local_environment_matches_spec( + prefix_records: Vec, + specs: &IndexSet, + platform: Option, +) -> bool { + // Check whether all specs in the manifest are present in the installed + // environment + let specs_in_manifest_are_present = specs + .iter() + .all(|spec| prefix_records.iter().any(|record| spec.matches(record))); + + if !specs_in_manifest_are_present { + tracing::debug!("Not all specs in the manifest are present in the environment"); + return false; + } + + // Check whether all packages in the installed environment have the correct + // platform + if let Some(platform) = platform { + let platform_specs_match_env = prefix_records.iter().all(|record| { + let Ok(package_platform) = Platform::from_str(&record.package_record.subdir) else { + return true; + }; + + match package_platform { + Platform::NoArch => true, + p if p == platform => true, + _ => false, + } + }); + + if !platform_specs_match_env { + tracing::debug!("Not all packages in the environment have the correct platform"); + return false; + } + } + + // Prune dependencies from the repodata that are valid for the requested specs + fn prune_dependencies( + mut remaining_prefix_records: Vec, + matched_record: &RepoDataRecord, + ) -> Vec { + let mut work_queue = Vec::from([matched_record.as_ref().clone()]); + + while let Some(current_record) = work_queue.pop() { + let dependencies = ¤t_record.depends; + for dependency in dependencies { + let Ok(match_spec) = MatchSpec::from_str(dependency, ParseStrictness::Lenient) + else { + continue; + }; + let Some(index) = remaining_prefix_records + .iter() + .position(|record| match_spec.matches(&record.package_record)) + else { + continue; + }; + + let matched_record = remaining_prefix_records.remove(index).as_ref().clone(); + work_queue.push(matched_record); + } + } + + remaining_prefix_records + } + + // Process each spec and remove matched entries and their dependencies + let remaining_prefix_records = specs.iter().fold(prefix_records, |mut acc, spec| { + let Some(index) = acc.iter().position(|record| spec.matches(record.as_ref())) else { + return acc; + }; + let matched_record = acc.swap_remove(index); + prune_dependencies(acc, &matched_record) + }); + + // If there are no remaining prefix records, then this means that + // the environment doesn't contain records that don't match the manifest + if !remaining_prefix_records.is_empty() { + tracing::debug!( + "Environment contains extra entries that don't match the manifest: {:?}", + remaining_prefix_records + ); + false + } else { + true + } +} + +#[cfg(test)] +mod tests { + use fs_err as fs; + use rattler_conda_types::{MatchSpec, ParseStrictness, Platform}; + use rattler_lock::LockFile; + use rstest::{fixture, rstest}; + + use super::*; + + #[fixture] + fn ripgrep_specs() -> IndexSet { + IndexSet::from([MatchSpec::from_str("ripgrep=14.1.0", ParseStrictness::Strict).unwrap()]) + } + + #[fixture] + fn ripgrep_records() -> Vec { + LockFile::from_str(include_str!("./test_data/lockfiles/ripgrep.lock")) + .unwrap() + .default_environment() + .unwrap() + .conda_repodata_records_for_platform(Platform::Linux64) + .unwrap() + .unwrap() + } + + #[fixture] + fn ripgrep_bat_specs() -> IndexSet { + IndexSet::from([ + MatchSpec::from_str("ripgrep=14.1.0", ParseStrictness::Strict).unwrap(), + MatchSpec::from_str("bat=0.24.0", ParseStrictness::Strict).unwrap(), + ]) + } + + #[fixture] + fn ripgrep_bat_records() -> Vec { + LockFile::from_str(include_str!("./test_data/lockfiles/ripgrep_bat.lock")) + .unwrap() + .default_environment() + .unwrap() + .conda_repodata_records_for_platform(Platform::Linux64) + .unwrap() + .unwrap() + } + + #[rstest] + fn test_local_environment_matches_spec( + ripgrep_records: Vec, + ripgrep_specs: IndexSet, + ) { + assert!(local_environment_matches_spec( + ripgrep_records, + &ripgrep_specs, + None + )); + } + + #[rstest] + fn test_local_environment_misses_entries_for_specs( + mut ripgrep_records: Vec, + ripgrep_specs: IndexSet, + ) { + // Remove last repodata record + ripgrep_records.pop(); + + assert!(!local_environment_matches_spec( + ripgrep_records, + &ripgrep_specs, + None + )); + } + + #[rstest] + fn test_local_environment_has_too_many_entries_to_match_spec( + ripgrep_bat_records: Vec, + ripgrep_specs: IndexSet, + ripgrep_bat_specs: IndexSet, + ) { + assert!(!local_environment_matches_spec( + ripgrep_bat_records.clone(), + &ripgrep_specs, + None + ), "The function needs to detect that records coming from ripgrep and bat don't match ripgrep alone."); + + assert!( + local_environment_matches_spec(ripgrep_bat_records, &ripgrep_bat_specs, None), + "The records and specs match and the function should return `true`." + ); + } + + #[rstest] + fn test_local_environment_matches_given_platform( + ripgrep_records: Vec, + ripgrep_specs: IndexSet, + ) { + assert!( + local_environment_matches_spec( + ripgrep_records, + &ripgrep_specs, + Some(Platform::Linux64) + ), + "The records contains only linux-64 entries" + ); + } + + #[rstest] + fn test_local_environment_doesnt_match_given_platform( + ripgrep_records: Vec, + ripgrep_specs: IndexSet, + ) { + assert!( + !local_environment_matches_spec(ripgrep_records, &ripgrep_specs, Some(Platform::Win64),), + "The record contains linux-64 entries, so the function should always return `false`" + ); + } + + #[cfg(windows)] + #[tokio::test] + async fn test_extract_executable_from_script_windows() { + let script_without_quote = r#" +@SET "PATH=C:\Users\USER\.pixi/envs\hyperfine\bin:%PATH%" +@SET "CONDA_PREFIX=C:\Users\USER\.pixi/envs\hyperfine" +@C:\Users\USER\.pixi/envs\hyperfine\bin/hyperfine.exe %* +"#; + let script_path = Path::new("hyperfine.bat"); + let tempdir = tempfile::tempdir().unwrap(); + let script_path = tempdir.path().join(script_path); + fs::write(&script_path, script_without_quote).unwrap(); + let executable_path = extract_executable_from_script(&script_path).await.unwrap(); + assert_eq!( + executable_path, + Path::new("C:\\Users\\USER\\.pixi/envs\\hyperfine\\bin/hyperfine.exe") + ); + + let script_with_quote = r#" +@SET "PATH=C:\Users\USER\.pixi/envs\python\bin;%PATH%" +@SET "CONDA_PREFIX=C:\Users\USER\.pixi/envs\python" +@"C:\Users\USER\.pixi\envs\python\Scripts/pydoc.exe" %* +"#; + let script_path = Path::new("pydoc.bat"); + let script_path = tempdir.path().join(script_path); + fs::write(&script_path, script_with_quote).unwrap(); + let executable_path = extract_executable_from_script(&script_path).await.unwrap(); + assert_eq!( + executable_path, + Path::new("C:\\Users\\USER\\.pixi\\envs\\python\\Scripts/pydoc.exe") + ); + } + + #[cfg(unix)] + #[tokio::test] + async fn test_extract_executable_from_script_unix() { + let script = r#"#!/bin/sh +export PATH="/home/user/.pixi/envs/nushell/bin:${PATH}" +export CONDA_PREFIX="/home/user/.pixi/envs/nushell" +"/home/user/.pixi/envs/nushell/bin/nu" "$@" +"#; + let script_path = Path::new("nu"); + let tempdir = tempfile::tempdir().unwrap(); + let script_path = tempdir.path().join(script_path); + fs::write(&script_path, script).unwrap(); + let executable_path = extract_executable_from_script(&script_path).await.unwrap(); + assert_eq!( + executable_path, + Path::new("/home/user/.pixi/envs/nushell/bin/nu") + ); + } +} diff --git a/src/global/mod.rs b/src/global/mod.rs new file mode 100644 index 000000000..2491acdda --- /dev/null +++ b/src/global/mod.rs @@ -0,0 +1,54 @@ +pub(crate) mod common; +pub(crate) mod install; +pub(crate) mod project; + +pub(crate) use common::{BinDir, EnvDir, EnvRoot, StateChange, StateChanges}; +pub(crate) use install::extract_executable_from_script; +pub(crate) use project::{EnvironmentName, ExposedName, Mapping, Project}; + +use crate::prefix::Prefix; +use rattler_conda_types::PrefixRecord; +use std::path::{Path, PathBuf}; + +/// Find the executable scripts within the specified package installed in this +/// conda prefix. +fn find_executables(prefix: &Prefix, prefix_package: &PrefixRecord) -> Vec { + prefix_package + .files + .iter() + .filter(|&relative_path| is_executable(prefix, relative_path)) + .cloned() + .collect() +} + +fn is_executable(prefix: &Prefix, relative_path: &Path) -> bool { + // Check if the file is in a known executable directory. + let binary_folders = if cfg!(windows) { + &([ + "", + "Library/mingw-w64/bin/", + "Library/usr/bin/", + "Library/bin/", + "Scripts/", + "bin/", + ][..]) + } else { + &(["bin"][..]) + }; + + let parent_folder = match relative_path.parent() { + Some(dir) => dir, + None => return false, + }; + + if !binary_folders + .iter() + .any(|bin_path| Path::new(bin_path) == parent_folder) + { + return false; + } + + // Check if the file is executable + let absolute_path = prefix.root().join(relative_path); + is_executable::is_executable(absolute_path) +} diff --git a/src/global/project/environment.rs b/src/global/project/environment.rs new file mode 100644 index 000000000..2d14967ff --- /dev/null +++ b/src/global/project/environment.rs @@ -0,0 +1,147 @@ +use crate::global::install::local_environment_matches_spec; +use crate::global::EnvDir; +use crate::prefix::Prefix; +use console::StyledObject; +use fancy_display::FancyDisplay; +use indexmap::IndexSet; +use itertools::Itertools; +use miette::Diagnostic; +use pixi_consts::consts; +use rattler_conda_types::{MatchSpec, Platform}; +use regex::Regex; +use serde::{self, Deserialize, Deserializer, Serialize}; +use std::{fmt, str::FromStr}; +use thiserror::Error; + +/// Represents the name of an environment. +#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize)] +pub(crate) struct EnvironmentName(String); + +impl EnvironmentName { + /// Returns the name of the environment. + pub fn as_str(&self) -> &str { + &self.0 + } +} + +impl fmt::Display for EnvironmentName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl PartialEq for EnvironmentName { + fn eq(&self, other: &str) -> bool { + self.as_str() == other + } +} + +impl<'de> Deserialize<'de> for EnvironmentName { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let name = String::deserialize(deserializer)?; + name.parse().map_err(serde::de::Error::custom) + } +} + +impl FancyDisplay for EnvironmentName { + fn fancy_display(&self) -> StyledObject<&str> { + consts::ENVIRONMENT_STYLE.apply_to(self.as_str()) + } +} + +impl FromStr for EnvironmentName { + type Err = ParseEnvironmentNameError; + fn from_str(s: &str) -> Result { + static REGEX: std::sync::OnceLock = std::sync::OnceLock::new(); + let regex = REGEX + .get_or_init(|| Regex::new(r"^[a-z0-9-_]+$").expect("Regex should be able to compile")); + + if !regex.is_match(s) { + // Return an error if the string doesn't match the regex + return Err(ParseEnvironmentNameError { + attempted_parse: s.to_string(), + }); + } + Ok(EnvironmentName(s.to_string())) + } +} + +/// Represents an error that occurs when parsing an environment name. +/// +/// This error is returned when a string fails to be parsed as an environment name. +#[derive(Debug, Clone, Error, Diagnostic, PartialEq)] +#[error("Failed to parse environment name '{attempted_parse}', please use only lowercase letters, numbers, dashes and underscores")] +pub struct ParseEnvironmentNameError { + /// The string that was attempted to be parsed. + pub attempted_parse: String, +} + +/// Checks if the manifest is in sync with the locally installed environment and binaries. +/// Returns `true` if the environment is in sync, `false` otherwise. +pub(crate) async fn environment_specs_in_sync( + env_dir: &EnvDir, + specs: &IndexSet, + platform: Option, +) -> miette::Result { + let prefix = Prefix::new(env_dir.path()); + + let repodata_records = prefix + .find_installed_packages(Some(50)) + .await? + .into_iter() + .map(|r| r.repodata_record) + .collect_vec(); + + if !local_environment_matches_spec(repodata_records, specs, platform) { + return Ok(false); + } + Ok(true) +} + +#[cfg(test)] +mod tests { + + use super::*; + use crate::global::EnvRoot; + use fs_err::tokio as tokio_fs; + use rattler_conda_types::ParseStrictness; + use std::path::PathBuf; + + #[tokio::test] + async fn test_environment_specs_in_sync() { + let home = tempfile::tempdir().unwrap(); + let env_root = EnvRoot::new(home.into_path()).unwrap(); + let env_name = EnvironmentName::from_str("test").unwrap(); + let env_dir = EnvDir::from_env_root(env_root, &env_name).await.unwrap(); + + // Test empty + let specs = IndexSet::new(); + let result = environment_specs_in_sync(&env_dir, &specs, None) + .await + .unwrap(); + assert!(result); + + // Test with spec + let mut specs = IndexSet::new(); + specs.insert(MatchSpec::from_str("_r-mutex==1.0.1", ParseStrictness::Strict).unwrap()); + // Copy from test data folder relative to this file to the conda-meta in environment directory + let file_name = "_r-mutex-1.0.1-anacondar_1.json"; + let target_dir = PathBuf::from(env_dir.path()).join("conda-meta"); + tokio_fs::create_dir_all(&target_dir).await.unwrap(); + let test_data_target = target_dir.join(file_name); + let test_data_source = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("src/global/test_data/conda-meta") + .join(file_name); + tokio_fs::copy(test_data_source, test_data_target) + .await + .unwrap(); + + let result = environment_specs_in_sync(&env_dir, &specs, None) + .await + .unwrap(); + assert!(result); + } +} diff --git a/src/global/project/manifest.rs b/src/global/project/manifest.rs new file mode 100644 index 000000000..396e5be6d --- /dev/null +++ b/src/global/project/manifest.rs @@ -0,0 +1,962 @@ +use std::fmt; +use std::path::{Path, PathBuf}; +use std::str::FromStr; + +use fancy_display::FancyDisplay; +use fs_err as fs; +use fs_err::tokio as tokio_fs; +use indexmap::IndexSet; +use miette::IntoDiagnostic; + +use crate::global::project::ParsedEnvironment; +use pixi_config::Config; +use pixi_manifest::{PrioritizedChannel, TomlManifest}; +use pixi_spec::PixiSpec; +use rattler_conda_types::{ChannelConfig, MatchSpec, NamedChannelOrUrl, Platform}; +use serde::{Deserialize, Serialize}; +use toml_edit::{DocumentMut, Item}; + +use super::parsed_manifest::{ManifestParsingError, ManifestVersion, ParsedManifest}; +use super::{EnvironmentName, ExposedName, MANIFEST_DEFAULT_NAME}; + +/// Handles the global project's manifest file. +/// This struct is responsible for reading, parsing, editing, and saving the +/// manifest. It encapsulates all logic related to the manifest's TOML format +/// and structure. The manifest data is represented as a [`ParsedManifest`] +/// struct for easy manipulation. +#[derive(Debug, Clone, Default)] +pub struct Manifest { + /// The path to the manifest file + pub path: PathBuf, + + /// Editable toml document + pub document: TomlManifest, + + /// The parsed manifest + pub parsed: ParsedManifest, +} + +impl Manifest { + /// Creates a new manifest from a path + pub fn from_path(path: impl AsRef) -> miette::Result { + let manifest_path = dunce::canonicalize(path.as_ref()).into_diagnostic()?; + let contents = fs::read_to_string(path.as_ref()).into_diagnostic()?; + Self::from_str(manifest_path.as_ref(), contents) + } + + /// Creates a new manifest from a string + pub fn from_str(manifest_path: &Path, contents: impl Into) -> miette::Result { + let contents = contents.into(); + let parsed = ParsedManifest::from_toml_str(&contents); + + let (manifest, document) = match parsed.and_then(|manifest| { + contents + .parse::() + .map(|doc| (manifest, doc)) + .map_err(ManifestParsingError::from) + }) { + Ok(result) => result, + Err(e) => e.to_fancy(MANIFEST_DEFAULT_NAME, &contents, manifest_path)?, + }; + + let manifest = Self { + path: manifest_path.to_path_buf(), + + document: TomlManifest::new(document), + parsed: manifest, + }; + + Ok(manifest) + } + + /// Adds an environment to the manifest + pub fn add_environment( + &mut self, + env_name: &EnvironmentName, + channels: Option>, + ) -> miette::Result<()> { + let channels = channels + .filter(|c| !c.is_empty()) + .unwrap_or_else(|| Config::load_global().default_channels()); + + // Update self.parsed + if self.parsed.envs.get(env_name).is_some() { + miette::bail!("Environment {} already exists.", env_name.fancy_display()); + } + self.parsed.envs.insert( + env_name.clone(), + ParsedEnvironment::new(channels.clone().into_iter().map(PrioritizedChannel::from)), + ); + + // Update self.document + let channels_array = self + .document + .get_or_insert_toml_array(&format!("envs.{env_name}"), "channels")?; + for channel in channels { + channels_array.push(channel.as_str()); + } + + tracing::debug!( + "Added environment {} to toml document", + env_name.fancy_display() + ); + Ok(()) + } + + /// Removes a specific environment from the manifest + pub fn remove_environment(&mut self, env_name: &EnvironmentName) -> miette::Result<()> { + // Update self.parsed + self.parsed.envs.shift_remove(env_name).ok_or_else(|| { + miette::miette!("Environment {} doesn't exist.", env_name.fancy_display()) + })?; + + // Update self.document + self.document + .get_or_insert_nested_table("envs")? + .remove(env_name.as_str()) + .ok_or_else(|| { + miette::miette!("Environment {} doesn't exist.", env_name.fancy_display()) + })?; + + tracing::debug!( + "Removed environment {} from toml document", + env_name.fancy_display() + ); + Ok(()) + } + + /// Adds a dependency to the manifest + pub fn add_dependency( + &mut self, + env_name: &EnvironmentName, + spec: &MatchSpec, + channel_config: &ChannelConfig, + ) -> miette::Result<()> { + // Determine the name of the package to add + let (Some(name), spec) = spec.clone().into_nameless() else { + miette::bail!("pixi doesn't support wildcard dependencies") + }; + let spec = PixiSpec::from_nameless_matchspec(spec, channel_config); + + // Update self.parsed + self.parsed + .envs + .get_mut(env_name) + .ok_or_else(|| { + miette::miette!("Environment {} doesn't exist.", env_name.fancy_display()) + })? + .dependencies + .insert(name.clone(), spec.clone()); + + // Update self.document + self.document.insert_into_inline_table( + &format!("envs.{env_name}.dependencies"), + name.clone().as_normalized(), + spec.clone().to_toml_value(), + )?; + + tracing::debug!( + "Added dependency {}={} to toml document for environment {}", + name.as_normalized(), + spec.to_toml_value().to_string(), + env_name.fancy_display() + ); + Ok(()) + } + + /// Removes a dependency from the manifest + pub fn remove_dependency( + &mut self, + env_name: &EnvironmentName, + spec: &MatchSpec, + ) -> miette::Result<()> { + // Determine the name of the package to add + let (Some(name), _spec) = spec.clone().into_nameless() else { + miette::bail!("pixi does not support wildcard dependencies") + }; + + // Update self.parsed + self.parsed + .envs + .get_mut(env_name) + .ok_or_else(|| { + miette::miette!("Environment {} doesn't exist.", env_name.fancy_display()) + })? + .dependencies + .swap_remove(&name) + .ok_or(miette::miette!( + "Dependency {} not found in {}", + console::style(name.as_normalized()).green(), + env_name.fancy_display() + ))?; + + // Update self.document + self.document + .get_or_insert_nested_table(&format!("envs.{env_name}.dependencies"))? + .remove(name.as_normalized()); + + tracing::debug!( + "Removed dependency {} to toml document for environment {}", + console::style(name.as_normalized()).green(), + env_name.fancy_display() + ); + Ok(()) + } + + /// Sets the platform of a specific environment in the manifest + pub fn set_platform( + &mut self, + env_name: &EnvironmentName, + platform: Platform, + ) -> miette::Result<()> { + // Ensure the environment exists + if !self.parsed.envs.contains_key(env_name) { + miette::bail!("Environment {} doesn't exist", env_name.fancy_display()); + } + + // Update self.parsed + self.parsed + .envs + .get_mut(env_name) + .ok_or_else(|| { + miette::miette!("Can't find environment {} yet", env_name.fancy_display()) + })? + .platform + .replace(platform); + + // Update self.document + self.document + .get_or_insert_nested_table(&format!("envs.{env_name}"))? + .insert( + "platform", + Item::Value(toml_edit::Value::from(platform.to_string())), + ); + + tracing::debug!( + "Set platform {} for environment {} in toml document", + platform, + env_name + ); + Ok(()) + } + + #[allow(dead_code)] + /// Adds a channel to the manifest + pub fn add_channel( + &mut self, + env_name: &EnvironmentName, + channel: &NamedChannelOrUrl, + ) -> miette::Result<()> { + // Ensure the environment exists + if !self.parsed.envs.contains_key(env_name) { + miette::bail!("Environment {} doesn't exist", env_name.fancy_display()); + } + + // Update self.parsed + let env = self + .parsed + .envs + .get_mut(env_name) + .ok_or_else(|| miette::miette!("This should be impossible"))?; + env.channels + .insert(PrioritizedChannel::from(channel.clone())); + + // Update self.document + let channels_array = self + .document + .get_or_insert_nested_table(&format!("envs.{env_name}"))? + .entry("channels") + .or_insert_with(|| toml_edit::Item::Value(toml_edit::Value::Array(Default::default()))) + .as_array_mut() + .ok_or_else(|| miette::miette!("Expected an array for channels"))?; + + // Convert existing TOML array to a IndexSet to ensure uniqueness + let mut existing_channels: IndexSet = channels_array + .iter() + .filter_map(|item| item.as_str().map(|s| s.to_string())) + .collect(); + + // Add the new channel to the HashSet + existing_channels.insert(channel.to_string()); + + // Reinsert unique channels + *channels_array = existing_channels.iter().collect(); + + tracing::debug!("Added channel {channel} for environment {env_name} in toml document"); + Ok(()) + } + + /// Matches an exposed name to its corresponding environment name. + pub fn match_exposed_name_to_environment( + &self, + exposed_name: &ExposedName, + ) -> miette::Result { + for (env_name, env) in &self.parsed.envs { + for mapping in &env.exposed { + if mapping.exposed_name == *exposed_name { + return Ok(env_name.clone()); + } + } + } + Err(miette::miette!( + "Exposed name {} not found in any environment", + exposed_name.fancy_display() + )) + } + + /// Checks if an exposed name already exists in other environments + pub fn exposed_name_already_exists_in_other_envs( + &self, + exposed_name: &ExposedName, + env_name: &EnvironmentName, + ) -> bool { + self.parsed + .envs + .iter() + .filter_map(|(name, env)| if name != env_name { Some(env) } else { None }) + .flat_map(|env| env.exposed.iter()) + .any(|mapping| mapping.exposed_name == *exposed_name) + } + + /// Adds exposed mapping to the manifest + pub fn add_exposed_mapping( + &mut self, + env_name: &EnvironmentName, + mapping: &Mapping, + ) -> miette::Result<()> { + // Ensure the environment exists + if !self.parsed.envs.contains_key(env_name) { + miette::bail!("Environment {} doesn't exist", env_name.fancy_display()); + } + + // Ensure exposed name is unique + if self.exposed_name_already_exists_in_other_envs(&mapping.exposed_name, env_name) { + miette::bail!( + "Exposed name {} already exists", + mapping.exposed_name.fancy_display() + ); + } + + // Update self.parsed + self.parsed + .envs + .get_mut(env_name) + .ok_or_else(|| miette::miette!("This should be impossible"))? + .exposed + .insert(mapping.clone()); + + // Update self.document + self.document.insert_into_inline_table( + &format!("envs.{env_name}.exposed"), + &mapping.exposed_name.to_string(), + toml_edit::Value::from(mapping.executable_name.clone()), + )?; + + tracing::debug!("Added exposed mapping {mapping} to toml document"); + Ok(()) + } + + /// Removes exposed mapping from the manifest + pub fn remove_exposed_name( + &mut self, + env_name: &EnvironmentName, + exposed_name: &ExposedName, + ) -> miette::Result<()> { + // Ensure the environment exists + if !self.parsed.envs.contains_key(env_name) { + miette::bail!("Environment {} doesn't exist", env_name.fancy_display()); + } + let environment = self + .parsed + .envs + .get_mut(env_name) + .ok_or_else(|| miette::miette!("[envs.{env_name}] needs to exist"))?; + + // Remove exposed_name from parsed environment + environment + .exposed + .retain(|map| map.exposed_name() != exposed_name); + + // Remove from the document + self.document + .get_or_insert_nested_table(&format!("envs.{env_name}.exposed"))? + .remove(&exposed_name.to_string()) + .ok_or_else(|| miette::miette!("The exposed name {exposed_name} doesn't exist"))?; + + tracing::debug!("Removed exposed mapping {exposed_name} from toml document"); + Ok(()) + } + + /// Removes all exposed mappings for a specific environment + pub fn remove_all_exposed_mappings( + &mut self, + env_name: &EnvironmentName, + ) -> miette::Result<()> { + // Ensure the environment exists + let env = self.parsed.envs.get_mut(env_name).ok_or_else(|| { + miette::miette!("Environment {} doesn't exist", env_name.fancy_display()) + })?; + + // Clear the exposed mappings + env.exposed.clear(); + + // Update self.document + self.document + .get_or_insert_nested_table(&format!("envs.{env_name}"))? + .remove("exposed"); + + tracing::debug!( + "Removed all exposed mappings for environment {} in toml document", + env_name.fancy_display() + ); + Ok(()) + } + + /// Saves the manifest to the file system + pub async fn save(&self) -> miette::Result<()> { + let contents = { + // Ensure that version is always set when saving + let mut document = self.document.clone(); + document.get_or_insert("version", ManifestVersion::default().into()); + document.to_string() + }; + + tokio_fs::write(&self.path, contents) + .await + .into_diagnostic()?; + Ok(()) + } +} + +#[derive(Debug, Clone, Serialize, Deserialize, Hash, PartialEq, Eq)] +pub struct Mapping { + exposed_name: ExposedName, + executable_name: String, +} + +impl Mapping { + pub fn new(exposed_name: ExposedName, executable_name: String) -> Self { + Self { + exposed_name, + executable_name, + } + } + + pub fn exposed_name(&self) -> &ExposedName { + &self.exposed_name + } + + pub fn executable_name(&self) -> &str { + &self.executable_name + } +} + +impl fmt::Display for Mapping { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}={}", self.exposed_name, self.executable_name) + } +} + +impl FromStr for Mapping { + type Err = miette::Error; + + fn from_str(input: &str) -> Result { + // If we can't parse exposed_name=executable_name, assume input=input + let (exposed_name, executable_name) = input.split_once('=').unwrap_or((input, input)); + let exposed_name = ExposedName::from_str(exposed_name)?; + Ok(Mapping::new(exposed_name, executable_name.to_string())) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use indexmap::IndexSet; + use insta::assert_snapshot; + use itertools::Itertools; + use rattler_conda_types::ParseStrictness; + + use super::*; + + #[test] + fn test_add_exposed_mapping_new_env() { + let mut manifest = Manifest::default(); + let exposed_name = ExposedName::from_str("test_exposed").unwrap(); + let executable_name = "test_executable".to_string(); + let mapping = Mapping::new(exposed_name.clone(), executable_name); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + manifest.add_environment(&env_name, None).unwrap(); + + let result = manifest.add_exposed_mapping(&env_name, &mapping); + assert!(result.is_ok()); + + let expected_value = "test_executable"; + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table(&format!("envs.{}.exposed", env_name)) + .unwrap() + .get(&exposed_name.to_string()) + .unwrap() + .as_str() + .unwrap(); + assert_eq!(expected_value, actual_value); + + // Check parsed + let actual_value = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .exposed + .iter() + .find(|map| map.exposed_name() == &exposed_name) + .unwrap() + .executable_name(); + assert_eq!(expected_value, actual_value) + } + + #[test] + fn test_add_exposed_mapping_existing_env() { + let mut manifest = Manifest::default(); + let exposed_name1 = ExposedName::from_str("test_exposed1").unwrap(); + let executable_name1 = "test_executable1".to_string(); + let mapping1 = Mapping::new(exposed_name1.clone(), executable_name1); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + manifest.add_environment(&env_name, None).unwrap(); + + manifest.add_exposed_mapping(&env_name, &mapping1).unwrap(); + + let exposed_name2 = ExposedName::from_str("test_exposed2").unwrap(); + let executable_name2 = "test_executable2".to_string(); + let mapping2 = Mapping::new(exposed_name2.clone(), executable_name2); + let result = manifest.add_exposed_mapping(&env_name, &mapping2); + assert!(result.is_ok()); + + // Check document for executable1 + let expected_value1 = "test_executable1"; + let actual_value1 = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}.exposed")) + .unwrap() + .get(&exposed_name1.to_string()) + .unwrap() + .as_str() + .unwrap(); + assert_eq!(expected_value1, actual_value1); + + // Check parsed for executable1 + let actual_value1 = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .exposed + .iter() + .find(|map| map.exposed_name() == &exposed_name1) + .unwrap() + .executable_name(); + assert_eq!(expected_value1, actual_value1); + + // Check document for executable2 + let expected_value2 = "test_executable2"; + let actual_value2 = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}.exposed")) + .unwrap() + .get(&exposed_name2.to_string()) + .unwrap() + .as_str() + .unwrap(); + assert_eq!(expected_value2, actual_value2); + + // Check parsed for executable2 + let actual_value2 = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .exposed + .iter() + .find(|map| map.exposed_name() == &exposed_name2) + .unwrap() + .executable_name(); + assert_eq!(expected_value2, actual_value2); + } + + #[test] + fn test_remove_exposed_mapping() { + let mut manifest = Manifest::default(); + let exposed_name = ExposedName::from_str("test_exposed").unwrap(); + let executable_name = "test_executable".to_string(); + let mapping = Mapping::new(exposed_name.clone(), executable_name); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Add and remove mapping again + manifest.add_exposed_mapping(&env_name, &mapping).unwrap(); + manifest + .remove_exposed_name(&env_name, &exposed_name) + .unwrap(); + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}.exposed")) + .unwrap() + .get(&exposed_name.to_string()); + assert!(actual_value.is_none()); + + // Check parsed + assert!(!manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .exposed + .iter() + .any(|map| map.exposed_name() == &exposed_name)); + } + + #[test] + fn test_remove_exposed_mapping_nonexistent() { + let mut manifest = Manifest::default(); + let exposed_name = ExposedName::from_str("test_exposed").unwrap(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + // Removing an exposed name that doesn't exist should return an error + let result = manifest.remove_exposed_name(&env_name, &exposed_name); + assert!(result.is_err()) + } + + #[test] + fn test_add_environment_default_channel() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table("envs") + .unwrap() + .get(env_name.as_str()); + assert!(actual_value.is_some()); + + // Check parsed + let env = manifest.parsed.envs.get(&env_name).unwrap(); + + // Check channels + let expected_channels = Config::load_global() + .default_channels() + .into_iter() + .map(From::from) + .collect::>(); + let actual_channels = env.channels.clone(); + assert_eq!(expected_channels, actual_channels); + } + + #[test] + fn test_add_environment_given_channel() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + let channels = Vec::from([ + NamedChannelOrUrl::from_str("test-channel-1").unwrap(), + NamedChannelOrUrl::from_str("test-channel-2").unwrap(), + ]); + + // Add environment + manifest + .add_environment(&env_name, Some(channels.clone())) + .unwrap(); + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table("envs") + .unwrap() + .get(env_name.as_str()); + assert!(actual_value.is_some()); + + // Check parsed + let env = manifest.parsed.envs.get(&env_name).unwrap(); + + // Check channels + let expected_channels = channels + .into_iter() + .map(From::from) + .collect::>(); + let actual_channels = env.channels.clone(); + assert_eq!(expected_channels, actual_channels); + } + + #[test] + fn test_remove_environment() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Remove environment + manifest.remove_environment(&env_name).unwrap(); + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table("envs") + .unwrap() + .get(env_name.as_str()); + assert!(actual_value.is_none()); + + // Check parsed + let actual_value = manifest.parsed.envs.get(&env_name); + assert!(actual_value.is_none()); + } + + #[test] + fn test_remove_non_existent_environment() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("non-existent-env").unwrap(); + + // Remove non-existent environment + let result = manifest.remove_environment(&env_name); + + // This should fail + assert!(result.is_err()); + } + + #[test] + fn test_add_dependency() { + let mut manifest = Manifest::default(); + let channel_config = ChannelConfig::default_with_root_dir(std::env::current_dir().unwrap()); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + let version_match_spec = + MatchSpec::from_str("pythonic ==3.15.0", ParseStrictness::Strict).unwrap(); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Add dependency + manifest + .add_dependency(&env_name, &version_match_spec, &channel_config) + .unwrap(); + + // Check document + let actual_value = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}.dependencies")) + .unwrap() + .get(version_match_spec.name.clone().unwrap().as_normalized()); + assert!(actual_value.is_some()); + assert_eq!( + actual_value.unwrap().to_string().replace('"', ""), + version_match_spec.clone().version.unwrap().to_string() + ); + + // Check parsed + let actual_value = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .dependencies + .get(&version_match_spec.clone().name.unwrap()) + .unwrap() + .clone(); + assert_eq!( + actual_value, + PixiSpec::from_nameless_matchspec( + version_match_spec.into_nameless().1, + &channel_config + ) + ); + + // Add another dependency + let build_match_spec = MatchSpec::from_str( + "python [version='3.11.0', build=he550d4f_1_cpython]", + ParseStrictness::Strict, + ) + .unwrap(); + manifest + .add_dependency(&env_name, &build_match_spec, &channel_config) + .unwrap(); + let any_spec = MatchSpec::from_str("any-spec", ParseStrictness::Strict).unwrap(); + manifest + .add_dependency(&env_name, &any_spec, &channel_config) + .unwrap(); + + assert_snapshot!(manifest.document.to_string()); + } + + #[test] + fn test_add_existing_dependency() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + + let match_spec = MatchSpec::from_str("pythonic ==3.15.0", ParseStrictness::Strict).unwrap(); + let channel_config = ChannelConfig::default_with_root_dir(std::env::current_dir().unwrap()); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Add dependency + manifest + .add_dependency(&env_name, &match_spec, &channel_config) + .unwrap(); + + // Add the same dependency again, with a new match_spec + let new_match_spec = + MatchSpec::from_str("pythonic==3.18.0", ParseStrictness::Strict).unwrap(); + manifest + .add_dependency(&env_name, &new_match_spec, &channel_config) + .unwrap(); + + // Check document + let name = match_spec.name.clone().unwrap(); + let actual_value = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}.dependencies")) + .unwrap() + .get(name.clone().as_normalized()); + assert!(actual_value.is_some()); + assert_eq!( + actual_value.unwrap().to_string().replace('"', ""), + "==3.18.0" + ); + + // Check parsed + let actual_value = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .dependencies + .get(&name) + .unwrap() + .clone(); + assert_eq!( + actual_value.into_version().unwrap().to_string(), + "==3.18.0".to_string() + ); + } + + #[test] + fn test_set_platform() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + let platform = Platform::LinuxRiscv64; + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Set platform + manifest.set_platform(&env_name, platform).unwrap(); + + // Check document + let actual_platform = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}")) + .unwrap() + .get("platform") + .unwrap(); + assert_eq!(actual_platform.as_str().unwrap(), platform.as_str()); + + // Check parsed + let actual_platform = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .platform + .unwrap(); + assert_eq!(actual_platform, platform); + } + + #[test] + fn test_add_channel() { + let mut manifest = Manifest::default(); + let env_name = EnvironmentName::from_str("test-env").unwrap(); + let channel = NamedChannelOrUrl::from_str("test-channel").unwrap(); + let mut channels = Config::load_global().default_channels(); + channels.push(channel.clone()); + + // Add environment + manifest.add_environment(&env_name, None).unwrap(); + + // Add channel + manifest.add_channel(&env_name, &channel).unwrap(); + + // Check document + let actual_channels = manifest + .document + .get_or_insert_nested_table(&format!("envs.{env_name}")) + .unwrap() + .get("channels") + .unwrap() + .as_array() + .unwrap() + .into_iter() + .filter_map(|v| v.as_str()) + .collect_vec(); + let expected_channels = channels.iter().map(|c| c.as_str()).collect_vec(); + assert_eq!(actual_channels, expected_channels); + + // Check parsed + let actual_channels = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .channels + .clone(); + let expected_channels: IndexSet = + channels.into_iter().map(From::from).collect(); + assert_eq!(actual_channels, expected_channels); + } + + #[test] + fn test_remove_dependency() { + let env_name = EnvironmentName::from_str("test-env").unwrap(); + let match_spec = MatchSpec::from_str("pytest", ParseStrictness::Strict).unwrap(); + + let mut manifest = Manifest::from_str( + Path::new("global.toml"), + r#" +[envs.test-env] +channels = ["test-channel"] +dependencies = { "python" = "*", pytest = "*"} +"#, + ) + .unwrap(); + + // Remove dependency + manifest.remove_dependency(&env_name, &match_spec).unwrap(); + + // Check document + assert!(!manifest + .document + .to_string() + .contains(match_spec.name.clone().unwrap().as_normalized())); + + // Check parsed + let actual_value = manifest + .parsed + .envs + .get(&env_name) + .unwrap() + .dependencies + .get(&match_spec.name.unwrap()); + assert!(actual_value.is_none()); + + assert_snapshot!(manifest.document.to_string()); + } +} diff --git a/src/global/project/mod.rs b/src/global/project/mod.rs new file mode 100644 index 000000000..b198364a0 --- /dev/null +++ b/src/global/project/mod.rs @@ -0,0 +1,1234 @@ +use super::{extract_executable_from_script, BinDir, EnvRoot, StateChange, StateChanges}; +use crate::global::common::{ + channel_url_to_prioritized_channel, find_package_records, get_expose_scripts_sync_status, +}; +use crate::global::install::{ + create_activation_script, create_executable_scripts, script_exec_mapping, +}; +use crate::global::project::environment::environment_specs_in_sync; +use crate::repodata::Repodata; +use crate::rlimit::try_increase_rlimit_to_sensible; +use crate::{ + global::{find_executables, EnvDir}, + prefix::Prefix, +}; +use ahash::HashSet; +pub(crate) use environment::EnvironmentName; +use fancy_display::FancyDisplay; +use fs::tokio as tokio_fs; +use fs_err as fs; +use futures::stream::StreamExt; +use indexmap::{IndexMap, IndexSet}; +use itertools::Itertools; +pub(crate) use manifest::{Manifest, Mapping}; +use miette::{miette, Context, IntoDiagnostic}; +pub(crate) use parsed_manifest::ExposedName; +pub(crate) use parsed_manifest::ParsedEnvironment; +use parsed_manifest::ParsedManifest; +use pixi_config::{default_channel_config, home_path, Config}; +use pixi_consts::consts; +use pixi_manifest::PrioritizedChannel; +use pixi_progress::{await_in_progress, global_multi_progress, wrap_in_progress}; +use pixi_utils::executable_from_path; +use pixi_utils::reqwest::build_reqwest_clients; +use rattler::install::{DefaultProgressFormatter, IndicatifReporter, Installer}; +use rattler::package_cache::PackageCache; +use rattler_conda_types::{ + ChannelConfig, GenericVirtualPackage, MatchSpec, PackageName, Platform, PrefixRecord, +}; +use rattler_lock::Matches; +use rattler_repodata_gateway::Gateway; +use rattler_shell::shell::ShellEnum; +use rattler_solve::resolvo::Solver; +use rattler_solve::{SolverImpl, SolverTask}; +use rattler_virtual_packages::{VirtualPackage, VirtualPackageOverrides}; +use reqwest_middleware::ClientWithMiddleware; +use std::sync::OnceLock; +use std::{ + ffi::OsStr, + fmt::{Debug, Formatter}, + path::{Path, PathBuf}, + str::FromStr, +}; +use toml_edit::DocumentMut; + +mod environment; +mod manifest; +mod parsed_manifest; + +pub(crate) const MANIFEST_DEFAULT_NAME: &str = "pixi-global.toml"; +pub(crate) const MANIFESTS_DIR: &str = "manifests"; + +/// The pixi global project, this main struct to interact with the pixi global +/// project. This struct holds the `Manifest` and has functions to modify +/// or request information from it. This allows in the future to have multiple +/// manifests linked to a pixi global project. +#[derive(Clone)] +pub struct Project { + /// Root folder of the project + root: PathBuf, + /// The manifest for the project + pub(crate) manifest: Manifest, + /// The global configuration as loaded from the config file(s) + config: Config, + /// Root directory of the global environments + pub(crate) env_root: EnvRoot, + /// Binary directory + pub(crate) bin_dir: BinDir, + /// Reqwest client shared for this project. + /// This is wrapped in a `OnceLock` to allow for lazy initialization. + client: OnceLock<(reqwest::Client, ClientWithMiddleware)>, + /// The repodata gateway to use for answering queries about repodata. + /// This is wrapped in a `OnceLock` to allow for lazy initialization. + repodata_gateway: OnceLock, +} + +impl Debug for Project { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Global Project") + .field("root", &self.root) + .field("manifest", &self.manifest) + .finish() + } +} + +/// Intermediate struct to store all the binaries that are exposed. +#[derive(Debug)] +struct ExposedData { + env_name: EnvironmentName, + platform: Option, + channels: Vec, + package: PackageName, + exposed: ExposedName, + executable_name: String, +} + +impl ExposedData { + /// Constructs an `ExposedData` instance from a exposed script path. + /// + /// This function extracts metadata from the exposed script path, including the + /// environment name, platform, channel, and package information, by reading + /// the associated `conda-meta` directory. + pub async fn from_exposed_path( + path: &Path, + env_root: &EnvRoot, + channel_config: &ChannelConfig, + ) -> miette::Result { + let exposed = ExposedName::from_str(executable_from_path(path).as_str())?; + let executable_path = extract_executable_from_script(path).await?; + + let executable = executable_from_path(&executable_path); + let env_path = determine_env_path(&executable_path, env_root.path())?; + let env_name = env_path + .file_name() + .and_then(OsStr::to_str) + .ok_or_else(|| { + miette::miette!( + "executable path's grandparent '{}' has no file name", + executable_path.display() + ) + }) + .and_then(|env| EnvironmentName::from_str(env).into_diagnostic())?; + + let conda_meta = env_path.join(consts::CONDA_META_DIR); + let env_dir = EnvDir::from_env_root(env_root.clone(), &env_name).await?; + let prefix = Prefix::new(env_dir.path()); + + let (platform, channel, package) = + package_from_conda_meta(&conda_meta, &executable, &prefix, channel_config).await?; + + let mut channels = vec![channel]; + + // Find all channels used to create the environment + let all_channels = prefix + .find_installed_packages(None) + .await? + .iter() + .map(|prefix_record| prefix_record.repodata_record.channel.clone()) + .collect::>(); + for channel in all_channels { + tracing::debug!("Channel: {} found in environment: {}", channel, env_name); + channels.push(channel_url_to_prioritized_channel( + &channel, + channel_config, + )?); + } + + Ok(ExposedData { + env_name, + platform, + channels, + package, + executable_name: executable, + exposed, + }) + } +} + +fn determine_env_path(executable_path: &Path, env_root: &Path) -> miette::Result { + let mut current_path = executable_path; + + while let Some(parent) = current_path.parent() { + if parent == env_root { + return Ok(current_path.to_owned()); + } + current_path = parent; + } + + miette::bail!( + "Couldn't determine environment path: no parent of '{}' has '{}' as its direct parent", + executable_path.display(), + env_root.display() + ) +} + +/// Converts a `PrefixRecord` into package metadata, including platform, channel, and package name. +fn convert_record_to_metadata( + prefix_record: &PrefixRecord, + channel_config: &ChannelConfig, +) -> miette::Result<(Option, PrioritizedChannel, PackageName)> { + let platform = match Platform::from_str(&prefix_record.repodata_record.package_record.subdir) { + Ok(Platform::NoArch) => None, + Ok(platform) if platform == Platform::current() => None, + Err(_) => None, + Ok(p) => Some(p), + }; + + let package_name = prefix_record.repodata_record.package_record.name.clone(); + + let channel = + channel_url_to_prioritized_channel(&prefix_record.repodata_record.channel, channel_config)?; + + Ok((platform, channel, package_name)) +} + +/// Extracts package metadata from the `conda-meta` directory for a given executable. +/// +/// This function reads the `conda-meta` directory to find the package metadata +/// associated with the specified executable. It returns the platform, channel, and +/// package name of the executable. +async fn package_from_conda_meta( + conda_meta: &Path, + executable: &str, + prefix: &Prefix, + channel_config: &ChannelConfig, +) -> miette::Result<(Option, PrioritizedChannel, PackageName)> { + let records = find_package_records(conda_meta).await?; + + for prefix_record in records { + if find_executables(prefix, &prefix_record) + .iter() + .any(|exe_path| executable_from_path(exe_path) == executable) + { + return convert_record_to_metadata(&prefix_record, channel_config); + } + } + + miette::bail!("Couldn't find {executable} in {}", conda_meta.display()) +} + +impl Project { + /// Constructs a new instance from an internal manifest representation + pub(crate) fn from_manifest(manifest: Manifest, env_root: EnvRoot, bin_dir: BinDir) -> Self { + let root = manifest + .path + .parent() + .expect("manifest path should always have a parent") + .to_owned(); + + let config = Config::load(&root); + + let client = OnceLock::new(); + let repodata_gateway = OnceLock::new(); + Self { + root, + manifest, + config, + env_root, + bin_dir, + client, + repodata_gateway, + } + } + + /// Constructs a project from a manifest. + pub(crate) fn from_str( + manifest_path: &Path, + content: &str, + env_root: EnvRoot, + bin_dir: BinDir, + ) -> miette::Result { + let manifest = Manifest::from_str(manifest_path, content)?; + Ok(Self::from_manifest(manifest, env_root, bin_dir)) + } + + /// Discovers the project manifest file in path at + /// `~/.pixi/manifests/pixi-global.toml`. If the manifest doesn't exist + /// yet, and the function will try to create one from the existing + /// installation. If that one fails, an empty one will be created. + pub(crate) async fn discover_or_create() -> miette::Result { + let manifest_dir = Self::manifest_dir()?; + let manifest_path = Self::default_manifest_path()?; + // Prompt user if the manifest is empty and the user wants to create one + + let bin_dir = BinDir::from_env().await?; + let env_root = EnvRoot::from_env().await?; + + if !manifest_path.exists() { + tokio_fs::create_dir_all(&manifest_dir) + .await + .into_diagnostic()?; + + if !env_root.directories().await?.is_empty() { + return Self::try_from_existing_installation(&manifest_path, env_root, bin_dir) + .await + .wrap_err_with(|| { + "Failed to create global manifest from existing installation" + }); + } else { + tokio_fs::File::create(&manifest_path) + .await + .into_diagnostic()?; + } + } + + Self::from_path(&manifest_path, env_root, bin_dir) + } + + async fn try_from_existing_installation( + manifest_path: &Path, + env_root: EnvRoot, + bin_dir: BinDir, + ) -> miette::Result { + let config = Config::load(env_root.path()); + + let exposed_binaries: Vec = bin_dir + .files() + .await? + .into_iter() + .map(|path| { + let env_root = env_root.clone(); + let config = config.clone(); + async move { + ExposedData::from_exposed_path(&path, &env_root, config.global_channel_config()) + .await + } + }) + .collect::>() + .filter_map(|result| async { + match result { + Ok(data) => Some(data), + Err(e) => { + tracing::warn!("{e}"); + None + } + } + }) + .collect() + .await; + + let parsed_manifest = ParsedManifest::from(exposed_binaries); + let toml_pretty = toml_edit::ser::to_string_pretty(&parsed_manifest).into_diagnostic()?; + let mut document: DocumentMut = toml_pretty.parse().into_diagnostic()?; + + // Ensure that the manifest uses inline tables for "dependencies" and "exposed" + if let Some(envs) = document + .get_mut("envs") + .and_then(|item| item.as_table_mut()) + { + for (_, env_table) in envs.iter_mut() { + let Some(env_table) = env_table.as_table_mut() else { + continue; + }; + + for entry in ["dependencies", "exposed"] { + if let Some(table) = env_table.get(entry).and_then(|item| item.as_table()) { + env_table + .insert(entry, toml_edit::value(table.clone().into_inline_table())); + } + } + } + } + let toml = document.to_string(); + tokio_fs::write(&manifest_path, &toml) + .await + .into_diagnostic()?; + Self::from_str(manifest_path, &toml, env_root, bin_dir) + } + + /// Get default dir for the pixi global manifest + pub(crate) fn manifest_dir() -> miette::Result { + home_path() + .map(|dir| dir.join(MANIFESTS_DIR)) + .ok_or_else(|| miette::miette!("Couldn't get home directory")) + } + + /// Get the default path to the global manifest file + pub(crate) fn default_manifest_path() -> miette::Result { + Self::manifest_dir().map(|dir| dir.join(MANIFEST_DEFAULT_NAME)) + } + + /// Loads a project from manifest file. + pub(crate) fn from_path( + manifest_path: &Path, + env_root: EnvRoot, + bin_dir: BinDir, + ) -> miette::Result { + let manifest = Manifest::from_path(manifest_path)?; + Ok(Project::from_manifest(manifest, env_root, bin_dir)) + } + + /// Merge config with existing config project + pub(crate) fn with_cli_config(mut self, config: C) -> Self + where + C: Into, + { + self.config = self.config.merge_config(config.into()); + self + } + + /// Returns the environments in this project. + pub(crate) fn environments(&self) -> &IndexMap { + &self.manifest.parsed.envs + } + + /// Return the environment with the given name. + pub(crate) fn environment(&self, name: &EnvironmentName) -> Option<&ParsedEnvironment> { + self.manifest.parsed.envs.get(name) + } + + /// Returns the EnvDir with the environment name. + pub(crate) async fn environment_dir(&self, name: &EnvironmentName) -> miette::Result { + EnvDir::from_env_root(self.env_root.clone(), name).await + } + + /// Returns the prefix of the environment with the given name. + pub(crate) async fn environment_prefix( + &self, + env_name: &EnvironmentName, + ) -> miette::Result { + Ok(Prefix::new(self.environment_dir(env_name).await?.path())) + } + + /// Create an authenticated reqwest client for this project + /// use authentication from `rattler_networking` + pub fn authenticated_client(&self) -> &ClientWithMiddleware { + &self.client_and_authenticated_client().1 + } + + fn client_and_authenticated_client(&self) -> &(reqwest::Client, ClientWithMiddleware) { + self.client + .get_or_init(|| build_reqwest_clients(Some(&self.config))) + } + + pub(crate) fn config(&self) -> &Config { + &self.config + } + + pub(crate) async fn install_environment( + &self, + env_name: &EnvironmentName, + ) -> miette::Result<()> { + let environment = self + .environment(env_name) + .ok_or_else(|| miette::miette!("Environment {} not found", env_name.fancy_display()))?; + let channels = environment + .channels() + .into_iter() + .map(|channel| { + channel + .clone() + .into_channel(self.config.global_channel_config()) + }) + .collect::, _>>() + .into_diagnostic()?; + + let platform = environment.platform.unwrap_or_else(Platform::current); + + let match_specs = environment + .dependencies + .clone() + .into_iter() + .map(|(name, spec)| { + if let Some(nameless_spec) = spec + .clone() + .try_into_nameless_match_spec(self.config().global_channel_config()) + .into_diagnostic()? + { + Ok(MatchSpec::from_nameless(nameless_spec, Some(name.clone()))) + } else { + Err(miette!("Couldn't convert {spec:?} to nameless match spec.")) + } + }) + .collect::>>()?; + + let repodata = await_in_progress( + format!( + "Querying repodata for environment: {} ", + env_name.fancy_display() + ), + |_| async { + self.repodata_gateway() + .query(channels, [platform, Platform::NoArch], match_specs.clone()) + .recursive(true) + .await + .into_diagnostic() + }, + ) + .await?; + + // Determine virtual packages of the current platform + let virtual_packages = VirtualPackage::detect(&VirtualPackageOverrides::default()) + .into_diagnostic() + .context("failed to determine virtual packages")? + .iter() + .cloned() + .map(GenericVirtualPackage::from) + .collect(); + + // Solve the environment + let cloned_env_name = env_name.clone(); + let solved_records = tokio::task::spawn_blocking(move || { + wrap_in_progress( + format!("Solving environment: {}", cloned_env_name.fancy_display()), + move || { + Solver.solve(SolverTask { + specs: match_specs, + virtual_packages, + ..SolverTask::from_iter(&repodata) + }) + }, + ) + .into_diagnostic() + .context("failed to solve environment") + }) + .await + .into_diagnostic()??; + + try_increase_rlimit_to_sensible(); + + // Install the environment + let package_cache = PackageCache::new(pixi_config::get_cache_dir()?.join("pkgs")); + let prefix = self.environment_prefix(env_name).await?; + await_in_progress( + format!( + "Creating virtual environment for {}", + env_name.fancy_display() + ), + |pb| { + Installer::new() + .with_download_client(self.authenticated_client().clone()) + .with_io_concurrency_limit(100) + .with_execute_link_scripts(false) + .with_package_cache(package_cache) + .with_target_platform(platform) + .with_reporter( + IndicatifReporter::builder() + .with_multi_progress(global_multi_progress()) + .with_placement(rattler::install::Placement::After(pb)) + .with_formatter(DefaultProgressFormatter::default().with_prefix(" ")) + .clear_when_done(true) + .finish(), + ) + .install(prefix.root(), solved_records) + }, + ) + .await + .into_diagnostic()?; + + Ok(()) + } + + /// Remove an environment from the manifest and the global installation. + pub(crate) async fn remove_environment( + &mut self, + env_name: &EnvironmentName, + ) -> miette::Result { + let env_dir = EnvDir::from_env_root(self.env_root.clone(), env_name).await?; + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + + // Remove the environment from the manifest, if it exists, otherwise ignore error. + self.manifest.remove_environment(env_name)?; + + // Remove the environment + tokio_fs::remove_dir_all(env_dir.path()) + .await + .into_diagnostic()?; + + // Get all removable binaries related to the environment + let (to_remove, _to_add) = + get_expose_scripts_sync_status(&self.bin_dir, &env_dir, &IndexSet::new()).await?; + + // Remove all removable binaries + for binary_path in to_remove { + tokio_fs::remove_file(&binary_path) + .await + .into_diagnostic()?; + state_changes.insert_change( + env_name, + StateChange::RemovedExposed(ExposedName::from_str(&executable_from_path( + &binary_path, + ))?), + ); + } + + state_changes.insert_change(env_name, StateChange::RemovedEnvironment); + + Ok(state_changes) + } + + /// Find all binaries related to the environment and remove those that are not listed as exposed. + pub async fn prune_exposed(&self, env_name: &EnvironmentName) -> miette::Result { + let mut state_changes = StateChanges::default(); + let environment = self + .environment(env_name) + .ok_or_else(|| miette::miette!("Environment {} not found", env_name.fancy_display()))?; + let env_dir = EnvDir::from_env_root(self.env_root.clone(), env_name).await?; + + // Get all removable binaries related to the environment + let (to_remove, _to_add) = + get_expose_scripts_sync_status(&self.bin_dir, &env_dir, &environment.exposed).await?; + + // Remove all removable binaries + for exposed_path in to_remove { + state_changes.insert_change( + env_name, + StateChange::RemovedExposed(ExposedName::from_str(&executable_from_path( + &exposed_path, + ))?), + ); + tokio_fs::remove_file(&exposed_path) + .await + .into_diagnostic()?; + } + + Ok(state_changes) + } + + /// Find the exposed names that are no longer installed in the environment + /// and remove them. + /// This needs to happen after a different version of a package was installed + /// which doesn't have the same executables anymore. + pub async fn remove_broken_expose_names( + &mut self, + env_name: &EnvironmentName, + ) -> miette::Result { + // Figure out which package the exposed binaries belong to + let prefix = self.environment_prefix(env_name).await?; + let prefix_records = &prefix.find_installed_packages(None).await?; + let all_executables = &prefix.find_executables(prefix_records.as_slice()); + + // Get the parsed environment + let environment = self + .environment(env_name) + .ok_or_else(|| miette::miette!("Environment {} not found", env_name.fancy_display()))?; + + // Find the exposed names that are no longer and remove them + let to_remove = environment + .exposed + .iter() + .filter_map(|mapping| { + // If the executable is still requested, do not remove the mapping + if all_executables + .iter() + .any(|(_, path)| executable_from_path(path) == mapping.executable_name()) + { + tracing::debug!("Not removing mapping to: {}", mapping.executable_name()); + return None; + } + // Else do remove the mapping + Some(mapping.exposed_name().clone()) + }) + .collect_vec(); + + // Removed the removable exposed names from the manifest + for exposed_name in &to_remove { + self.manifest.remove_exposed_name(env_name, exposed_name)?; + } + + // Remove outdated binaries + self.prune_exposed(env_name).await + } + + /// Check if the environment is in sync with the manifest + /// + /// Validated the specs in the installed environment. + /// And verifies only and all required exposed binaries are in the bin dir. + pub async fn environment_in_sync(&self, env_name: &EnvironmentName) -> miette::Result { + let environment = self.environment(env_name).ok_or(miette::miette!( + "Environment {} not found in manifest.", + env_name.fancy_display() + ))?; + + let specs = environment + .dependencies + .clone() + .into_iter() + .map(|(name, spec)| { + let match_spec = MatchSpec::from_nameless( + spec.clone() + .try_into_nameless_match_spec(&default_channel_config()) + .into_diagnostic()? + .ok_or_else(|| { + miette::miette!("Couldn't convert {spec:?} to nameless match spec.") + })?, + Some(name.clone()), + ); + Ok(match_spec) + }) + .collect::, miette::Report>>()?; + + let env_dir = + EnvDir::from_path(self.env_root.clone().path().join(env_name.clone().as_str())); + + let specs_in_sync = + environment_specs_in_sync(&env_dir, &specs, environment.platform).await?; + if !specs_in_sync { + return Ok(false); + } + + // Verify the binaries to be in sync with the environment + let (to_remove, to_add) = + get_expose_scripts_sync_status(&self.bin_dir, &env_dir, &environment.exposed).await?; + if !to_remove.is_empty() || !to_add.is_empty() { + tracing::debug!( + "Environment {} binaries not in sync: to_remove: {:?}, to_add: {:?}", + env_name.fancy_display(), + to_remove, + to_add + ); + return Ok(false); + } + + Ok(true) + } + + /// Check if all environments are in sync with the manifest + pub async fn environments_in_sync(&self) -> miette::Result { + let mut in_sync = true; + for (env_name, _parsed_environment) in self.environments() { + if !self.environment_in_sync(env_name).await? { + tracing::debug!( + "Environment {} not up to date with the manifest", + env_name.fancy_display() + ); + in_sync = false; + } + } + Ok(in_sync) + } + /// Expose executables from the environment to the global bin directory. + /// + /// This function will first remove all binaries that are not listed as exposed. + /// It will then create an activation script for the shell and create the scripts. + pub async fn expose_executables_from_environment( + &self, + env_name: &EnvironmentName, + ) -> miette::Result { + let mut state_changes = StateChanges::default(); + + // First clean up binaries that are not listed as exposed + state_changes |= self.prune_exposed(env_name).await?; + + // Determine the shell to use for the invocation script + let shell: ShellEnum = if cfg!(windows) { + rattler_shell::shell::CmdExe.into() + } else { + rattler_shell::shell::Bash.into() + }; + let env_dir = EnvDir::from_env_root(self.env_root.clone(), env_name).await?; + let prefix = Prefix::new(env_dir.path()); + + let environment = self + .environment(env_name) + .ok_or_else(|| miette::miette!("Environment {} not found", env_name.fancy_display()))?; + + // Construct the reusable activation script for the shell and generate an + // invocation script for each executable added by the package to the + // environment. + let activation_script = create_activation_script(&prefix, shell.clone())?; + + let prefix_records = &prefix.find_installed_packages(None).await?; + + let all_executables = &prefix.find_executables(prefix_records.as_slice()); + + let exposed: HashSet<&str> = environment + .exposed + .iter() + .map(|map| map.executable_name()) + .collect(); + + let exposed_executables: Vec<_> = all_executables + .iter() + .filter(|(name, _)| exposed.contains(name.as_str())) + .cloned() + .collect(); + + let script_mapping = environment + .exposed + .iter() + .map(|mapping| { + script_exec_mapping( + mapping.exposed_name(), + mapping.executable_name(), + exposed_executables.iter(), + &self.bin_dir, + &env_dir, + ) + }) + .collect::>>() + .wrap_err(format!( + "Failed to add executables for environment: {}", + env_name + ))?; + + tracing::debug!( + "Exposing executables for environment {}", + env_name.fancy_display() + ); + state_changes |= create_executable_scripts( + &script_mapping, + &prefix, + &shell, + activation_script, + env_name, + ) + .await?; + + Ok(state_changes) + } + + // Syncs the manifest with the local environments + // Returns true if the global installation had to be updated + pub(crate) async fn sync(&self) -> Result { + let mut state_changes = StateChanges::default(); + + // Prune environments that are not listed + state_changes |= self.prune_old_environments().await?; + + // Remove broken scripts + if let Err(err) = self.remove_broken_scripts().await { + tracing::warn!("Couldn't remove broken exposed executables: {err}") + } + + for env_name in self.environments().keys() { + state_changes |= self.sync_environment(env_name).await?; + } + + Ok(state_changes) + } + + /// Syncs the parsed environment with the installation. + /// Returns true if the environment had to be updated. + pub(crate) async fn sync_environment( + &self, + env_name: &EnvironmentName, + ) -> miette::Result { + let mut state_changes = StateChanges::new_with_env(env_name.clone()); + if !self.environment_in_sync(env_name).await? { + tracing::debug!( + "Environment {} specs not up to date with manifest", + env_name.fancy_display() + ); + self.install_environment(env_name).await?; + state_changes.insert_change(env_name, StateChange::UpdatedEnvironment); + } + + // Expose executables + state_changes |= self.expose_executables_from_environment(env_name).await?; + + Ok(state_changes) + } + + /// Delete scripts in the bin folder that are broken + pub(crate) async fn remove_broken_scripts(&self) -> miette::Result<()> { + for exposed_path in self.bin_dir.files().await? { + if extract_executable_from_script(&exposed_path) + .await + .and_then(|path| { + if path.is_file() { + Ok(path) + } else { + miette::bail!("Path is not a file") + } + }) + .is_err() + { + tokio_fs::remove_file(exposed_path) + .await + .into_diagnostic()?; + } + } + + Ok(()) + } + + /// Delete all non required environments + pub(crate) async fn prune_old_environments(&self) -> miette::Result { + let env_set: HashSet<&EnvironmentName> = self.environments().keys().collect(); + + let mut state_changes = StateChanges::default(); + for env_path in self.env_root.directories().await? { + let Some(Ok(env_name)) = env_path + .file_name() + .and_then(|name| name.to_str()) + .map(EnvironmentName::from_str) + else { + continue; + }; + + if !env_set.contains(&env_name) { + // Test if the environment directory is a conda environment + if let Ok(true) = env_path.join(consts::CONDA_META_DIR).try_exists() { + // Remove the conda environment + tokio_fs::remove_dir_all(&env_path) + .await + .into_diagnostic()?; + // Get all removable binaries related to the environment + let (to_remove, _to_add) = get_expose_scripts_sync_status( + &self.bin_dir, + &EnvDir::from_path(env_path.clone()), + &IndexSet::new(), + ) + .await?; + + // Remove all removable binaries + for binary_path in to_remove { + tokio_fs::remove_file(&binary_path) + .await + .into_diagnostic()?; + } + state_changes.insert_change(&env_name, StateChange::RemovedEnvironment); + } + } + } + Ok(state_changes) + } + + // Figure which packages have been added + pub async fn added_packages( + &self, + specs: &[MatchSpec], + env_name: &EnvironmentName, + ) -> miette::Result { + let mut state_changes = StateChanges::default(); + state_changes.push_changes( + env_name, + self.environment_prefix(env_name) + .await? + .find_installed_packages(None) + .await? + .into_iter() + .filter(|r| specs.iter().any(|s| s.matches(&r.repodata_record))) + .map(|r| r.repodata_record.package_record) + .map(StateChange::AddedPackage), + ); + Ok(state_changes) + } +} + +impl Repodata for Project { + /// Returns the [`Gateway`] used by this project. + fn repodata_gateway(&self) -> &Gateway { + self.repodata_gateway.get_or_init(|| { + Self::repodata_gateway_init( + self.authenticated_client().clone(), + self.config().clone().into(), + ) + }) + } +} + +#[cfg(test)] +mod tests { + use std::{collections::HashMap, io::Write}; + + use super::*; + use fake::{faker::filesystem::zh_tw::FilePath, Fake}; + use itertools::Itertools; + use rattler_conda_types::{ + NamedChannelOrUrl, PackageRecord, Platform, RepoDataRecord, VersionWithSource, + }; + use tempfile::tempdir; + use url::Url; + + const SIMPLE_MANIFEST: &str = r#" + [envs.python] + channels = ["dummy-channel"] + [envs.python.dependencies] + dummy = "3.11.*" + [envs.python.exposed] + dummy = "dummy" + "#; + + #[tokio::test] + async fn test_project_from_str() { + let manifest_path: PathBuf = FilePath().fake(); + let env_root = EnvRoot::from_env().await.unwrap(); + let bin_dir = BinDir::from_env().await.unwrap(); + + let project = + Project::from_str(&manifest_path, SIMPLE_MANIFEST, env_root, bin_dir).unwrap(); + assert_eq!(project.root, manifest_path.parent().unwrap()); + } + + #[tokio::test] + async fn test_project_from_path() { + let tempdir = tempfile::tempdir().unwrap(); + let manifest_path = tempdir.path().join(MANIFEST_DEFAULT_NAME); + + let env_root = EnvRoot::from_env().await.unwrap(); + let bin_dir = BinDir::from_env().await.unwrap(); + + // Create and write global manifest + let mut file = fs::File::create(&manifest_path).unwrap(); + file.write_all(SIMPLE_MANIFEST.as_bytes()).unwrap(); + let project = Project::from_path(&manifest_path, env_root, bin_dir).unwrap(); + + // Canonicalize both paths + let canonical_root = project.root.canonicalize().unwrap(); + let canonical_manifest_parent = manifest_path.parent().unwrap().canonicalize().unwrap(); + + assert_eq!(canonical_root, canonical_manifest_parent); + } + + #[tokio::test] + async fn test_project_from_manifest() { + let manifest_path: PathBuf = FilePath().fake(); + + let env_root = EnvRoot::from_env().await.unwrap(); + let bin_dir = BinDir::from_env().await.unwrap(); + + let manifest = Manifest::from_str(&manifest_path, SIMPLE_MANIFEST).unwrap(); + let project = Project::from_manifest(manifest, env_root, bin_dir); + assert_eq!(project.root, manifest_path.parent().unwrap()); + } + + #[test] + fn test_project_manifest_dir() { + Project::manifest_dir().unwrap(); + } + + #[tokio::test] + async fn test_prune_exposed() { + let tempdir = tempfile::tempdir().unwrap(); + let project = Project::from_str( + &PathBuf::from("dummy"), + r#" + [envs.test] + channels = ["conda-forge"] + [envs.test.dependencies] + python = "*" + [envs.test.exposed] + python = "python" + "#, + EnvRoot::new(tempdir.path().to_path_buf()).unwrap(), + BinDir::new(tempdir.path().to_path_buf()).unwrap(), + ) + .unwrap(); + + let env_name = "test".parse().unwrap(); + + // Create non-exposed but related binary + let not_python = ExposedName::from_str("not-python").unwrap(); + let non_exposed_bin = project.bin_dir.executable_script_path(¬_python); + let mut file = fs::File::create(&non_exposed_bin).unwrap(); + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let path = project.env_root.path().join("test/bin/not-python"); + file.write_all(format!(r#""{}" "$@""#, path.to_string_lossy()).as_bytes()) + .unwrap(); + // Set the file permissions to make it executable + let metadata = tokio_fs::metadata(&non_exposed_bin).await.unwrap(); + let mut permissions = metadata.permissions(); + permissions.set_mode(0o755); // rwxr-xr-x + tokio_fs::set_permissions(&non_exposed_bin, permissions) + .await + .unwrap(); + } + #[cfg(windows)] + { + let path = project.env_root.path().join("test/bin/not-python.exe"); + file.write_all(format!(r#"@"{}" %*"#, path.to_string_lossy()).as_bytes()) + .unwrap(); + } + + // Create a file that should be exposed + let python = ExposedName::from_str("python").unwrap(); + let bin = project.bin_dir.executable_script_path(&python); + let mut file = fs::File::create(&bin).unwrap(); + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + let path = project.env_root.path().join("test/bin/python"); + file.write_all(format!(r#""{}" "$@""#, path.to_string_lossy()).as_bytes()) + .unwrap(); + + // Set the file permissions to make it executable + let metadata = tokio_fs::metadata(&bin).await.unwrap(); + let mut permissions = metadata.permissions(); + permissions.set_mode(0o755); // rwxr-xr-x + tokio_fs::set_permissions(&bin, permissions).await.unwrap(); + } + #[cfg(windows)] + { + let path = project.env_root.path().join("test/bin/python.exe"); + file.write_all(format!(r#"@"{}" %*"#, path.to_string_lossy()).as_bytes()) + .unwrap(); + } + + // Create unrelated file + let unrelated = project.bin_dir.path().join("unrelated"); + fs::File::create(&unrelated).unwrap(); + + // Remove exposed + let state_changes = project.prune_exposed(&env_name).await.unwrap(); + assert_eq!( + state_changes.changes(), + std::collections::HashMap::from([( + env_name.clone(), + vec![StateChange::RemovedExposed(not_python)] + )]) + ); + + // Check if the non-exposed file was removed + assert_eq!(fs::read_dir(project.bin_dir.path()).unwrap().count(), 2); + assert!(bin.exists()); + assert!(unrelated.exists()); + assert!(!non_exposed_bin.exists()); + } + + #[tokio::test] + async fn test_prune() { + // Create a temporary directory + let temp_dir = tempdir().unwrap(); + + // Set the env root to the temporary directory + let env_root = EnvRoot::new(temp_dir.path().to_owned()).unwrap(); + + // Create some directories in the temporary directory + let envs = ["env1", "env2", "env3", "non-conda-env-dir"]; + for env in envs { + EnvDir::from_env_root(env_root.clone(), &EnvironmentName::from_str(env).unwrap()) + .await + .unwrap(); + } + // Add conda meta data to env2 to make sure it's seen as a conda environment + tokio_fs::create_dir_all(env_root.path().join("env2").join(consts::CONDA_META_DIR)) + .await + .unwrap(); + + // Create project with env1 and env3 + let manifest = Manifest::from_str( + &env_root.path().join(MANIFEST_DEFAULT_NAME), + r#" + [envs.env1] + channels = ["conda-forge"] + [envs.env1.dependencies] + python = "*" + [envs.env1.exposed] + python1 = "python" + + [envs.env3] + channels = ["conda-forge"] + [envs.env3.dependencies] + python = "*" + [envs.env3.exposed] + python2 = "python" + "#, + ) + .unwrap(); + let project = Project::from_manifest( + manifest, + env_root.clone(), + BinDir::new(env_root.path().parent().unwrap().to_path_buf()).unwrap(), + ); + + // Call the prune method with a list of environments to keep (env1 and env3) but not env4 + let state_changes = project.prune_old_environments().await.unwrap(); + assert_eq!( + state_changes.changes(), + HashMap::from([( + "env2".parse().unwrap(), + vec![StateChange::RemovedEnvironment] + )]) + ); + + // Verify that only the specified directories remain + let remaining_dirs = fs::read_dir(env_root.path()) + .unwrap() + .filter_map(|entry| entry.ok()) + .filter(|entry| entry.path().is_dir()) + .map(|entry| entry.file_name().into_string().unwrap()) + .sorted() + .collect_vec(); + + assert_eq!(remaining_dirs, vec!["env1", "env3", "non-conda-env-dir"]); + } + + #[test] + fn test_convert_repodata_to_exposed_data() { + let temp_dir = tempdir().unwrap(); + let channel_config = ChannelConfig::default_with_root_dir(temp_dir.path().to_owned()); + let mut package_record = PackageRecord::new( + "python".parse().unwrap(), + VersionWithSource::from_str("3.9.7").unwrap(), + "build_string".to_string(), + ); + + // Set platform to something different than current + package_record.subdir = Platform::LinuxRiscv32.to_string(); + + let repodata_record = RepoDataRecord { + package_record: package_record.clone(), + file_name: "doesnt_matter.conda".to_string(), + url: Url::from_str("https://also_doesnt_matter").unwrap(), + channel: format!("{}{}", channel_config.channel_alias.clone(), "test-channel"), + }; + let prefix_record = PrefixRecord::from_repodata_record( + repodata_record, + None, + None, + vec![], + Default::default(), + None, + ); + + // Test with default channel alias + let (platform, channel, package) = + convert_record_to_metadata(&prefix_record, &channel_config).unwrap(); + assert_eq!( + channel, + NamedChannelOrUrl::from_str("test-channel").unwrap().into() + ); + assert_eq!(package, "python".parse().unwrap()); + assert_eq!(platform, Some(Platform::LinuxRiscv32)); + + // Test with different from default channel alias + let repodata_record = RepoDataRecord { + package_record: package_record.clone(), + file_name: "doesnt_matter.conda".to_string(), + url: Url::from_str("https://also_doesnt_matter").unwrap(), + channel: "https://test-channel.com/idk".to_string(), + }; + let prefix_record = PrefixRecord::from_repodata_record( + repodata_record, + None, + None, + vec![], + Default::default(), + None, + ); + + let (_platform, channel, package) = + convert_record_to_metadata(&prefix_record, &channel_config).unwrap(); + assert_eq!( + channel, + NamedChannelOrUrl::from_str("https://test-channel.com/idk") + .unwrap() + .into() + ); + assert_eq!(package, "python".parse().unwrap()); + } +} diff --git a/src/global/project/parsed_manifest.rs b/src/global/project/parsed_manifest.rs new file mode 100644 index 000000000..8209406e5 --- /dev/null +++ b/src/global/project/parsed_manifest.rs @@ -0,0 +1,473 @@ +use std::cmp::Ordering; +use std::collections::HashMap; +use std::fmt; +use std::path::Path; +use std::str::FromStr; + +use super::environment::EnvironmentName; +use console::StyledObject; +use fancy_display::FancyDisplay; +use indexmap::{IndexMap, IndexSet}; +use itertools::Itertools; +use miette::{Context, Diagnostic, IntoDiagnostic, LabeledSpan, NamedSource, Report}; +use pixi_consts::consts; +use pixi_manifest::PrioritizedChannel; +use rattler_conda_types::{NamedChannelOrUrl, PackageName, Platform}; +use serde::de::{Deserialize, Deserializer, Visitor}; +use serde::ser::SerializeMap; +use serde::{Serialize, Serializer}; +use serde_with::{serde_as, serde_derive::Deserialize}; +use thiserror::Error; +use toml_edit::TomlError; + +use super::ExposedData; +use crate::global::Mapping; +use pixi_spec::PixiSpec; + +pub const GLOBAL_MANIFEST_VERSION: u32 = 1; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct ManifestVersion(u32); + +impl Default for ManifestVersion { + fn default() -> Self { + ManifestVersion(GLOBAL_MANIFEST_VERSION) + } +} + +impl From for toml_edit::Item { + fn from(version: ManifestVersion) -> Self { + toml_edit::value(version.0 as i64) + } +} + +#[derive(Error, Debug, Clone, Diagnostic)] +pub enum ManifestParsingError { + #[error(transparent)] + Error(#[from] toml_edit::TomlError), + #[error("The 'version' of the manifest is too low: '{0}', the supported version is '{GLOBAL_MANIFEST_VERSION}', please update the manifest")] + VersionTooLow(u32, #[source] toml_edit::TomlError), + #[error("The 'version' of the manifest is too high: '{0}', the supported version is '{GLOBAL_MANIFEST_VERSION}', please update `pixi` to support the new manifest version")] + VersionTooHigh(u32, #[source] toml_edit::TomlError), +} + +impl ManifestParsingError { + pub fn to_fancy( + &self, + file_name: &str, + contents: impl Into, + path: &Path, + ) -> Result { + if let Some(span) = self.span() { + Err(miette::miette!( + labels = vec![LabeledSpan::at(span, self.message())], + "Failed to parse global manifest: {}", + console::style(path.display()).bold() + ) + .with_source_code(NamedSource::new(file_name, contents.into()))) + } else { + Err(self.clone()).into_diagnostic().with_context(|| { + format!( + "Failed to parse global manifest: '{}'", + console::style(path.display()).bold() + ) + }) + } + } + + fn span(&self) -> Option> { + match self { + ManifestParsingError::Error(e) => e.span(), + _ => None, + } + } + fn message(&self) -> String { + match self { + ManifestParsingError::Error(e) => e.message().to_owned(), + _ => self.to_string(), + } + } +} + +/// Describes the contents of a parsed global project manifest. +#[derive(Debug, Clone, Serialize, Default)] +pub struct ParsedManifest { + /// The version of the manifest + version: ManifestVersion, + /// The environments the project can create. + pub(crate) envs: IndexMap, +} + +impl ParsedManifest { + /// Parses a toml string into a project manifest. + pub(crate) fn from_toml_str(source: &str) -> Result { + // If it fails only try to get version from the file to see if we can create a better error based on that. + match toml_edit::de::from_str::(source) { + Ok(toml) => Ok(toml), + Err(e) => { + // Define a struct that only includes the `version` field. + #[derive(Deserialize)] + struct VersionOnly { + version: ManifestVersion, + } + + // Attempt to deserialize the TOML string into `VersionOnly`. + match toml_edit::de::from_str::(source) { + Ok(version_only) => { + let version = version_only.version.0; + // Check if the version is supported. + match version.cmp(&GLOBAL_MANIFEST_VERSION) { + Ordering::Greater => Err(ManifestParsingError::VersionTooHigh( + version, + TomlError::from(e), + )), + Ordering::Less => Err(ManifestParsingError::VersionTooLow( + version, + TomlError::from(e), + )), + // Version is supported, but there was another parsing error. + Ordering::Equal => Err(ManifestParsingError::Error(TomlError::from(e))), + } + } + Err(_) => { + // Could not extract the version; return the original error. + Err(ManifestParsingError::Error(TomlError::from(e))) + } + } + } + } + } +} + +impl From for ParsedManifest +where + I: IntoIterator, +{ + fn from(value: I) -> Self { + let mut envs: IndexMap = IndexMap::new(); + for data in value { + let ExposedData { + env_name, + platform, + channels, + package, + executable_name, + exposed, + } = data; + let parsed_environment = envs.entry(env_name).or_default(); + parsed_environment.channels.extend(channels); + parsed_environment.platform = platform; + parsed_environment + .dependencies + .insert(package, PixiSpec::default()); + parsed_environment + .exposed + .insert(Mapping::new(exposed, executable_name)); + } + + Self { + envs, + version: ManifestVersion::default(), + } + } +} + +impl<'de> serde::Deserialize<'de> for ParsedManifest { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[serde_as] + #[derive(Deserialize, Debug, Clone)] + #[serde(deny_unknown_fields, rename_all = "kebab-case")] + pub struct TomlManifest { + /// The version of the manifest + #[serde(default)] + version: ManifestVersion, + /// The environments the project can create. + #[serde(default)] + envs: IndexMap, + } + + let manifest = TomlManifest::deserialize(deserializer)?; + + // Check for duplicate keys in the exposed fields + let mut exposed_names = IndexSet::new(); + let mut duplicates = IndexMap::new(); + for key in manifest + .envs + .values() + .flat_map(|env| env.exposed.iter().map(|m| m.exposed_name())) + { + if !exposed_names.insert(key) { + duplicates.entry(key).or_insert_with(Vec::new).push(key); + } + } + if !duplicates.is_empty() { + return Err(serde::de::Error::custom(format!( + "Duplicated exposed names found: {}", + duplicates + .keys() + .sorted() + .map(|exposed_name| exposed_name.fancy_display()) + .join(", ") + ))); + } + + Ok(Self { + version: manifest.version, + envs: manifest.envs, + }) + } +} + +/// Deserialize a map of exposed names to executable names. +fn deserialize_expose_mappings<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let map: HashMap = HashMap::deserialize(deserializer)?; + Ok(map + .into_iter() + .map(|(exposed_name, executable_name)| Mapping::new(exposed_name, executable_name)) + .collect()) +} + +/// Custom serializer for a map of exposed names to executable names. +fn serialize_expose_mappings( + mappings: &IndexSet, + serializer: S, +) -> Result +where + S: Serializer, +{ + let mut map = serializer.serialize_map(Some(mappings.len()))?; + for mapping in mappings { + map.serialize_entry(&mapping.exposed_name(), &mapping.executable_name())?; + } + map.end() +} + +#[serde_as] +#[derive(Deserialize, Serialize, Debug, Clone, Default)] +#[serde(deny_unknown_fields, rename_all = "kebab-case")] +pub(crate) struct ParsedEnvironment { + #[serde_as(as = "IndexSet")] + pub channels: IndexSet, + // Platform used by the environment. + pub platform: Option, + #[serde(default, deserialize_with = "pixi_manifest::deserialize_package_map")] + pub(crate) dependencies: IndexMap, + #[serde( + default, + deserialize_with = "deserialize_expose_mappings", + serialize_with = "serialize_expose_mappings" + )] + pub(crate) exposed: IndexSet, +} + +impl ParsedEnvironment { + // Create empty parsed environment + pub(crate) fn new(channels: impl IntoIterator) -> Self { + Self { + channels: channels.into_iter().collect(), + ..Default::default() + } + } + /// Returns the platform associated with this platform, `None` means current platform + pub(crate) fn platform(&self) -> Option { + self.platform + } + + /// Returns the channels associated with this environment. + pub(crate) fn channels(&self) -> IndexSet<&NamedChannelOrUrl> { + PrioritizedChannel::sort_channels_by_priority(&self.channels).collect() + } + + /// Returns the dependencies associated with this environment. + pub(crate) fn dependencies(&self) -> &IndexMap { + &self.dependencies + } + + /// Returns the exposed name mappings associated with this environment. + pub(crate) fn exposed(&self) -> &IndexSet { + &self.exposed + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, PartialOrd, Ord)] +pub(crate) struct ExposedName(String); + +impl fmt::Display for ExposedName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl FancyDisplay for ExposedName { + fn fancy_display(&self) -> StyledObject<&str> { + consts::EXPOSED_NAME_STYLE.apply_to(&self.0) + } +} + +#[derive(Error, Diagnostic, Debug, PartialEq)] +pub(crate) enum ExposedNameError { + #[error("'pixi' is not allowed as exposed name in the map")] + PixiBinParseError, +} + +impl FromStr for ExposedName { + type Err = ExposedNameError; + + fn from_str(value: &str) -> Result { + if value == "pixi" { + Err(ExposedNameError::PixiBinParseError) + } else { + Ok(ExposedName(value.to_string())) + } + } +} + +impl<'de> Deserialize<'de> for ExposedName { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct ExposedKeyVisitor; + + impl<'de> Visitor<'de> for ExposedKeyVisitor { + type Value = ExposedName; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string that is not 'pixi'") + } + + fn visit_str(self, value: &str) -> Result + where + E: serde::de::Error, + { + ExposedName::from_str(value).map_err(serde::de::Error::custom) + } + } + + deserializer.deserialize_str(ExposedKeyVisitor) + } +} + +/// Represents an error that occurs when parsing an binary exposed name. +/// +/// This error is returned when a string fails to be parsed as an environment name. +#[derive(Debug, Clone, Error, Diagnostic, PartialEq)] +#[error("pixi is not allowed as exposed name in the map")] +pub struct ParseExposedKeyError {} + +#[cfg(test)] +mod tests { + use insta::assert_snapshot; + + use super::ParsedManifest; + + #[test] + fn test_invalid_key() { + let examples = [ + "[invalid]", + "[envs.ipython.invalid]", + r#"[envs."python;3".dependencies]"#, + ]; + assert_snapshot!(examples + .into_iter() + .map(|example| ParsedManifest::from_toml_str(example) + .unwrap_err() + .to_string()) + .collect::>() + .join("\n")) + } + + #[test] + fn test_duplicate_exposed() { + let contents = r#" + [envs.python-3-10] + channels = ["conda-forge"] + [envs.python-3-10.dependencies] + python = "3.10" + [envs.python-3-10.exposed] + python = "python" + python3 = "python" + [envs.python-3-11] + channels = ["conda-forge"] + [envs.python-3-11.dependencies] + python = "3.11" + [envs.python-3-11.exposed] + "python" = "python" + "python3" = "python" + "#; + let manifest = ParsedManifest::from_toml_str(contents); + + assert!(manifest.is_err()); + assert_snapshot!(manifest.unwrap_err()); + } + + #[test] + fn test_duplicate_dependency() { + let contents = r#" + [envs.python] + channels = ["conda-forge"] + [envs.python.dependencies] + python = "*" + PYTHON = "*" + [envs.python.exposed] + python = "python" + "#; + let manifest = ParsedManifest::from_toml_str(contents); + + assert!(manifest.is_err()); + assert_snapshot!(manifest.unwrap_err()); + } + + #[test] + fn test_expose_pixi() { + let contents = r#" + [envs.test] + channels = ["conda-forge"] + [envs.test.dependencies] + python = "*" + [envs.test.exposed] + pixi = "python" + "#; + let manifest = ParsedManifest::from_toml_str(contents); + + assert!(manifest.is_err()); + assert_snapshot!(manifest.unwrap_err()); + } + + #[test] + fn test_tool_deserialization() { + let contents = r#" + # The name of the environment is `python` + [envs.python] + channels = ["conda-forge"] + # optional, defaults to your current OS + platform = "osx-64" + # It will expose python, python3 and python3.11, but not pip + [envs.python.dependencies] + python = "3.11.*" + pip = "*" + + [envs.python.exposed] + python = "python" + python3 = "python3" + "python3.11" = "python3.11" + + # The name of the environment is `python3-10` + [envs.python3-10] + channels = ["https://fast.prefix.dev/conda-forge"] + # It will expose python3.10 + [envs.python3-10.dependencies] + python = "3.10.*" + + [envs.python3-10.exposed] + "python3.10" = "python" + "#; + let _manifest = ParsedManifest::from_toml_str(contents).unwrap(); + } +} diff --git a/src/global/project/snapshots/pixi__global__project__manifest__tests__add_dependency.snap b/src/global/project/snapshots/pixi__global__project__manifest__tests__add_dependency.snap new file mode 100644 index 000000000..f7e96e898 --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__manifest__tests__add_dependency.snap @@ -0,0 +1,7 @@ +--- +source: src/global/project/manifest.rs +expression: manifest.document.to_string() +--- +[envs.test-env] +channels = ["conda-forge"] +dependencies = { pythonic = "==3.15.0", python = { version = "==3.11.0", build = "he550d4f_1_cpython" }, any-spec = "*" } diff --git a/src/global/project/snapshots/pixi__global__project__manifest__tests__remove_dependency.snap b/src/global/project/snapshots/pixi__global__project__manifest__tests__remove_dependency.snap new file mode 100644 index 000000000..dc030881b --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__manifest__tests__remove_dependency.snap @@ -0,0 +1,7 @@ +--- +source: src/global/project/manifest.rs +expression: manifest.document.to_string() +--- +[envs.test-env] +channels = ["test-channel"] +dependencies = { "python" = "*"} diff --git a/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_dependency.snap b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_dependency.snap new file mode 100644 index 000000000..9899838e7 --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_dependency.snap @@ -0,0 +1,9 @@ +--- +source: src/global/project/parsed_manifest.rs +expression: manifest.unwrap_err() +--- +TOML parse error at line 6, column 9 + | +6 | PYTHON = "*" + | ^^^^^^ +duplicate dependency: python (please avoid using capitalized names for the dependencies) diff --git a/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_exposed.snap b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_exposed.snap new file mode 100644 index 000000000..8063ba668 --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__duplicate_exposed.snap @@ -0,0 +1,5 @@ +--- +source: src/global/project/parsed_manifest.rs +expression: manifest.unwrap_err() +--- +Duplicated exposed names found: python, python3 diff --git a/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__expose_pixi.snap b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__expose_pixi.snap new file mode 100644 index 000000000..53b79056f --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__expose_pixi.snap @@ -0,0 +1,9 @@ +--- +source: src/global/project/parsed_manifest.rs +expression: manifest.unwrap_err() +--- +TOML parse error at line 7, column 9 + | +7 | pixi = "python" + | ^^^^ +'pixi' is not allowed as exposed name in the map diff --git a/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__invalid_key.snap b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__invalid_key.snap new file mode 100644 index 000000000..cec8e6f14 --- /dev/null +++ b/src/global/project/snapshots/pixi__global__project__parsed_manifest__tests__invalid_key.snap @@ -0,0 +1,21 @@ +--- +source: src/global/project/parsed_manifest.rs +expression: "examples.into_iter().map(|example|\nParsedManifest::from_toml_str(example).unwrap_err().to_string()).collect::>().join(\"\\n\")" +--- +TOML parse error at line 1, column 2 + | +1 | [invalid] + | ^^^^^^^ +unknown field `invalid`, expected `version` or `envs` + +TOML parse error at line 1, column 15 + | +1 | [envs.ipython.invalid] + | ^^^^^^^ +unknown field `invalid`, expected one of `channels`, `platform`, `dependencies`, `exposed` + +TOML parse error at line 1, column 7 + | +1 | [envs."python;3".dependencies] + | ^^^^^^^^^^ +Failed to parse environment name 'python;3', please use only lowercase letters, numbers, dashes and underscores diff --git a/src/global/snapshots/pixi__global__expose__tests__expose_add_when_binary_exist.snap b/src/global/snapshots/pixi__global__expose__tests__expose_add_when_binary_exist.snap new file mode 100644 index 000000000..c345f0cd9 --- /dev/null +++ b/src/global/snapshots/pixi__global__expose__tests__expose_add_when_binary_exist.snap @@ -0,0 +1,12 @@ +--- +source: src/global/expose.rs +expression: project.manifest.document.to_string() +--- +[envs.python-3-10] +channels = ["conda-forge"] +[envs.python-3-10.dependencies] +python = "3.10" +[envs.python-3-10.exposed] +python = "python" +python3 = "python" +atuin = "atuin" diff --git a/src/global/test_data/conda-meta/_r-mutex-1.0.1-anacondar_1.json b/src/global/test_data/conda-meta/_r-mutex-1.0.1-anacondar_1.json new file mode 100644 index 000000000..831983ff7 --- /dev/null +++ b/src/global/test_data/conda-meta/_r-mutex-1.0.1-anacondar_1.json @@ -0,0 +1,27 @@ +{ + "build": "anacondar_1", + "build_number": 1, + "depends": [], + "license": "BSD", + "md5": "19f9db5f4f1b7f5ef5f6d67207f25f38", + "name": "_r-mutex", + "noarch": "generic", + "sha256": "e58f9eeb416b92b550e824bcb1b9fb1958dee69abfe3089dfd1a9173e3a0528a", + "size": 3566, + "subdir": "noarch", + "timestamp": 1562343890778, + "version": "1.0.1", + "fn": "_r-mutex-1.0.1-anacondar_1.tar.bz2", + "url": "https://conda.anaconda.org/conda-forge/noarch/_r-mutex-1.0.1-anacondar_1.tar.bz2", + "channel": "https://conda.anaconda.org/conda-forge", + "extracted_package_dir": "/home/rarts/.cache/rattler/cache/pkgs/_r-mutex-1.0.1-anacondar_1", + "files": [], + "paths_data": { + "paths_version": 1, + "paths": [] + }, + "link": { + "source": "/home/rarts/.cache/rattler/cache/pkgs/_r-mutex-1.0.1-anacondar_1", + "type": 1 + } +} diff --git a/src/global/test_data/conda-meta/non_conda_meta_data_file b/src/global/test_data/conda-meta/non_conda_meta_data_file new file mode 100644 index 000000000..fdd56858e --- /dev/null +++ b/src/global/test_data/conda-meta/non_conda_meta_data_file @@ -0,0 +1 @@ +The existence of this file shouldn't break `find_package_records` diff --git a/src/global/test_data/conda-meta/python-3.12.3-hab00c5b_0_cpython.json b/src/global/test_data/conda-meta/python-3.12.3-hab00c5b_0_cpython.json new file mode 100644 index 000000000..e5501f843 --- /dev/null +++ b/src/global/test_data/conda-meta/python-3.12.3-hab00c5b_0_cpython.json @@ -0,0 +1,15524 @@ +{ + "build": "hab00c5b_0_cpython", + "build_number": 0, + "constrains": [ + "python_abi 3.12.* *_cp312" + ], + "depends": [ + "bzip2 >=1.0.8,<2.0a0", + "ld_impl_linux-64 >=2.36.1", + "libexpat >=2.6.2,<3.0a0", + "libffi >=3.4,<4.0a0", + "libgcc-ng >=12", + "libnsl >=2.0.1,<2.1.0a0", + "libsqlite >=3.45.2,<4.0a0", + "libuuid >=2.38.1,<3.0a0", + "libxcrypt >=4.4.36", + "libzlib >=1.2.13,<2.0.0a0", + "ncurses >=6.4.20240210,<7.0a0", + "openssl >=3.2.1,<4.0a0", + "readline >=8.2,<9.0a0", + "tk >=8.6.13,<8.7.0a0", + "tzdata", + "xz >=5.2.6,<6.0a0" + ], + "license": "Python-2.0", + "md5": "2540b74d304f71d3e89c81209db4db84", + "name": "python", + "sha256": "f9865bcbff69f15fd89a33a2da12ad616e98d65ce7c83c644b92e66e5016b227", + "size": 31991381, + "subdir": "linux-64", + "timestamp": 1713208036041, + "version": "3.12.3", + "fn": "python-3.12.3-hab00c5b_0_cpython.conda", + "url": "https://conda.anaconda.org/conda-forge/linux-64/python-3.12.3-hab00c5b_0_cpython.conda", + "channel": "https://conda.anaconda.org/conda-forge", + "extracted_package_dir": "/home/rarts/.cache/rattler/cache/pkgs/python-3.12.3-hab00c5b_0_cpython", + "files": [ + "bin/2to3", + "bin/2to3-3.12", + "bin/idle3", + "bin/idle3.12", + "bin/pydoc", + "bin/pydoc3", + "bin/pydoc3.12", + "bin/python", + "bin/python3", + "bin/python3-config", + "bin/python3.1", + "bin/python3.12", + "bin/python3.12-config", + "compiler_compat/README", + "compiler_compat/ld", + "include/python3.12/Python.h", + "include/python3.12/abstract.h", + "include/python3.12/bltinmodule.h", + "include/python3.12/boolobject.h", + "include/python3.12/bytearrayobject.h", + "include/python3.12/bytesobject.h", + "include/python3.12/ceval.h", + "include/python3.12/codecs.h", + "include/python3.12/compile.h", + "include/python3.12/complexobject.h", + "include/python3.12/cpython/abstract.h", + "include/python3.12/cpython/bytearrayobject.h", + "include/python3.12/cpython/bytesobject.h", + "include/python3.12/cpython/cellobject.h", + "include/python3.12/cpython/ceval.h", + "include/python3.12/cpython/classobject.h", + "include/python3.12/cpython/code.h", + "include/python3.12/cpython/compile.h", + "include/python3.12/cpython/complexobject.h", + "include/python3.12/cpython/context.h", + "include/python3.12/cpython/descrobject.h", + "include/python3.12/cpython/dictobject.h", + "include/python3.12/cpython/fileobject.h", + "include/python3.12/cpython/fileutils.h", + "include/python3.12/cpython/floatobject.h", + "include/python3.12/cpython/frameobject.h", + "include/python3.12/cpython/funcobject.h", + "include/python3.12/cpython/genobject.h", + "include/python3.12/cpython/import.h", + "include/python3.12/cpython/initconfig.h", + "include/python3.12/cpython/interpreteridobject.h", + "include/python3.12/cpython/listobject.h", + "include/python3.12/cpython/longintrepr.h", + "include/python3.12/cpython/longobject.h", + "include/python3.12/cpython/memoryobject.h", + "include/python3.12/cpython/methodobject.h", + "include/python3.12/cpython/modsupport.h", + "include/python3.12/cpython/object.h", + "include/python3.12/cpython/objimpl.h", + "include/python3.12/cpython/odictobject.h", + "include/python3.12/cpython/picklebufobject.h", + "include/python3.12/cpython/pthread_stubs.h", + "include/python3.12/cpython/pyctype.h", + "include/python3.12/cpython/pydebug.h", + "include/python3.12/cpython/pyerrors.h", + "include/python3.12/cpython/pyfpe.h", + "include/python3.12/cpython/pyframe.h", + "include/python3.12/cpython/pylifecycle.h", + "include/python3.12/cpython/pymem.h", + "include/python3.12/cpython/pystate.h", + "include/python3.12/cpython/pythonrun.h", + "include/python3.12/cpython/pythread.h", + "include/python3.12/cpython/pytime.h", + "include/python3.12/cpython/setobject.h", + "include/python3.12/cpython/sysmodule.h", + "include/python3.12/cpython/traceback.h", + "include/python3.12/cpython/tupleobject.h", + "include/python3.12/cpython/unicodeobject.h", + "include/python3.12/cpython/warnings.h", + "include/python3.12/cpython/weakrefobject.h", + "include/python3.12/datetime.h", + "include/python3.12/descrobject.h", + "include/python3.12/dictobject.h", + "include/python3.12/dynamic_annotations.h", + "include/python3.12/enumobject.h", + "include/python3.12/errcode.h", + "include/python3.12/exports.h", + "include/python3.12/fileobject.h", + "include/python3.12/fileutils.h", + "include/python3.12/floatobject.h", + "include/python3.12/frameobject.h", + "include/python3.12/genericaliasobject.h", + "include/python3.12/import.h", + "include/python3.12/internal/pycore_abstract.h", + "include/python3.12/internal/pycore_asdl.h", + "include/python3.12/internal/pycore_ast.h", + "include/python3.12/internal/pycore_ast_state.h", + "include/python3.12/internal/pycore_atexit.h", + "include/python3.12/internal/pycore_atomic.h", + "include/python3.12/internal/pycore_atomic_funcs.h", + "include/python3.12/internal/pycore_bitutils.h", + "include/python3.12/internal/pycore_blocks_output_buffer.h", + "include/python3.12/internal/pycore_bytes_methods.h", + "include/python3.12/internal/pycore_bytesobject.h", + "include/python3.12/internal/pycore_call.h", + "include/python3.12/internal/pycore_ceval.h", + "include/python3.12/internal/pycore_ceval_state.h", + "include/python3.12/internal/pycore_code.h", + "include/python3.12/internal/pycore_compile.h", + "include/python3.12/internal/pycore_condvar.h", + "include/python3.12/internal/pycore_context.h", + "include/python3.12/internal/pycore_descrobject.h", + "include/python3.12/internal/pycore_dict.h", + "include/python3.12/internal/pycore_dict_state.h", + "include/python3.12/internal/pycore_dtoa.h", + "include/python3.12/internal/pycore_emscripten_signal.h", + "include/python3.12/internal/pycore_exceptions.h", + "include/python3.12/internal/pycore_faulthandler.h", + "include/python3.12/internal/pycore_fileutils.h", + "include/python3.12/internal/pycore_fileutils_windows.h", + "include/python3.12/internal/pycore_floatobject.h", + "include/python3.12/internal/pycore_flowgraph.h", + "include/python3.12/internal/pycore_format.h", + "include/python3.12/internal/pycore_frame.h", + "include/python3.12/internal/pycore_function.h", + "include/python3.12/internal/pycore_gc.h", + "include/python3.12/internal/pycore_genobject.h", + "include/python3.12/internal/pycore_getopt.h", + "include/python3.12/internal/pycore_gil.h", + "include/python3.12/internal/pycore_global_objects.h", + "include/python3.12/internal/pycore_global_objects_fini_generated.h", + "include/python3.12/internal/pycore_global_strings.h", + "include/python3.12/internal/pycore_hamt.h", + "include/python3.12/internal/pycore_hashtable.h", + "include/python3.12/internal/pycore_import.h", + "include/python3.12/internal/pycore_initconfig.h", + "include/python3.12/internal/pycore_instruments.h", + "include/python3.12/internal/pycore_interp.h", + "include/python3.12/internal/pycore_intrinsics.h", + "include/python3.12/internal/pycore_list.h", + "include/python3.12/internal/pycore_long.h", + "include/python3.12/internal/pycore_memoryobject.h", + "include/python3.12/internal/pycore_moduleobject.h", + "include/python3.12/internal/pycore_namespace.h", + "include/python3.12/internal/pycore_object.h", + "include/python3.12/internal/pycore_object_state.h", + "include/python3.12/internal/pycore_obmalloc.h", + "include/python3.12/internal/pycore_obmalloc_init.h", + "include/python3.12/internal/pycore_opcode.h", + "include/python3.12/internal/pycore_opcode_utils.h", + "include/python3.12/internal/pycore_parser.h", + "include/python3.12/internal/pycore_pathconfig.h", + "include/python3.12/internal/pycore_pyarena.h", + "include/python3.12/internal/pycore_pyerrors.h", + "include/python3.12/internal/pycore_pyhash.h", + "include/python3.12/internal/pycore_pylifecycle.h", + "include/python3.12/internal/pycore_pymath.h", + "include/python3.12/internal/pycore_pymem.h", + "include/python3.12/internal/pycore_pymem_init.h", + "include/python3.12/internal/pycore_pystate.h", + "include/python3.12/internal/pycore_pythread.h", + "include/python3.12/internal/pycore_range.h", + "include/python3.12/internal/pycore_runtime.h", + "include/python3.12/internal/pycore_runtime_init.h", + "include/python3.12/internal/pycore_runtime_init_generated.h", + "include/python3.12/internal/pycore_signal.h", + "include/python3.12/internal/pycore_sliceobject.h", + "include/python3.12/internal/pycore_strhex.h", + "include/python3.12/internal/pycore_structseq.h", + "include/python3.12/internal/pycore_symtable.h", + "include/python3.12/internal/pycore_sysmodule.h", + "include/python3.12/internal/pycore_time.h", + "include/python3.12/internal/pycore_token.h", + "include/python3.12/internal/pycore_traceback.h", + "include/python3.12/internal/pycore_tracemalloc.h", + "include/python3.12/internal/pycore_tuple.h", + "include/python3.12/internal/pycore_typeobject.h", + "include/python3.12/internal/pycore_typevarobject.h", + "include/python3.12/internal/pycore_ucnhash.h", + "include/python3.12/internal/pycore_unicodeobject.h", + "include/python3.12/internal/pycore_unicodeobject_generated.h", + "include/python3.12/internal/pycore_unionobject.h", + "include/python3.12/internal/pycore_warnings.h", + "include/python3.12/interpreteridobject.h", + "include/python3.12/intrcheck.h", + "include/python3.12/iterobject.h", + "include/python3.12/listobject.h", + "include/python3.12/longobject.h", + "include/python3.12/marshal.h", + "include/python3.12/memoryobject.h", + "include/python3.12/methodobject.h", + "include/python3.12/modsupport.h", + "include/python3.12/moduleobject.h", + "include/python3.12/object.h", + "include/python3.12/objimpl.h", + "include/python3.12/opcode.h", + "include/python3.12/osdefs.h", + "include/python3.12/osmodule.h", + "include/python3.12/patchlevel.h", + "include/python3.12/py_curses.h", + "include/python3.12/pybuffer.h", + "include/python3.12/pycapsule.h", + "include/python3.12/pyconfig.h", + "include/python3.12/pydtrace.h", + "include/python3.12/pyerrors.h", + "include/python3.12/pyexpat.h", + "include/python3.12/pyframe.h", + "include/python3.12/pyhash.h", + "include/python3.12/pylifecycle.h", + "include/python3.12/pymacconfig.h", + "include/python3.12/pymacro.h", + "include/python3.12/pymath.h", + "include/python3.12/pymem.h", + "include/python3.12/pyport.h", + "include/python3.12/pystate.h", + "include/python3.12/pystats.h", + "include/python3.12/pystrcmp.h", + "include/python3.12/pystrtod.h", + "include/python3.12/pythonrun.h", + "include/python3.12/pythread.h", + "include/python3.12/pytypedefs.h", + "include/python3.12/rangeobject.h", + "include/python3.12/setobject.h", + "include/python3.12/sliceobject.h", + "include/python3.12/structmember.h", + "include/python3.12/structseq.h", + "include/python3.12/sysmodule.h", + "include/python3.12/traceback.h", + "include/python3.12/tracemalloc.h", + "include/python3.12/tupleobject.h", + "include/python3.12/typeslots.h", + "include/python3.12/unicodeobject.h", + "include/python3.12/warnings.h", + "include/python3.12/weakrefobject.h", + "lib/libpython3.12.so", + "lib/libpython3.12.so.1.0", + "lib/libpython3.so", + "lib/pkgconfig/python-3.12-embed.pc", + "lib/pkgconfig/python-3.12.pc", + "lib/pkgconfig/python3-embed.pc", + "lib/pkgconfig/python3.pc", + "lib/python3.1", + "lib/python3.12/LICENSE.txt", + "lib/python3.12/__future__.py", + "lib/python3.12/__hello__.py", + "lib/python3.12/__phello__/__init__.py", + "lib/python3.12/__phello__/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/__phello__/__pycache__/spam.cpython-312.pyc", + "lib/python3.12/__phello__/spam.py", + "lib/python3.12/__pycache__/__future__.cpython-312.pyc", + "lib/python3.12/__pycache__/__hello__.cpython-312.pyc", + "lib/python3.12/__pycache__/_aix_support.cpython-312.pyc", + "lib/python3.12/__pycache__/_collections_abc.cpython-312.pyc", + "lib/python3.12/__pycache__/_compat_pickle.cpython-312.pyc", + "lib/python3.12/__pycache__/_compression.cpython-312.pyc", + "lib/python3.12/__pycache__/_markupbase.cpython-312.pyc", + "lib/python3.12/__pycache__/_osx_support.cpython-312.pyc", + "lib/python3.12/__pycache__/_py_abc.cpython-312.pyc", + "lib/python3.12/__pycache__/_pydatetime.cpython-312.pyc", + "lib/python3.12/__pycache__/_pydecimal.cpython-312.pyc", + "lib/python3.12/__pycache__/_pyio.cpython-312.pyc", + "lib/python3.12/__pycache__/_pylong.cpython-312.pyc", + "lib/python3.12/__pycache__/_sitebuiltins.cpython-312.pyc", + "lib/python3.12/__pycache__/_strptime.cpython-312.pyc", + "lib/python3.12/__pycache__/_sysconfigdata__linux_x86_64-linux-gnu.cpython-312.pyc", + "lib/python3.12/__pycache__/_sysconfigdata_x86_64_conda_cos6_linux_gnu.cpython-312.pyc", + "lib/python3.12/__pycache__/_sysconfigdata_x86_64_conda_linux_gnu.cpython-312.pyc", + "lib/python3.12/__pycache__/_threading_local.cpython-312.pyc", + "lib/python3.12/__pycache__/_weakrefset.cpython-312.pyc", + "lib/python3.12/__pycache__/abc.cpython-312.pyc", + "lib/python3.12/__pycache__/aifc.cpython-312.pyc", + "lib/python3.12/__pycache__/antigravity.cpython-312.pyc", + "lib/python3.12/__pycache__/argparse.cpython-312.pyc", + "lib/python3.12/__pycache__/ast.cpython-312.pyc", + "lib/python3.12/__pycache__/base64.cpython-312.pyc", + "lib/python3.12/__pycache__/bdb.cpython-312.pyc", + "lib/python3.12/__pycache__/bisect.cpython-312.pyc", + "lib/python3.12/__pycache__/bz2.cpython-312.pyc", + "lib/python3.12/__pycache__/cProfile.cpython-312.pyc", + "lib/python3.12/__pycache__/calendar.cpython-312.pyc", + "lib/python3.12/__pycache__/cgi.cpython-312.pyc", + "lib/python3.12/__pycache__/cgitb.cpython-312.pyc", + "lib/python3.12/__pycache__/chunk.cpython-312.pyc", + "lib/python3.12/__pycache__/cmd.cpython-312.pyc", + "lib/python3.12/__pycache__/code.cpython-312.pyc", + "lib/python3.12/__pycache__/codecs.cpython-312.pyc", + "lib/python3.12/__pycache__/codeop.cpython-312.pyc", + "lib/python3.12/__pycache__/colorsys.cpython-312.pyc", + "lib/python3.12/__pycache__/compileall.cpython-312.pyc", + "lib/python3.12/__pycache__/configparser.cpython-312.pyc", + "lib/python3.12/__pycache__/contextlib.cpython-312.pyc", + "lib/python3.12/__pycache__/contextvars.cpython-312.pyc", + "lib/python3.12/__pycache__/copy.cpython-312.pyc", + "lib/python3.12/__pycache__/copyreg.cpython-312.pyc", + "lib/python3.12/__pycache__/crypt.cpython-312.pyc", + "lib/python3.12/__pycache__/csv.cpython-312.pyc", + "lib/python3.12/__pycache__/dataclasses.cpython-312.pyc", + "lib/python3.12/__pycache__/datetime.cpython-312.pyc", + "lib/python3.12/__pycache__/decimal.cpython-312.pyc", + "lib/python3.12/__pycache__/difflib.cpython-312.pyc", + "lib/python3.12/__pycache__/dis.cpython-312.pyc", + "lib/python3.12/__pycache__/doctest.cpython-312.pyc", + "lib/python3.12/__pycache__/enum.cpython-312.pyc", + "lib/python3.12/__pycache__/filecmp.cpython-312.pyc", + "lib/python3.12/__pycache__/fileinput.cpython-312.pyc", + "lib/python3.12/__pycache__/fnmatch.cpython-312.pyc", + "lib/python3.12/__pycache__/fractions.cpython-312.pyc", + "lib/python3.12/__pycache__/ftplib.cpython-312.pyc", + "lib/python3.12/__pycache__/functools.cpython-312.pyc", + "lib/python3.12/__pycache__/genericpath.cpython-312.pyc", + "lib/python3.12/__pycache__/getopt.cpython-312.pyc", + "lib/python3.12/__pycache__/getpass.cpython-312.pyc", + "lib/python3.12/__pycache__/gettext.cpython-312.pyc", + "lib/python3.12/__pycache__/glob.cpython-312.pyc", + "lib/python3.12/__pycache__/graphlib.cpython-312.pyc", + "lib/python3.12/__pycache__/gzip.cpython-312.pyc", + "lib/python3.12/__pycache__/hashlib.cpython-312.pyc", + "lib/python3.12/__pycache__/heapq.cpython-312.pyc", + "lib/python3.12/__pycache__/hmac.cpython-312.pyc", + "lib/python3.12/__pycache__/imaplib.cpython-312.pyc", + "lib/python3.12/__pycache__/imghdr.cpython-312.pyc", + "lib/python3.12/__pycache__/inspect.cpython-312.pyc", + "lib/python3.12/__pycache__/io.cpython-312.pyc", + "lib/python3.12/__pycache__/ipaddress.cpython-312.pyc", + "lib/python3.12/__pycache__/keyword.cpython-312.pyc", + "lib/python3.12/__pycache__/linecache.cpython-312.pyc", + "lib/python3.12/__pycache__/locale.cpython-312.pyc", + "lib/python3.12/__pycache__/lzma.cpython-312.pyc", + "lib/python3.12/__pycache__/mailbox.cpython-312.pyc", + "lib/python3.12/__pycache__/mailcap.cpython-312.pyc", + "lib/python3.12/__pycache__/mimetypes.cpython-312.pyc", + "lib/python3.12/__pycache__/modulefinder.cpython-312.pyc", + "lib/python3.12/__pycache__/netrc.cpython-312.pyc", + "lib/python3.12/__pycache__/nntplib.cpython-312.pyc", + "lib/python3.12/__pycache__/ntpath.cpython-312.pyc", + "lib/python3.12/__pycache__/nturl2path.cpython-312.pyc", + "lib/python3.12/__pycache__/numbers.cpython-312.pyc", + "lib/python3.12/__pycache__/opcode.cpython-312.pyc", + "lib/python3.12/__pycache__/operator.cpython-312.pyc", + "lib/python3.12/__pycache__/optparse.cpython-312.pyc", + "lib/python3.12/__pycache__/os.cpython-312.pyc", + "lib/python3.12/__pycache__/pathlib.cpython-312.pyc", + "lib/python3.12/__pycache__/pdb.cpython-312.pyc", + "lib/python3.12/__pycache__/pickle.cpython-312.pyc", + "lib/python3.12/__pycache__/pickletools.cpython-312.pyc", + "lib/python3.12/__pycache__/pipes.cpython-312.pyc", + "lib/python3.12/__pycache__/pkgutil.cpython-312.pyc", + "lib/python3.12/__pycache__/platform.cpython-312.pyc", + "lib/python3.12/__pycache__/plistlib.cpython-312.pyc", + "lib/python3.12/__pycache__/poplib.cpython-312.pyc", + "lib/python3.12/__pycache__/posixpath.cpython-312.pyc", + "lib/python3.12/__pycache__/pprint.cpython-312.pyc", + "lib/python3.12/__pycache__/profile.cpython-312.pyc", + "lib/python3.12/__pycache__/pstats.cpython-312.pyc", + "lib/python3.12/__pycache__/pty.cpython-312.pyc", + "lib/python3.12/__pycache__/py_compile.cpython-312.pyc", + "lib/python3.12/__pycache__/pyclbr.cpython-312.pyc", + "lib/python3.12/__pycache__/pydoc.cpython-312.pyc", + "lib/python3.12/__pycache__/queue.cpython-312.pyc", + "lib/python3.12/__pycache__/quopri.cpython-312.pyc", + "lib/python3.12/__pycache__/random.cpython-312.pyc", + "lib/python3.12/__pycache__/reprlib.cpython-312.pyc", + "lib/python3.12/__pycache__/rlcompleter.cpython-312.pyc", + "lib/python3.12/__pycache__/runpy.cpython-312.pyc", + "lib/python3.12/__pycache__/sched.cpython-312.pyc", + "lib/python3.12/__pycache__/secrets.cpython-312.pyc", + "lib/python3.12/__pycache__/selectors.cpython-312.pyc", + "lib/python3.12/__pycache__/shelve.cpython-312.pyc", + "lib/python3.12/__pycache__/shlex.cpython-312.pyc", + "lib/python3.12/__pycache__/shutil.cpython-312.pyc", + "lib/python3.12/__pycache__/signal.cpython-312.pyc", + "lib/python3.12/__pycache__/site.cpython-312.pyc", + "lib/python3.12/__pycache__/smtplib.cpython-312.pyc", + "lib/python3.12/__pycache__/sndhdr.cpython-312.pyc", + "lib/python3.12/__pycache__/socket.cpython-312.pyc", + "lib/python3.12/__pycache__/socketserver.cpython-312.pyc", + "lib/python3.12/__pycache__/sre_compile.cpython-312.pyc", + "lib/python3.12/__pycache__/sre_constants.cpython-312.pyc", + "lib/python3.12/__pycache__/sre_parse.cpython-312.pyc", + "lib/python3.12/__pycache__/ssl.cpython-312.pyc", + "lib/python3.12/__pycache__/stat.cpython-312.pyc", + "lib/python3.12/__pycache__/statistics.cpython-312.pyc", + "lib/python3.12/__pycache__/string.cpython-312.pyc", + "lib/python3.12/__pycache__/stringprep.cpython-312.pyc", + "lib/python3.12/__pycache__/struct.cpython-312.pyc", + "lib/python3.12/__pycache__/subprocess.cpython-312.pyc", + "lib/python3.12/__pycache__/sunau.cpython-312.pyc", + "lib/python3.12/__pycache__/symtable.cpython-312.pyc", + "lib/python3.12/__pycache__/sysconfig.cpython-312.pyc", + "lib/python3.12/__pycache__/tabnanny.cpython-312.pyc", + "lib/python3.12/__pycache__/tarfile.cpython-312.pyc", + "lib/python3.12/__pycache__/telnetlib.cpython-312.pyc", + "lib/python3.12/__pycache__/tempfile.cpython-312.pyc", + "lib/python3.12/__pycache__/textwrap.cpython-312.pyc", + "lib/python3.12/__pycache__/this.cpython-312.pyc", + "lib/python3.12/__pycache__/threading.cpython-312.pyc", + "lib/python3.12/__pycache__/timeit.cpython-312.pyc", + "lib/python3.12/__pycache__/token.cpython-312.pyc", + "lib/python3.12/__pycache__/tokenize.cpython-312.pyc", + "lib/python3.12/__pycache__/trace.cpython-312.pyc", + "lib/python3.12/__pycache__/traceback.cpython-312.pyc", + "lib/python3.12/__pycache__/tracemalloc.cpython-312.pyc", + "lib/python3.12/__pycache__/tty.cpython-312.pyc", + "lib/python3.12/__pycache__/turtle.cpython-312.pyc", + "lib/python3.12/__pycache__/types.cpython-312.pyc", + "lib/python3.12/__pycache__/typing.cpython-312.pyc", + "lib/python3.12/__pycache__/uu.cpython-312.pyc", + "lib/python3.12/__pycache__/uuid.cpython-312.pyc", + "lib/python3.12/__pycache__/warnings.cpython-312.pyc", + "lib/python3.12/__pycache__/wave.cpython-312.pyc", + "lib/python3.12/__pycache__/weakref.cpython-312.pyc", + "lib/python3.12/__pycache__/webbrowser.cpython-312.pyc", + "lib/python3.12/__pycache__/xdrlib.cpython-312.pyc", + "lib/python3.12/__pycache__/zipapp.cpython-312.pyc", + "lib/python3.12/__pycache__/zipimport.cpython-312.pyc", + "lib/python3.12/_aix_support.py", + "lib/python3.12/_collections_abc.py", + "lib/python3.12/_compat_pickle.py", + "lib/python3.12/_compression.py", + "lib/python3.12/_markupbase.py", + "lib/python3.12/_osx_support.py", + "lib/python3.12/_py_abc.py", + "lib/python3.12/_pydatetime.py", + "lib/python3.12/_pydecimal.py", + "lib/python3.12/_pyio.py", + "lib/python3.12/_pylong.py", + "lib/python3.12/_sitebuiltins.py", + "lib/python3.12/_strptime.py", + "lib/python3.12/_sysconfigdata__linux_x86_64-linux-gnu.py", + "lib/python3.12/_sysconfigdata__linux_x86_64-linux-gnu.py.orig", + "lib/python3.12/_sysconfigdata_x86_64_conda_cos6_linux_gnu.py", + "lib/python3.12/_sysconfigdata_x86_64_conda_linux_gnu.py", + "lib/python3.12/_threading_local.py", + "lib/python3.12/_weakrefset.py", + "lib/python3.12/abc.py", + "lib/python3.12/aifc.py", + "lib/python3.12/antigravity.py", + "lib/python3.12/argparse.py", + "lib/python3.12/ast.py", + "lib/python3.12/asyncio/__init__.py", + "lib/python3.12/asyncio/__main__.py", + "lib/python3.12/asyncio/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/base_events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/base_futures.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/base_subprocess.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/base_tasks.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/constants.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/coroutines.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/exceptions.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/format_helpers.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/futures.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/locks.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/log.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/mixins.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/proactor_events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/protocols.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/queues.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/runners.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/selector_events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/sslproto.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/staggered.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/streams.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/subprocess.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/taskgroups.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/tasks.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/threads.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/timeouts.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/transports.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/trsock.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/unix_events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/windows_events.cpython-312.pyc", + "lib/python3.12/asyncio/__pycache__/windows_utils.cpython-312.pyc", + "lib/python3.12/asyncio/base_events.py", + "lib/python3.12/asyncio/base_futures.py", + "lib/python3.12/asyncio/base_subprocess.py", + "lib/python3.12/asyncio/base_tasks.py", + "lib/python3.12/asyncio/constants.py", + "lib/python3.12/asyncio/coroutines.py", + "lib/python3.12/asyncio/events.py", + "lib/python3.12/asyncio/exceptions.py", + "lib/python3.12/asyncio/format_helpers.py", + "lib/python3.12/asyncio/futures.py", + "lib/python3.12/asyncio/locks.py", + "lib/python3.12/asyncio/log.py", + "lib/python3.12/asyncio/mixins.py", + "lib/python3.12/asyncio/proactor_events.py", + "lib/python3.12/asyncio/protocols.py", + "lib/python3.12/asyncio/queues.py", + "lib/python3.12/asyncio/runners.py", + "lib/python3.12/asyncio/selector_events.py", + "lib/python3.12/asyncio/sslproto.py", + "lib/python3.12/asyncio/staggered.py", + "lib/python3.12/asyncio/streams.py", + "lib/python3.12/asyncio/subprocess.py", + "lib/python3.12/asyncio/taskgroups.py", + "lib/python3.12/asyncio/tasks.py", + "lib/python3.12/asyncio/threads.py", + "lib/python3.12/asyncio/timeouts.py", + "lib/python3.12/asyncio/transports.py", + "lib/python3.12/asyncio/trsock.py", + "lib/python3.12/asyncio/unix_events.py", + "lib/python3.12/asyncio/windows_events.py", + "lib/python3.12/asyncio/windows_utils.py", + "lib/python3.12/base64.py", + "lib/python3.12/bdb.py", + "lib/python3.12/bisect.py", + "lib/python3.12/bz2.py", + "lib/python3.12/cProfile.py", + "lib/python3.12/calendar.py", + "lib/python3.12/cgi.py", + "lib/python3.12/cgitb.py", + "lib/python3.12/chunk.py", + "lib/python3.12/cmd.py", + "lib/python3.12/code.py", + "lib/python3.12/codecs.py", + "lib/python3.12/codeop.py", + "lib/python3.12/collections/__init__.py", + "lib/python3.12/collections/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/collections/__pycache__/abc.cpython-312.pyc", + "lib/python3.12/collections/abc.py", + "lib/python3.12/colorsys.py", + "lib/python3.12/compileall.py", + "lib/python3.12/concurrent/__init__.py", + "lib/python3.12/concurrent/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/concurrent/futures/__init__.py", + "lib/python3.12/concurrent/futures/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/concurrent/futures/__pycache__/_base.cpython-312.pyc", + "lib/python3.12/concurrent/futures/__pycache__/process.cpython-312.pyc", + "lib/python3.12/concurrent/futures/__pycache__/thread.cpython-312.pyc", + "lib/python3.12/concurrent/futures/_base.py", + "lib/python3.12/concurrent/futures/process.py", + "lib/python3.12/concurrent/futures/thread.py", + "lib/python3.12/config-3.12-x86_64-linux-gnu/Makefile", + "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup", + "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.bootstrap", + "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.local", + "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.stdlib", + "lib/python3.12/config-3.12-x86_64-linux-gnu/__pycache__/python-config.cpython-312.pyc", + "lib/python3.12/config-3.12-x86_64-linux-gnu/config.c", + "lib/python3.12/config-3.12-x86_64-linux-gnu/config.c.in", + "lib/python3.12/config-3.12-x86_64-linux-gnu/install-sh", + "lib/python3.12/config-3.12-x86_64-linux-gnu/makesetup", + "lib/python3.12/config-3.12-x86_64-linux-gnu/python-config.py", + "lib/python3.12/config-3.12-x86_64-linux-gnu/python.o", + "lib/python3.12/configparser.py", + "lib/python3.12/contextlib.py", + "lib/python3.12/contextvars.py", + "lib/python3.12/copy.py", + "lib/python3.12/copyreg.py", + "lib/python3.12/crypt.py", + "lib/python3.12/csv.py", + "lib/python3.12/ctypes/__init__.py", + "lib/python3.12/ctypes/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/ctypes/__pycache__/_aix.cpython-312.pyc", + "lib/python3.12/ctypes/__pycache__/_endian.cpython-312.pyc", + "lib/python3.12/ctypes/__pycache__/util.cpython-312.pyc", + "lib/python3.12/ctypes/__pycache__/wintypes.cpython-312.pyc", + "lib/python3.12/ctypes/_aix.py", + "lib/python3.12/ctypes/_endian.py", + "lib/python3.12/ctypes/macholib/README.ctypes", + "lib/python3.12/ctypes/macholib/__init__.py", + "lib/python3.12/ctypes/macholib/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/ctypes/macholib/__pycache__/dyld.cpython-312.pyc", + "lib/python3.12/ctypes/macholib/__pycache__/dylib.cpython-312.pyc", + "lib/python3.12/ctypes/macholib/__pycache__/framework.cpython-312.pyc", + "lib/python3.12/ctypes/macholib/dyld.py", + "lib/python3.12/ctypes/macholib/dylib.py", + "lib/python3.12/ctypes/macholib/fetch_macholib", + "lib/python3.12/ctypes/macholib/fetch_macholib.bat", + "lib/python3.12/ctypes/macholib/framework.py", + "lib/python3.12/ctypes/util.py", + "lib/python3.12/ctypes/wintypes.py", + "lib/python3.12/curses/__init__.py", + "lib/python3.12/curses/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/curses/__pycache__/ascii.cpython-312.pyc", + "lib/python3.12/curses/__pycache__/has_key.cpython-312.pyc", + "lib/python3.12/curses/__pycache__/panel.cpython-312.pyc", + "lib/python3.12/curses/__pycache__/textpad.cpython-312.pyc", + "lib/python3.12/curses/ascii.py", + "lib/python3.12/curses/has_key.py", + "lib/python3.12/curses/panel.py", + "lib/python3.12/curses/textpad.py", + "lib/python3.12/dataclasses.py", + "lib/python3.12/datetime.py", + "lib/python3.12/dbm/__init__.py", + "lib/python3.12/dbm/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/dbm/__pycache__/dumb.cpython-312.pyc", + "lib/python3.12/dbm/__pycache__/gnu.cpython-312.pyc", + "lib/python3.12/dbm/__pycache__/ndbm.cpython-312.pyc", + "lib/python3.12/dbm/dumb.py", + "lib/python3.12/dbm/gnu.py", + "lib/python3.12/dbm/ndbm.py", + "lib/python3.12/decimal.py", + "lib/python3.12/difflib.py", + "lib/python3.12/dis.py", + "lib/python3.12/doctest.py", + "lib/python3.12/email/__init__.py", + "lib/python3.12/email/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/email/__pycache__/_encoded_words.cpython-312.pyc", + "lib/python3.12/email/__pycache__/_header_value_parser.cpython-312.pyc", + "lib/python3.12/email/__pycache__/_parseaddr.cpython-312.pyc", + "lib/python3.12/email/__pycache__/_policybase.cpython-312.pyc", + "lib/python3.12/email/__pycache__/base64mime.cpython-312.pyc", + "lib/python3.12/email/__pycache__/charset.cpython-312.pyc", + "lib/python3.12/email/__pycache__/contentmanager.cpython-312.pyc", + "lib/python3.12/email/__pycache__/encoders.cpython-312.pyc", + "lib/python3.12/email/__pycache__/errors.cpython-312.pyc", + "lib/python3.12/email/__pycache__/feedparser.cpython-312.pyc", + "lib/python3.12/email/__pycache__/generator.cpython-312.pyc", + "lib/python3.12/email/__pycache__/header.cpython-312.pyc", + "lib/python3.12/email/__pycache__/headerregistry.cpython-312.pyc", + "lib/python3.12/email/__pycache__/iterators.cpython-312.pyc", + "lib/python3.12/email/__pycache__/message.cpython-312.pyc", + "lib/python3.12/email/__pycache__/parser.cpython-312.pyc", + "lib/python3.12/email/__pycache__/policy.cpython-312.pyc", + "lib/python3.12/email/__pycache__/quoprimime.cpython-312.pyc", + "lib/python3.12/email/__pycache__/utils.cpython-312.pyc", + "lib/python3.12/email/_encoded_words.py", + "lib/python3.12/email/_header_value_parser.py", + "lib/python3.12/email/_parseaddr.py", + "lib/python3.12/email/_policybase.py", + "lib/python3.12/email/architecture.rst", + "lib/python3.12/email/base64mime.py", + "lib/python3.12/email/charset.py", + "lib/python3.12/email/contentmanager.py", + "lib/python3.12/email/encoders.py", + "lib/python3.12/email/errors.py", + "lib/python3.12/email/feedparser.py", + "lib/python3.12/email/generator.py", + "lib/python3.12/email/header.py", + "lib/python3.12/email/headerregistry.py", + "lib/python3.12/email/iterators.py", + "lib/python3.12/email/message.py", + "lib/python3.12/email/mime/__init__.py", + "lib/python3.12/email/mime/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/application.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/audio.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/base.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/image.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/message.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/multipart.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/nonmultipart.cpython-312.pyc", + "lib/python3.12/email/mime/__pycache__/text.cpython-312.pyc", + "lib/python3.12/email/mime/application.py", + "lib/python3.12/email/mime/audio.py", + "lib/python3.12/email/mime/base.py", + "lib/python3.12/email/mime/image.py", + "lib/python3.12/email/mime/message.py", + "lib/python3.12/email/mime/multipart.py", + "lib/python3.12/email/mime/nonmultipart.py", + "lib/python3.12/email/mime/text.py", + "lib/python3.12/email/parser.py", + "lib/python3.12/email/policy.py", + "lib/python3.12/email/quoprimime.py", + "lib/python3.12/email/utils.py", + "lib/python3.12/encodings/__init__.py", + "lib/python3.12/encodings/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/aliases.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/ascii.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/base64_codec.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/big5.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/big5hkscs.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/bz2_codec.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/charmap.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp037.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1006.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1026.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1125.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1140.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1250.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1251.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1252.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1253.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1254.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1255.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1256.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1257.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp1258.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp273.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp424.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp437.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp500.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp720.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp737.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp775.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp850.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp852.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp855.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp856.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp857.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp858.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp860.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp861.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp862.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp863.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp864.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp865.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp866.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp869.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp874.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp875.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp932.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp949.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/cp950.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/euc_jis_2004.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/euc_jisx0213.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/euc_jp.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/euc_kr.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/gb18030.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/gb2312.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/gbk.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/hex_codec.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/hp_roman8.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/hz.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/idna.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp_1.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp_2.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp_2004.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp_3.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_jp_ext.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso2022_kr.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_1.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_10.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_11.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_13.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_14.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_15.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_16.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_2.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_3.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_4.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_5.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_6.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_7.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_8.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/iso8859_9.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/johab.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/koi8_r.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/koi8_t.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/koi8_u.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/kz1048.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/latin_1.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_arabic.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_croatian.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_cyrillic.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_farsi.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_greek.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_iceland.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_latin2.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_roman.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_romanian.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mac_turkish.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/mbcs.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/oem.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/palmos.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/ptcp154.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/punycode.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/quopri_codec.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/raw_unicode_escape.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/rot_13.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/shift_jis.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/shift_jis_2004.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/shift_jisx0213.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/tis_620.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/undefined.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/unicode_escape.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_16.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_16_be.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_16_le.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_32.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_32_be.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_32_le.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_7.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_8.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/utf_8_sig.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/uu_codec.cpython-312.pyc", + "lib/python3.12/encodings/__pycache__/zlib_codec.cpython-312.pyc", + "lib/python3.12/encodings/aliases.py", + "lib/python3.12/encodings/ascii.py", + "lib/python3.12/encodings/base64_codec.py", + "lib/python3.12/encodings/big5.py", + "lib/python3.12/encodings/big5hkscs.py", + "lib/python3.12/encodings/bz2_codec.py", + "lib/python3.12/encodings/charmap.py", + "lib/python3.12/encodings/cp037.py", + "lib/python3.12/encodings/cp1006.py", + "lib/python3.12/encodings/cp1026.py", + "lib/python3.12/encodings/cp1125.py", + "lib/python3.12/encodings/cp1140.py", + "lib/python3.12/encodings/cp1250.py", + "lib/python3.12/encodings/cp1251.py", + "lib/python3.12/encodings/cp1252.py", + "lib/python3.12/encodings/cp1253.py", + "lib/python3.12/encodings/cp1254.py", + "lib/python3.12/encodings/cp1255.py", + "lib/python3.12/encodings/cp1256.py", + "lib/python3.12/encodings/cp1257.py", + "lib/python3.12/encodings/cp1258.py", + "lib/python3.12/encodings/cp273.py", + "lib/python3.12/encodings/cp424.py", + "lib/python3.12/encodings/cp437.py", + "lib/python3.12/encodings/cp500.py", + "lib/python3.12/encodings/cp720.py", + "lib/python3.12/encodings/cp737.py", + "lib/python3.12/encodings/cp775.py", + "lib/python3.12/encodings/cp850.py", + "lib/python3.12/encodings/cp852.py", + "lib/python3.12/encodings/cp855.py", + "lib/python3.12/encodings/cp856.py", + "lib/python3.12/encodings/cp857.py", + "lib/python3.12/encodings/cp858.py", + "lib/python3.12/encodings/cp860.py", + "lib/python3.12/encodings/cp861.py", + "lib/python3.12/encodings/cp862.py", + "lib/python3.12/encodings/cp863.py", + "lib/python3.12/encodings/cp864.py", + "lib/python3.12/encodings/cp865.py", + "lib/python3.12/encodings/cp866.py", + "lib/python3.12/encodings/cp869.py", + "lib/python3.12/encodings/cp874.py", + "lib/python3.12/encodings/cp875.py", + "lib/python3.12/encodings/cp932.py", + "lib/python3.12/encodings/cp949.py", + "lib/python3.12/encodings/cp950.py", + "lib/python3.12/encodings/euc_jis_2004.py", + "lib/python3.12/encodings/euc_jisx0213.py", + "lib/python3.12/encodings/euc_jp.py", + "lib/python3.12/encodings/euc_kr.py", + "lib/python3.12/encodings/gb18030.py", + "lib/python3.12/encodings/gb2312.py", + "lib/python3.12/encodings/gbk.py", + "lib/python3.12/encodings/hex_codec.py", + "lib/python3.12/encodings/hp_roman8.py", + "lib/python3.12/encodings/hz.py", + "lib/python3.12/encodings/idna.py", + "lib/python3.12/encodings/iso2022_jp.py", + "lib/python3.12/encodings/iso2022_jp_1.py", + "lib/python3.12/encodings/iso2022_jp_2.py", + "lib/python3.12/encodings/iso2022_jp_2004.py", + "lib/python3.12/encodings/iso2022_jp_3.py", + "lib/python3.12/encodings/iso2022_jp_ext.py", + "lib/python3.12/encodings/iso2022_kr.py", + "lib/python3.12/encodings/iso8859_1.py", + "lib/python3.12/encodings/iso8859_10.py", + "lib/python3.12/encodings/iso8859_11.py", + "lib/python3.12/encodings/iso8859_13.py", + "lib/python3.12/encodings/iso8859_14.py", + "lib/python3.12/encodings/iso8859_15.py", + "lib/python3.12/encodings/iso8859_16.py", + "lib/python3.12/encodings/iso8859_2.py", + "lib/python3.12/encodings/iso8859_3.py", + "lib/python3.12/encodings/iso8859_4.py", + "lib/python3.12/encodings/iso8859_5.py", + "lib/python3.12/encodings/iso8859_6.py", + "lib/python3.12/encodings/iso8859_7.py", + "lib/python3.12/encodings/iso8859_8.py", + "lib/python3.12/encodings/iso8859_9.py", + "lib/python3.12/encodings/johab.py", + "lib/python3.12/encodings/koi8_r.py", + "lib/python3.12/encodings/koi8_t.py", + "lib/python3.12/encodings/koi8_u.py", + "lib/python3.12/encodings/kz1048.py", + "lib/python3.12/encodings/latin_1.py", + "lib/python3.12/encodings/mac_arabic.py", + "lib/python3.12/encodings/mac_croatian.py", + "lib/python3.12/encodings/mac_cyrillic.py", + "lib/python3.12/encodings/mac_farsi.py", + "lib/python3.12/encodings/mac_greek.py", + "lib/python3.12/encodings/mac_iceland.py", + "lib/python3.12/encodings/mac_latin2.py", + "lib/python3.12/encodings/mac_roman.py", + "lib/python3.12/encodings/mac_romanian.py", + "lib/python3.12/encodings/mac_turkish.py", + "lib/python3.12/encodings/mbcs.py", + "lib/python3.12/encodings/oem.py", + "lib/python3.12/encodings/palmos.py", + "lib/python3.12/encodings/ptcp154.py", + "lib/python3.12/encodings/punycode.py", + "lib/python3.12/encodings/quopri_codec.py", + "lib/python3.12/encodings/raw_unicode_escape.py", + "lib/python3.12/encodings/rot_13.py", + "lib/python3.12/encodings/shift_jis.py", + "lib/python3.12/encodings/shift_jis_2004.py", + "lib/python3.12/encodings/shift_jisx0213.py", + "lib/python3.12/encodings/tis_620.py", + "lib/python3.12/encodings/undefined.py", + "lib/python3.12/encodings/unicode_escape.py", + "lib/python3.12/encodings/utf_16.py", + "lib/python3.12/encodings/utf_16_be.py", + "lib/python3.12/encodings/utf_16_le.py", + "lib/python3.12/encodings/utf_32.py", + "lib/python3.12/encodings/utf_32_be.py", + "lib/python3.12/encodings/utf_32_le.py", + "lib/python3.12/encodings/utf_7.py", + "lib/python3.12/encodings/utf_8.py", + "lib/python3.12/encodings/utf_8_sig.py", + "lib/python3.12/encodings/uu_codec.py", + "lib/python3.12/encodings/zlib_codec.py", + "lib/python3.12/ensurepip/__init__.py", + "lib/python3.12/ensurepip/__main__.py", + "lib/python3.12/ensurepip/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/ensurepip/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/ensurepip/__pycache__/_uninstall.cpython-312.pyc", + "lib/python3.12/ensurepip/_bundled/pip-24.0-py3-none-any.whl", + "lib/python3.12/ensurepip/_uninstall.py", + "lib/python3.12/enum.py", + "lib/python3.12/filecmp.py", + "lib/python3.12/fileinput.py", + "lib/python3.12/fnmatch.py", + "lib/python3.12/fractions.py", + "lib/python3.12/ftplib.py", + "lib/python3.12/functools.py", + "lib/python3.12/genericpath.py", + "lib/python3.12/getopt.py", + "lib/python3.12/getpass.py", + "lib/python3.12/gettext.py", + "lib/python3.12/glob.py", + "lib/python3.12/graphlib.py", + "lib/python3.12/gzip.py", + "lib/python3.12/hashlib.py", + "lib/python3.12/heapq.py", + "lib/python3.12/hmac.py", + "lib/python3.12/html/__init__.py", + "lib/python3.12/html/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/html/__pycache__/entities.cpython-312.pyc", + "lib/python3.12/html/__pycache__/parser.cpython-312.pyc", + "lib/python3.12/html/entities.py", + "lib/python3.12/html/parser.py", + "lib/python3.12/http/__init__.py", + "lib/python3.12/http/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/http/__pycache__/client.cpython-312.pyc", + "lib/python3.12/http/__pycache__/cookiejar.cpython-312.pyc", + "lib/python3.12/http/__pycache__/cookies.cpython-312.pyc", + "lib/python3.12/http/__pycache__/server.cpython-312.pyc", + "lib/python3.12/http/client.py", + "lib/python3.12/http/cookiejar.py", + "lib/python3.12/http/cookies.py", + "lib/python3.12/http/server.py", + "lib/python3.12/idlelib/CREDITS.txt", + "lib/python3.12/idlelib/ChangeLog", + "lib/python3.12/idlelib/HISTORY.txt", + "lib/python3.12/idlelib/Icons/README.txt", + "lib/python3.12/idlelib/Icons/folder.gif", + "lib/python3.12/idlelib/Icons/idle.ico", + "lib/python3.12/idlelib/Icons/idle_16.gif", + "lib/python3.12/idlelib/Icons/idle_16.png", + "lib/python3.12/idlelib/Icons/idle_256.png", + "lib/python3.12/idlelib/Icons/idle_32.gif", + "lib/python3.12/idlelib/Icons/idle_32.png", + "lib/python3.12/idlelib/Icons/idle_48.gif", + "lib/python3.12/idlelib/Icons/idle_48.png", + "lib/python3.12/idlelib/Icons/minusnode.gif", + "lib/python3.12/idlelib/Icons/openfolder.gif", + "lib/python3.12/idlelib/Icons/plusnode.gif", + "lib/python3.12/idlelib/Icons/python.gif", + "lib/python3.12/idlelib/Icons/tk.gif", + "lib/python3.12/idlelib/NEWS2x.txt", + "lib/python3.12/idlelib/News3.txt", + "lib/python3.12/idlelib/README.txt", + "lib/python3.12/idlelib/TODO.txt", + "lib/python3.12/idlelib/__init__.py", + "lib/python3.12/idlelib/__main__.py", + "lib/python3.12/idlelib/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/autocomplete.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/autocomplete_w.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/autoexpand.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/browser.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/calltip.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/calltip_w.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/codecontext.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/colorizer.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/config.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/config_key.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/configdialog.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/debugger.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/debugger_r.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/debugobj.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/debugobj_r.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/delegator.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/dynoption.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/editor.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/filelist.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/format.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/grep.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/help.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/help_about.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/history.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/hyperparser.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/idle.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/iomenu.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/macosx.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/mainmenu.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/multicall.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/outwin.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/parenmatch.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/pathbrowser.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/percolator.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/pyparse.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/pyshell.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/query.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/redirector.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/replace.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/rpc.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/run.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/runscript.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/scrolledlist.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/search.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/searchbase.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/searchengine.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/sidebar.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/squeezer.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/stackviewer.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/statusbar.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/textview.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/tooltip.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/tree.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/undo.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/util.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/window.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/zoomheight.cpython-312.pyc", + "lib/python3.12/idlelib/__pycache__/zzdummy.cpython-312.pyc", + "lib/python3.12/idlelib/autocomplete.py", + "lib/python3.12/idlelib/autocomplete_w.py", + "lib/python3.12/idlelib/autoexpand.py", + "lib/python3.12/idlelib/browser.py", + "lib/python3.12/idlelib/calltip.py", + "lib/python3.12/idlelib/calltip_w.py", + "lib/python3.12/idlelib/codecontext.py", + "lib/python3.12/idlelib/colorizer.py", + "lib/python3.12/idlelib/config-extensions.def", + "lib/python3.12/idlelib/config-highlight.def", + "lib/python3.12/idlelib/config-keys.def", + "lib/python3.12/idlelib/config-main.def", + "lib/python3.12/idlelib/config.py", + "lib/python3.12/idlelib/config_key.py", + "lib/python3.12/idlelib/configdialog.py", + "lib/python3.12/idlelib/debugger.py", + "lib/python3.12/idlelib/debugger_r.py", + "lib/python3.12/idlelib/debugobj.py", + "lib/python3.12/idlelib/debugobj_r.py", + "lib/python3.12/idlelib/delegator.py", + "lib/python3.12/idlelib/dynoption.py", + "lib/python3.12/idlelib/editor.py", + "lib/python3.12/idlelib/extend.txt", + "lib/python3.12/idlelib/filelist.py", + "lib/python3.12/idlelib/format.py", + "lib/python3.12/idlelib/grep.py", + "lib/python3.12/idlelib/help.html", + "lib/python3.12/idlelib/help.py", + "lib/python3.12/idlelib/help_about.py", + "lib/python3.12/idlelib/history.py", + "lib/python3.12/idlelib/hyperparser.py", + "lib/python3.12/idlelib/idle.bat", + "lib/python3.12/idlelib/idle.py", + "lib/python3.12/idlelib/idle.pyw", + "lib/python3.12/idlelib/idle_test/README.txt", + "lib/python3.12/idlelib/idle_test/__init__.py", + "lib/python3.12/idlelib/idle_test/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/htest.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/mock_idle.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/mock_tk.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/template.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_autocomplete.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_autocomplete_w.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_autoexpand.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_browser.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_calltip.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_calltip_w.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_codecontext.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_colorizer.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_config.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_config_key.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_configdialog.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_debugger.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_debugger_r.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_debugobj.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_debugobj_r.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_delegator.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_editmenu.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_editor.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_filelist.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_format.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_grep.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_help.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_help_about.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_history.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_hyperparser.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_iomenu.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_macosx.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_mainmenu.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_multicall.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_outwin.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_parenmatch.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_pathbrowser.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_percolator.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_pyparse.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_pyshell.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_query.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_redirector.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_replace.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_rpc.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_run.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_runscript.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_scrolledlist.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_search.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_searchbase.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_searchengine.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_sidebar.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_squeezer.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_stackviewer.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_statusbar.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_text.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_textview.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_tooltip.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_tree.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_undo.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_util.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_warning.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_window.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_zoomheight.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/test_zzdummy.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/__pycache__/tkinter_testing_utils.cpython-312.pyc", + "lib/python3.12/idlelib/idle_test/example_noext", + "lib/python3.12/idlelib/idle_test/example_stub.pyi", + "lib/python3.12/idlelib/idle_test/htest.py", + "lib/python3.12/idlelib/idle_test/mock_idle.py", + "lib/python3.12/idlelib/idle_test/mock_tk.py", + "lib/python3.12/idlelib/idle_test/template.py", + "lib/python3.12/idlelib/idle_test/test_autocomplete.py", + "lib/python3.12/idlelib/idle_test/test_autocomplete_w.py", + "lib/python3.12/idlelib/idle_test/test_autoexpand.py", + "lib/python3.12/idlelib/idle_test/test_browser.py", + "lib/python3.12/idlelib/idle_test/test_calltip.py", + "lib/python3.12/idlelib/idle_test/test_calltip_w.py", + "lib/python3.12/idlelib/idle_test/test_codecontext.py", + "lib/python3.12/idlelib/idle_test/test_colorizer.py", + "lib/python3.12/idlelib/idle_test/test_config.py", + "lib/python3.12/idlelib/idle_test/test_config_key.py", + "lib/python3.12/idlelib/idle_test/test_configdialog.py", + "lib/python3.12/idlelib/idle_test/test_debugger.py", + "lib/python3.12/idlelib/idle_test/test_debugger_r.py", + "lib/python3.12/idlelib/idle_test/test_debugobj.py", + "lib/python3.12/idlelib/idle_test/test_debugobj_r.py", + "lib/python3.12/idlelib/idle_test/test_delegator.py", + "lib/python3.12/idlelib/idle_test/test_editmenu.py", + "lib/python3.12/idlelib/idle_test/test_editor.py", + "lib/python3.12/idlelib/idle_test/test_filelist.py", + "lib/python3.12/idlelib/idle_test/test_format.py", + "lib/python3.12/idlelib/idle_test/test_grep.py", + "lib/python3.12/idlelib/idle_test/test_help.py", + "lib/python3.12/idlelib/idle_test/test_help_about.py", + "lib/python3.12/idlelib/idle_test/test_history.py", + "lib/python3.12/idlelib/idle_test/test_hyperparser.py", + "lib/python3.12/idlelib/idle_test/test_iomenu.py", + "lib/python3.12/idlelib/idle_test/test_macosx.py", + "lib/python3.12/idlelib/idle_test/test_mainmenu.py", + "lib/python3.12/idlelib/idle_test/test_multicall.py", + "lib/python3.12/idlelib/idle_test/test_outwin.py", + "lib/python3.12/idlelib/idle_test/test_parenmatch.py", + "lib/python3.12/idlelib/idle_test/test_pathbrowser.py", + "lib/python3.12/idlelib/idle_test/test_percolator.py", + "lib/python3.12/idlelib/idle_test/test_pyparse.py", + "lib/python3.12/idlelib/idle_test/test_pyshell.py", + "lib/python3.12/idlelib/idle_test/test_query.py", + "lib/python3.12/idlelib/idle_test/test_redirector.py", + "lib/python3.12/idlelib/idle_test/test_replace.py", + "lib/python3.12/idlelib/idle_test/test_rpc.py", + "lib/python3.12/idlelib/idle_test/test_run.py", + "lib/python3.12/idlelib/idle_test/test_runscript.py", + "lib/python3.12/idlelib/idle_test/test_scrolledlist.py", + "lib/python3.12/idlelib/idle_test/test_search.py", + "lib/python3.12/idlelib/idle_test/test_searchbase.py", + "lib/python3.12/idlelib/idle_test/test_searchengine.py", + "lib/python3.12/idlelib/idle_test/test_sidebar.py", + "lib/python3.12/idlelib/idle_test/test_squeezer.py", + "lib/python3.12/idlelib/idle_test/test_stackviewer.py", + "lib/python3.12/idlelib/idle_test/test_statusbar.py", + "lib/python3.12/idlelib/idle_test/test_text.py", + "lib/python3.12/idlelib/idle_test/test_textview.py", + "lib/python3.12/idlelib/idle_test/test_tooltip.py", + "lib/python3.12/idlelib/idle_test/test_tree.py", + "lib/python3.12/idlelib/idle_test/test_undo.py", + "lib/python3.12/idlelib/idle_test/test_util.py", + "lib/python3.12/idlelib/idle_test/test_warning.py", + "lib/python3.12/idlelib/idle_test/test_window.py", + "lib/python3.12/idlelib/idle_test/test_zoomheight.py", + "lib/python3.12/idlelib/idle_test/test_zzdummy.py", + "lib/python3.12/idlelib/idle_test/tkinter_testing_utils.py", + "lib/python3.12/idlelib/iomenu.py", + "lib/python3.12/idlelib/macosx.py", + "lib/python3.12/idlelib/mainmenu.py", + "lib/python3.12/idlelib/multicall.py", + "lib/python3.12/idlelib/outwin.py", + "lib/python3.12/idlelib/parenmatch.py", + "lib/python3.12/idlelib/pathbrowser.py", + "lib/python3.12/idlelib/percolator.py", + "lib/python3.12/idlelib/pyparse.py", + "lib/python3.12/idlelib/pyshell.py", + "lib/python3.12/idlelib/query.py", + "lib/python3.12/idlelib/redirector.py", + "lib/python3.12/idlelib/replace.py", + "lib/python3.12/idlelib/rpc.py", + "lib/python3.12/idlelib/run.py", + "lib/python3.12/idlelib/runscript.py", + "lib/python3.12/idlelib/scrolledlist.py", + "lib/python3.12/idlelib/search.py", + "lib/python3.12/idlelib/searchbase.py", + "lib/python3.12/idlelib/searchengine.py", + "lib/python3.12/idlelib/sidebar.py", + "lib/python3.12/idlelib/squeezer.py", + "lib/python3.12/idlelib/stackviewer.py", + "lib/python3.12/idlelib/statusbar.py", + "lib/python3.12/idlelib/textview.py", + "lib/python3.12/idlelib/tooltip.py", + "lib/python3.12/idlelib/tree.py", + "lib/python3.12/idlelib/undo.py", + "lib/python3.12/idlelib/util.py", + "lib/python3.12/idlelib/window.py", + "lib/python3.12/idlelib/zoomheight.py", + "lib/python3.12/idlelib/zzdummy.py", + "lib/python3.12/imaplib.py", + "lib/python3.12/imghdr.py", + "lib/python3.12/importlib/__init__.py", + "lib/python3.12/importlib/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/_abc.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/_bootstrap.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/_bootstrap_external.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/abc.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/machinery.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/readers.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/simple.cpython-312.pyc", + "lib/python3.12/importlib/__pycache__/util.cpython-312.pyc", + "lib/python3.12/importlib/_abc.py", + "lib/python3.12/importlib/_bootstrap.py", + "lib/python3.12/importlib/_bootstrap_external.py", + "lib/python3.12/importlib/abc.py", + "lib/python3.12/importlib/machinery.py", + "lib/python3.12/importlib/metadata/__init__.py", + "lib/python3.12/importlib/metadata/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_adapters.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_collections.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_functools.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_itertools.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_meta.cpython-312.pyc", + "lib/python3.12/importlib/metadata/__pycache__/_text.cpython-312.pyc", + "lib/python3.12/importlib/metadata/_adapters.py", + "lib/python3.12/importlib/metadata/_collections.py", + "lib/python3.12/importlib/metadata/_functools.py", + "lib/python3.12/importlib/metadata/_itertools.py", + "lib/python3.12/importlib/metadata/_meta.py", + "lib/python3.12/importlib/metadata/_text.py", + "lib/python3.12/importlib/readers.py", + "lib/python3.12/importlib/resources/__init__.py", + "lib/python3.12/importlib/resources/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/_adapters.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/_common.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/_itertools.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/_legacy.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/abc.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/readers.cpython-312.pyc", + "lib/python3.12/importlib/resources/__pycache__/simple.cpython-312.pyc", + "lib/python3.12/importlib/resources/_adapters.py", + "lib/python3.12/importlib/resources/_common.py", + "lib/python3.12/importlib/resources/_itertools.py", + "lib/python3.12/importlib/resources/_legacy.py", + "lib/python3.12/importlib/resources/abc.py", + "lib/python3.12/importlib/resources/readers.py", + "lib/python3.12/importlib/resources/simple.py", + "lib/python3.12/importlib/simple.py", + "lib/python3.12/importlib/util.py", + "lib/python3.12/inspect.py", + "lib/python3.12/io.py", + "lib/python3.12/ipaddress.py", + "lib/python3.12/json/__init__.py", + "lib/python3.12/json/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/json/__pycache__/decoder.cpython-312.pyc", + "lib/python3.12/json/__pycache__/encoder.cpython-312.pyc", + "lib/python3.12/json/__pycache__/scanner.cpython-312.pyc", + "lib/python3.12/json/__pycache__/tool.cpython-312.pyc", + "lib/python3.12/json/decoder.py", + "lib/python3.12/json/encoder.py", + "lib/python3.12/json/scanner.py", + "lib/python3.12/json/tool.py", + "lib/python3.12/keyword.py", + "lib/python3.12/lib-dynload/_asyncio.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_bisect.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_blake2.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_bz2.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_cn.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_hk.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_iso2022.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_jp.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_kr.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_codecs_tw.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_contextvars.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_crypt.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_csv.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_ctypes.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_ctypes_test.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_curses.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_curses_panel.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_datetime.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_decimal.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_elementtree.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_hashlib.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_heapq.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_json.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_lsprof.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_lzma.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_md5.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_multibytecodec.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_multiprocessing.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_opcode.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_pickle.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_posixshmem.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_posixsubprocess.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_queue.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_random.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_sha1.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_sha2.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_sha3.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_socket.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_sqlite3.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_ssl.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_statistics.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_struct.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testbuffer.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testcapi.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testclinic.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testimportmultiple.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testinternalcapi.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testmultiphase.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_testsinglephase.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_tkinter.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_uuid.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_xxinterpchannels.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_xxsubinterpreters.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_xxtestfuzz.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/_zoneinfo.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/array.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/audioop.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/binascii.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/cmath.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/fcntl.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/math.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/mmap.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/nis.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/ossaudiodev.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/pyexpat.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/readline.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/resource.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/select.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/spwd.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/syslog.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/termios.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/unicodedata.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/xxlimited.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/xxlimited_35.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/xxsubtype.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib-dynload/zlib.cpython-312-x86_64-linux-gnu.so", + "lib/python3.12/lib2to3/Grammar.txt", + "lib/python3.12/lib2to3/Grammar3.12.3.final.0.pickle", + "lib/python3.12/lib2to3/PatternGrammar.txt", + "lib/python3.12/lib2to3/PatternGrammar3.12.3.final.0.pickle", + "lib/python3.12/lib2to3/__init__.py", + "lib/python3.12/lib2to3/__main__.py", + "lib/python3.12/lib2to3/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/btm_matcher.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/btm_utils.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/fixer_base.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/fixer_util.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/main.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/patcomp.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/pygram.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/pytree.cpython-312.pyc", + "lib/python3.12/lib2to3/__pycache__/refactor.cpython-312.pyc", + "lib/python3.12/lib2to3/btm_matcher.py", + "lib/python3.12/lib2to3/btm_utils.py", + "lib/python3.12/lib2to3/fixer_base.py", + "lib/python3.12/lib2to3/fixer_util.py", + "lib/python3.12/lib2to3/fixes/__init__.py", + "lib/python3.12/lib2to3/fixes/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_apply.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_asserts.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_basestring.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_buffer.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_dict.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_except.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_exec.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_execfile.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_exitfunc.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_filter.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_funcattrs.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_future.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_getcwdu.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_has_key.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_idioms.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_import.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_imports.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_imports2.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_input.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_intern.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_isinstance.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_itertools.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_itertools_imports.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_long.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_map.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_metaclass.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_methodattrs.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_ne.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_next.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_nonzero.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_numliterals.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_operator.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_paren.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_print.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_raise.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_raw_input.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_reduce.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_reload.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_renames.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_repr.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_set_literal.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_standarderror.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_sys_exc.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_throw.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_tuple_params.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_types.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_unicode.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_urllib.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_ws_comma.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_xrange.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_xreadlines.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/__pycache__/fix_zip.cpython-312.pyc", + "lib/python3.12/lib2to3/fixes/fix_apply.py", + "lib/python3.12/lib2to3/fixes/fix_asserts.py", + "lib/python3.12/lib2to3/fixes/fix_basestring.py", + "lib/python3.12/lib2to3/fixes/fix_buffer.py", + "lib/python3.12/lib2to3/fixes/fix_dict.py", + "lib/python3.12/lib2to3/fixes/fix_except.py", + "lib/python3.12/lib2to3/fixes/fix_exec.py", + "lib/python3.12/lib2to3/fixes/fix_execfile.py", + "lib/python3.12/lib2to3/fixes/fix_exitfunc.py", + "lib/python3.12/lib2to3/fixes/fix_filter.py", + "lib/python3.12/lib2to3/fixes/fix_funcattrs.py", + "lib/python3.12/lib2to3/fixes/fix_future.py", + "lib/python3.12/lib2to3/fixes/fix_getcwdu.py", + "lib/python3.12/lib2to3/fixes/fix_has_key.py", + "lib/python3.12/lib2to3/fixes/fix_idioms.py", + "lib/python3.12/lib2to3/fixes/fix_import.py", + "lib/python3.12/lib2to3/fixes/fix_imports.py", + "lib/python3.12/lib2to3/fixes/fix_imports2.py", + "lib/python3.12/lib2to3/fixes/fix_input.py", + "lib/python3.12/lib2to3/fixes/fix_intern.py", + "lib/python3.12/lib2to3/fixes/fix_isinstance.py", + "lib/python3.12/lib2to3/fixes/fix_itertools.py", + "lib/python3.12/lib2to3/fixes/fix_itertools_imports.py", + "lib/python3.12/lib2to3/fixes/fix_long.py", + "lib/python3.12/lib2to3/fixes/fix_map.py", + "lib/python3.12/lib2to3/fixes/fix_metaclass.py", + "lib/python3.12/lib2to3/fixes/fix_methodattrs.py", + "lib/python3.12/lib2to3/fixes/fix_ne.py", + "lib/python3.12/lib2to3/fixes/fix_next.py", + "lib/python3.12/lib2to3/fixes/fix_nonzero.py", + "lib/python3.12/lib2to3/fixes/fix_numliterals.py", + "lib/python3.12/lib2to3/fixes/fix_operator.py", + "lib/python3.12/lib2to3/fixes/fix_paren.py", + "lib/python3.12/lib2to3/fixes/fix_print.py", + "lib/python3.12/lib2to3/fixes/fix_raise.py", + "lib/python3.12/lib2to3/fixes/fix_raw_input.py", + "lib/python3.12/lib2to3/fixes/fix_reduce.py", + "lib/python3.12/lib2to3/fixes/fix_reload.py", + "lib/python3.12/lib2to3/fixes/fix_renames.py", + "lib/python3.12/lib2to3/fixes/fix_repr.py", + "lib/python3.12/lib2to3/fixes/fix_set_literal.py", + "lib/python3.12/lib2to3/fixes/fix_standarderror.py", + "lib/python3.12/lib2to3/fixes/fix_sys_exc.py", + "lib/python3.12/lib2to3/fixes/fix_throw.py", + "lib/python3.12/lib2to3/fixes/fix_tuple_params.py", + "lib/python3.12/lib2to3/fixes/fix_types.py", + "lib/python3.12/lib2to3/fixes/fix_unicode.py", + "lib/python3.12/lib2to3/fixes/fix_urllib.py", + "lib/python3.12/lib2to3/fixes/fix_ws_comma.py", + "lib/python3.12/lib2to3/fixes/fix_xrange.py", + "lib/python3.12/lib2to3/fixes/fix_xreadlines.py", + "lib/python3.12/lib2to3/fixes/fix_zip.py", + "lib/python3.12/lib2to3/main.py", + "lib/python3.12/lib2to3/patcomp.py", + "lib/python3.12/lib2to3/pgen2/__init__.py", + "lib/python3.12/lib2to3/pgen2/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/conv.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/driver.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/grammar.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/literals.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/parse.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/pgen.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/token.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/__pycache__/tokenize.cpython-312.pyc", + "lib/python3.12/lib2to3/pgen2/conv.py", + "lib/python3.12/lib2to3/pgen2/driver.py", + "lib/python3.12/lib2to3/pgen2/grammar.py", + "lib/python3.12/lib2to3/pgen2/literals.py", + "lib/python3.12/lib2to3/pgen2/parse.py", + "lib/python3.12/lib2to3/pgen2/pgen.py", + "lib/python3.12/lib2to3/pgen2/token.py", + "lib/python3.12/lib2to3/pgen2/tokenize.py", + "lib/python3.12/lib2to3/pygram.py", + "lib/python3.12/lib2to3/pytree.py", + "lib/python3.12/lib2to3/refactor.py", + "lib/python3.12/linecache.py", + "lib/python3.12/locale.py", + "lib/python3.12/logging/__init__.py", + "lib/python3.12/logging/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/logging/__pycache__/config.cpython-312.pyc", + "lib/python3.12/logging/__pycache__/handlers.cpython-312.pyc", + "lib/python3.12/logging/config.py", + "lib/python3.12/logging/handlers.py", + "lib/python3.12/lzma.py", + "lib/python3.12/mailbox.py", + "lib/python3.12/mailcap.py", + "lib/python3.12/mimetypes.py", + "lib/python3.12/modulefinder.py", + "lib/python3.12/multiprocessing/__init__.py", + "lib/python3.12/multiprocessing/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/connection.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/context.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/forkserver.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/heap.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/managers.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/pool.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/popen_fork.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/popen_forkserver.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/popen_spawn_posix.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/popen_spawn_win32.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/process.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/queues.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/reduction.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/resource_sharer.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/resource_tracker.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/shared_memory.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/sharedctypes.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/spawn.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/synchronize.cpython-312.pyc", + "lib/python3.12/multiprocessing/__pycache__/util.cpython-312.pyc", + "lib/python3.12/multiprocessing/connection.py", + "lib/python3.12/multiprocessing/context.py", + "lib/python3.12/multiprocessing/dummy/__init__.py", + "lib/python3.12/multiprocessing/dummy/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/multiprocessing/dummy/__pycache__/connection.cpython-312.pyc", + "lib/python3.12/multiprocessing/dummy/connection.py", + "lib/python3.12/multiprocessing/forkserver.py", + "lib/python3.12/multiprocessing/heap.py", + "lib/python3.12/multiprocessing/managers.py", + "lib/python3.12/multiprocessing/pool.py", + "lib/python3.12/multiprocessing/popen_fork.py", + "lib/python3.12/multiprocessing/popen_forkserver.py", + "lib/python3.12/multiprocessing/popen_spawn_posix.py", + "lib/python3.12/multiprocessing/popen_spawn_win32.py", + "lib/python3.12/multiprocessing/process.py", + "lib/python3.12/multiprocessing/queues.py", + "lib/python3.12/multiprocessing/reduction.py", + "lib/python3.12/multiprocessing/resource_sharer.py", + "lib/python3.12/multiprocessing/resource_tracker.py", + "lib/python3.12/multiprocessing/shared_memory.py", + "lib/python3.12/multiprocessing/sharedctypes.py", + "lib/python3.12/multiprocessing/spawn.py", + "lib/python3.12/multiprocessing/synchronize.py", + "lib/python3.12/multiprocessing/util.py", + "lib/python3.12/netrc.py", + "lib/python3.12/nntplib.py", + "lib/python3.12/ntpath.py", + "lib/python3.12/nturl2path.py", + "lib/python3.12/numbers.py", + "lib/python3.12/opcode.py", + "lib/python3.12/operator.py", + "lib/python3.12/optparse.py", + "lib/python3.12/os.py", + "lib/python3.12/pathlib.py", + "lib/python3.12/pdb.py", + "lib/python3.12/pickle.py", + "lib/python3.12/pickletools.py", + "lib/python3.12/pipes.py", + "lib/python3.12/pkgutil.py", + "lib/python3.12/platform.py", + "lib/python3.12/plistlib.py", + "lib/python3.12/poplib.py", + "lib/python3.12/posixpath.py", + "lib/python3.12/pprint.py", + "lib/python3.12/profile.py", + "lib/python3.12/pstats.py", + "lib/python3.12/pty.py", + "lib/python3.12/py_compile.py", + "lib/python3.12/pyclbr.py", + "lib/python3.12/pydoc.py", + "lib/python3.12/pydoc_data/__init__.py", + "lib/python3.12/pydoc_data/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/pydoc_data/__pycache__/topics.cpython-312.pyc", + "lib/python3.12/pydoc_data/_pydoc.css", + "lib/python3.12/pydoc_data/topics.py", + "lib/python3.12/queue.py", + "lib/python3.12/quopri.py", + "lib/python3.12/random.py", + "lib/python3.12/re/__init__.py", + "lib/python3.12/re/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/re/__pycache__/_casefix.cpython-312.pyc", + "lib/python3.12/re/__pycache__/_compiler.cpython-312.pyc", + "lib/python3.12/re/__pycache__/_constants.cpython-312.pyc", + "lib/python3.12/re/__pycache__/_parser.cpython-312.pyc", + "lib/python3.12/re/_casefix.py", + "lib/python3.12/re/_compiler.py", + "lib/python3.12/re/_constants.py", + "lib/python3.12/re/_parser.py", + "lib/python3.12/reprlib.py", + "lib/python3.12/rlcompleter.py", + "lib/python3.12/runpy.py", + "lib/python3.12/sched.py", + "lib/python3.12/secrets.py", + "lib/python3.12/selectors.py", + "lib/python3.12/shelve.py", + "lib/python3.12/shlex.py", + "lib/python3.12/shutil.py", + "lib/python3.12/signal.py", + "lib/python3.12/site-packages/README.txt", + "lib/python3.12/site.py", + "lib/python3.12/smtplib.py", + "lib/python3.12/sndhdr.py", + "lib/python3.12/socket.py", + "lib/python3.12/socketserver.py", + "lib/python3.12/sqlite3/__init__.py", + "lib/python3.12/sqlite3/__main__.py", + "lib/python3.12/sqlite3/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/sqlite3/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/sqlite3/__pycache__/dbapi2.cpython-312.pyc", + "lib/python3.12/sqlite3/__pycache__/dump.cpython-312.pyc", + "lib/python3.12/sqlite3/dbapi2.py", + "lib/python3.12/sqlite3/dump.py", + "lib/python3.12/sre_compile.py", + "lib/python3.12/sre_constants.py", + "lib/python3.12/sre_parse.py", + "lib/python3.12/ssl.py", + "lib/python3.12/stat.py", + "lib/python3.12/statistics.py", + "lib/python3.12/string.py", + "lib/python3.12/stringprep.py", + "lib/python3.12/struct.py", + "lib/python3.12/subprocess.py", + "lib/python3.12/sunau.py", + "lib/python3.12/symtable.py", + "lib/python3.12/sysconfig.py", + "lib/python3.12/tabnanny.py", + "lib/python3.12/tarfile.py", + "lib/python3.12/telnetlib.py", + "lib/python3.12/tempfile.py", + "lib/python3.12/test/__init__.py", + "lib/python3.12/test/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/test/__pycache__/test_script_helper.cpython-312.pyc", + "lib/python3.12/test/__pycache__/test_support.cpython-312.pyc", + "lib/python3.12/test/support/__init__.py", + "lib/python3.12/test/support/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/ast_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/asynchat.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/asyncore.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/bytecode_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/hashlib_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/hypothesis_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/import_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/interpreters.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/logging_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/os_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/pty_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/script_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/smtpd.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/socket_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/testcase.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/threading_helper.cpython-312.pyc", + "lib/python3.12/test/support/__pycache__/warnings_helper.cpython-312.pyc", + "lib/python3.12/test/support/_hypothesis_stubs/__init__.py", + "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/_helpers.cpython-312.pyc", + "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/strategies.cpython-312.pyc", + "lib/python3.12/test/support/_hypothesis_stubs/_helpers.py", + "lib/python3.12/test/support/_hypothesis_stubs/strategies.py", + "lib/python3.12/test/support/ast_helper.py", + "lib/python3.12/test/support/asynchat.py", + "lib/python3.12/test/support/asyncore.py", + "lib/python3.12/test/support/bytecode_helper.py", + "lib/python3.12/test/support/hashlib_helper.py", + "lib/python3.12/test/support/hypothesis_helper.py", + "lib/python3.12/test/support/import_helper.py", + "lib/python3.12/test/support/interpreters.py", + "lib/python3.12/test/support/logging_helper.py", + "lib/python3.12/test/support/os_helper.py", + "lib/python3.12/test/support/pty_helper.py", + "lib/python3.12/test/support/script_helper.py", + "lib/python3.12/test/support/smtpd.py", + "lib/python3.12/test/support/socket_helper.py", + "lib/python3.12/test/support/testcase.py", + "lib/python3.12/test/support/threading_helper.py", + "lib/python3.12/test/support/warnings_helper.py", + "lib/python3.12/test/test_script_helper.py", + "lib/python3.12/test/test_support.py", + "lib/python3.12/textwrap.py", + "lib/python3.12/this.py", + "lib/python3.12/threading.py", + "lib/python3.12/timeit.py", + "lib/python3.12/tkinter/__init__.py", + "lib/python3.12/tkinter/__main__.py", + "lib/python3.12/tkinter/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/colorchooser.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/commondialog.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/constants.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/dialog.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/dnd.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/filedialog.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/font.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/messagebox.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/scrolledtext.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/simpledialog.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/tix.cpython-312.pyc", + "lib/python3.12/tkinter/__pycache__/ttk.cpython-312.pyc", + "lib/python3.12/tkinter/colorchooser.py", + "lib/python3.12/tkinter/commondialog.py", + "lib/python3.12/tkinter/constants.py", + "lib/python3.12/tkinter/dialog.py", + "lib/python3.12/tkinter/dnd.py", + "lib/python3.12/tkinter/filedialog.py", + "lib/python3.12/tkinter/font.py", + "lib/python3.12/tkinter/messagebox.py", + "lib/python3.12/tkinter/scrolledtext.py", + "lib/python3.12/tkinter/simpledialog.py", + "lib/python3.12/tkinter/tix.py", + "lib/python3.12/tkinter/ttk.py", + "lib/python3.12/token.py", + "lib/python3.12/tokenize.py", + "lib/python3.12/tomllib/__init__.py", + "lib/python3.12/tomllib/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/tomllib/__pycache__/_parser.cpython-312.pyc", + "lib/python3.12/tomllib/__pycache__/_re.cpython-312.pyc", + "lib/python3.12/tomllib/__pycache__/_types.cpython-312.pyc", + "lib/python3.12/tomllib/_parser.py", + "lib/python3.12/tomllib/_re.py", + "lib/python3.12/tomllib/_types.py", + "lib/python3.12/trace.py", + "lib/python3.12/traceback.py", + "lib/python3.12/tracemalloc.py", + "lib/python3.12/tty.py", + "lib/python3.12/turtle.py", + "lib/python3.12/turtledemo/__init__.py", + "lib/python3.12/turtledemo/__main__.py", + "lib/python3.12/turtledemo/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/bytedesign.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/chaos.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/clock.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/colormixer.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/forest.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/fractalcurves.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/lindenmayer.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/minimal_hanoi.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/nim.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/paint.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/peace.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/penrose.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/planet_and_moon.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/rosette.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/round_dance.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/sorting_animate.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/tree.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/two_canvases.cpython-312.pyc", + "lib/python3.12/turtledemo/__pycache__/yinyang.cpython-312.pyc", + "lib/python3.12/turtledemo/bytedesign.py", + "lib/python3.12/turtledemo/chaos.py", + "lib/python3.12/turtledemo/clock.py", + "lib/python3.12/turtledemo/colormixer.py", + "lib/python3.12/turtledemo/forest.py", + "lib/python3.12/turtledemo/fractalcurves.py", + "lib/python3.12/turtledemo/lindenmayer.py", + "lib/python3.12/turtledemo/minimal_hanoi.py", + "lib/python3.12/turtledemo/nim.py", + "lib/python3.12/turtledemo/paint.py", + "lib/python3.12/turtledemo/peace.py", + "lib/python3.12/turtledemo/penrose.py", + "lib/python3.12/turtledemo/planet_and_moon.py", + "lib/python3.12/turtledemo/rosette.py", + "lib/python3.12/turtledemo/round_dance.py", + "lib/python3.12/turtledemo/sorting_animate.py", + "lib/python3.12/turtledemo/tree.py", + "lib/python3.12/turtledemo/turtle.cfg", + "lib/python3.12/turtledemo/two_canvases.py", + "lib/python3.12/turtledemo/yinyang.py", + "lib/python3.12/types.py", + "lib/python3.12/typing.py", + "lib/python3.12/unittest/__init__.py", + "lib/python3.12/unittest/__main__.py", + "lib/python3.12/unittest/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/_log.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/async_case.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/case.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/loader.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/main.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/mock.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/result.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/runner.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/signals.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/suite.cpython-312.pyc", + "lib/python3.12/unittest/__pycache__/util.cpython-312.pyc", + "lib/python3.12/unittest/_log.py", + "lib/python3.12/unittest/async_case.py", + "lib/python3.12/unittest/case.py", + "lib/python3.12/unittest/loader.py", + "lib/python3.12/unittest/main.py", + "lib/python3.12/unittest/mock.py", + "lib/python3.12/unittest/result.py", + "lib/python3.12/unittest/runner.py", + "lib/python3.12/unittest/signals.py", + "lib/python3.12/unittest/suite.py", + "lib/python3.12/unittest/util.py", + "lib/python3.12/urllib/__init__.py", + "lib/python3.12/urllib/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/urllib/__pycache__/error.cpython-312.pyc", + "lib/python3.12/urllib/__pycache__/parse.cpython-312.pyc", + "lib/python3.12/urllib/__pycache__/request.cpython-312.pyc", + "lib/python3.12/urllib/__pycache__/response.cpython-312.pyc", + "lib/python3.12/urllib/__pycache__/robotparser.cpython-312.pyc", + "lib/python3.12/urllib/error.py", + "lib/python3.12/urllib/parse.py", + "lib/python3.12/urllib/request.py", + "lib/python3.12/urllib/response.py", + "lib/python3.12/urllib/robotparser.py", + "lib/python3.12/uu.py", + "lib/python3.12/uuid.py", + "lib/python3.12/venv/__init__.py", + "lib/python3.12/venv/__main__.py", + "lib/python3.12/venv/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/venv/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/venv/scripts/common/Activate.ps1", + "lib/python3.12/venv/scripts/common/activate", + "lib/python3.12/venv/scripts/posix/activate.csh", + "lib/python3.12/venv/scripts/posix/activate.fish", + "lib/python3.12/warnings.py", + "lib/python3.12/wave.py", + "lib/python3.12/weakref.py", + "lib/python3.12/webbrowser.py", + "lib/python3.12/wsgiref/__init__.py", + "lib/python3.12/wsgiref/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/handlers.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/headers.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/simple_server.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/types.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/util.cpython-312.pyc", + "lib/python3.12/wsgiref/__pycache__/validate.cpython-312.pyc", + "lib/python3.12/wsgiref/handlers.py", + "lib/python3.12/wsgiref/headers.py", + "lib/python3.12/wsgiref/simple_server.py", + "lib/python3.12/wsgiref/types.py", + "lib/python3.12/wsgiref/util.py", + "lib/python3.12/wsgiref/validate.py", + "lib/python3.12/xdrlib.py", + "lib/python3.12/xml/__init__.py", + "lib/python3.12/xml/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xml/dom/NodeFilter.py", + "lib/python3.12/xml/dom/__init__.py", + "lib/python3.12/xml/dom/__pycache__/NodeFilter.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/domreg.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/expatbuilder.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/minicompat.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/minidom.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/pulldom.cpython-312.pyc", + "lib/python3.12/xml/dom/__pycache__/xmlbuilder.cpython-312.pyc", + "lib/python3.12/xml/dom/domreg.py", + "lib/python3.12/xml/dom/expatbuilder.py", + "lib/python3.12/xml/dom/minicompat.py", + "lib/python3.12/xml/dom/minidom.py", + "lib/python3.12/xml/dom/pulldom.py", + "lib/python3.12/xml/dom/xmlbuilder.py", + "lib/python3.12/xml/etree/ElementInclude.py", + "lib/python3.12/xml/etree/ElementPath.py", + "lib/python3.12/xml/etree/ElementTree.py", + "lib/python3.12/xml/etree/__init__.py", + "lib/python3.12/xml/etree/__pycache__/ElementInclude.cpython-312.pyc", + "lib/python3.12/xml/etree/__pycache__/ElementPath.cpython-312.pyc", + "lib/python3.12/xml/etree/__pycache__/ElementTree.cpython-312.pyc", + "lib/python3.12/xml/etree/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xml/etree/__pycache__/cElementTree.cpython-312.pyc", + "lib/python3.12/xml/etree/cElementTree.py", + "lib/python3.12/xml/parsers/__init__.py", + "lib/python3.12/xml/parsers/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xml/parsers/__pycache__/expat.cpython-312.pyc", + "lib/python3.12/xml/parsers/expat.py", + "lib/python3.12/xml/sax/__init__.py", + "lib/python3.12/xml/sax/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xml/sax/__pycache__/_exceptions.cpython-312.pyc", + "lib/python3.12/xml/sax/__pycache__/expatreader.cpython-312.pyc", + "lib/python3.12/xml/sax/__pycache__/handler.cpython-312.pyc", + "lib/python3.12/xml/sax/__pycache__/saxutils.cpython-312.pyc", + "lib/python3.12/xml/sax/__pycache__/xmlreader.cpython-312.pyc", + "lib/python3.12/xml/sax/_exceptions.py", + "lib/python3.12/xml/sax/expatreader.py", + "lib/python3.12/xml/sax/handler.py", + "lib/python3.12/xml/sax/saxutils.py", + "lib/python3.12/xml/sax/xmlreader.py", + "lib/python3.12/xmlrpc/__init__.py", + "lib/python3.12/xmlrpc/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/xmlrpc/__pycache__/client.cpython-312.pyc", + "lib/python3.12/xmlrpc/__pycache__/server.cpython-312.pyc", + "lib/python3.12/xmlrpc/client.py", + "lib/python3.12/xmlrpc/server.py", + "lib/python3.12/zipapp.py", + "lib/python3.12/zipfile/__init__.py", + "lib/python3.12/zipfile/__main__.py", + "lib/python3.12/zipfile/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/zipfile/__pycache__/__main__.cpython-312.pyc", + "lib/python3.12/zipfile/_path/__init__.py", + "lib/python3.12/zipfile/_path/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/zipfile/_path/__pycache__/glob.cpython-312.pyc", + "lib/python3.12/zipfile/_path/glob.py", + "lib/python3.12/zipimport.py", + "lib/python3.12/zoneinfo/__init__.py", + "lib/python3.12/zoneinfo/__pycache__/__init__.cpython-312.pyc", + "lib/python3.12/zoneinfo/__pycache__/_common.cpython-312.pyc", + "lib/python3.12/zoneinfo/__pycache__/_tzpath.cpython-312.pyc", + "lib/python3.12/zoneinfo/__pycache__/_zoneinfo.cpython-312.pyc", + "lib/python3.12/zoneinfo/_common.py", + "lib/python3.12/zoneinfo/_tzpath.py", + "lib/python3.12/zoneinfo/_zoneinfo.py", + "share/man/man1/python3.1", + "share/man/man1/python3.12.1" + ], + "paths_data": { + "paths_version": 1, + "paths": [ + { + "_path": "bin/2to3", + "path_type": "softlink", + "sha256": "975c83ef558a24e849b5daef48bf85bb255f2b55bd03967004a4c0cfbda688e2", + "sha256_in_prefix": "7d6edfa4bb14fe3c0624f1e130de84638db658808e172f983df8b82e4dfb6b99", + "size_in_bytes": 347 + }, + { + "_path": "bin/2to3-3.12", + "path_type": "hardlink", + "sha256": "975c83ef558a24e849b5daef48bf85bb255f2b55bd03967004a4c0cfbda688e2", + "sha256_in_prefix": "d9e2c37819d335216109d98e903e77038e5ae4e1ff5e0c4f34d00d6499fb22ca", + "size_in_bytes": 131, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "bin/idle3", + "path_type": "softlink", + "sha256": "ca6c30c8417ab8b1fe2fdc59f2f2cc28bc3c363fee97b02540ed7061d801ab92", + "sha256_in_prefix": "378c0ee6a7835954aa9f2887df42f573439bca63ac626c62f1ba368d052cc75b", + "size_in_bytes": 345 + }, + { + "_path": "bin/idle3.12", + "path_type": "hardlink", + "sha256": "ca6c30c8417ab8b1fe2fdc59f2f2cc28bc3c363fee97b02540ed7061d801ab92", + "sha256_in_prefix": "7d9dd23ea70e79921a6d39f66ea3f5f5616e05feb02aa1af17240730196486df", + "size_in_bytes": 129, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "bin/pydoc", + "path_type": "softlink", + "sha256": "7ab6c37774c29a6ffc81d2529b25823d5108127e41c23271d633bb3922834b07", + "sha256_in_prefix": "0e7e5f6eeadeafea1f42e6cb604f0ba00f8dd893070cc268e75062c70a197545", + "size_in_bytes": 330 + }, + { + "_path": "bin/pydoc3", + "path_type": "softlink", + "sha256": "7ab6c37774c29a6ffc81d2529b25823d5108127e41c23271d633bb3922834b07", + "sha256_in_prefix": "0e7e5f6eeadeafea1f42e6cb604f0ba00f8dd893070cc268e75062c70a197545", + "size_in_bytes": 330 + }, + { + "_path": "bin/pydoc3.12", + "path_type": "hardlink", + "sha256": "7ab6c37774c29a6ffc81d2529b25823d5108127e41c23271d633bb3922834b07", + "sha256_in_prefix": "a0ec190d7f43f50ecc1acc46f321325082bf97b350e4966b83e490569dd69a9b", + "size_in_bytes": 114, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "bin/python", + "path_type": "softlink", + "sha256": "f744a9673243a054c8d33aa68b720becdf6f6e4208072f066b2166bc46c03de8", + "sha256_in_prefix": "42f2b28d8258c41a63374ac4365007738900f66a9b62a7eb1a2041a2e091d41b", + "size_in_bytes": 31389672 + }, + { + "_path": "bin/python3", + "path_type": "softlink", + "sha256": "f744a9673243a054c8d33aa68b720becdf6f6e4208072f066b2166bc46c03de8", + "sha256_in_prefix": "42f2b28d8258c41a63374ac4365007738900f66a9b62a7eb1a2041a2e091d41b", + "size_in_bytes": 31389672 + }, + { + "_path": "bin/python3-config", + "path_type": "softlink", + "sha256": "2788dc2c15a9ddccf9dc3b8526fd8573d7bba4177e29b7bea86accdf6fab727c", + "sha256_in_prefix": "1ee0db65654d143de59ff7ce7e7fba569cd80ea13f6ffa96b4cf1a59f8b5bcdd", + "size_in_bytes": 4172 + }, + { + "_path": "bin/python3.1", + "path_type": "softlink", + "sha256": "f744a9673243a054c8d33aa68b720becdf6f6e4208072f066b2166bc46c03de8", + "sha256_in_prefix": "42f2b28d8258c41a63374ac4365007738900f66a9b62a7eb1a2041a2e091d41b", + "size_in_bytes": 31389672 + }, + { + "_path": "bin/python3.12", + "path_type": "hardlink", + "sha256": "f744a9673243a054c8d33aa68b720becdf6f6e4208072f066b2166bc46c03de8", + "sha256_in_prefix": "b88f9a80c10bb592fcbf87c31c1408f09eb728f6f29248c9a30ebb88f915fa9a", + "size_in_bytes": 31389672, + "file_mode": "binary", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "bin/python3.12-config", + "path_type": "hardlink", + "sha256": "2788dc2c15a9ddccf9dc3b8526fd8573d7bba4177e29b7bea86accdf6fab727c", + "sha256_in_prefix": "6865a26dec8edb9996c4e13e3c27e9c9768c1b9ed13037f9025ef9d3486b8eb3", + "size_in_bytes": 3524, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "compiler_compat/README", + "path_type": "hardlink", + "sha256": "c574e4ff817a7fe4963a01fb33babaf271bab407854fb7ab6b265ebcf6973c73", + "sha256_in_prefix": "c574e4ff817a7fe4963a01fb33babaf271bab407854fb7ab6b265ebcf6973c73", + "size_in_bytes": 173 + }, + { + "_path": "compiler_compat/ld", + "path_type": "softlink", + "sha256": "df0752f24033ca8ea219295a7b8c9acbaa0be0393daa423300aa7845fda30d96", + "sha256_in_prefix": "82ed331970eb66c56622f31f8b6a55e7c1c671738fef6156c93b04190eb4e084", + "size_in_bytes": 2442288 + }, + { + "_path": "include/python3.12/Python.h", + "path_type": "hardlink", + "sha256": "729ef157f6026e6e1b3104593f87dddc597c3b83b60c7c2965878c62a56c6f7d", + "sha256_in_prefix": "729ef157f6026e6e1b3104593f87dddc597c3b83b60c7c2965878c62a56c6f7d", + "size_in_bytes": 2854 + }, + { + "_path": "include/python3.12/abstract.h", + "path_type": "hardlink", + "sha256": "8f0b27427f4e16b4295b2ab1a7bb499bf86748fafbd1959e220c506ed59f774f", + "sha256_in_prefix": "8f0b27427f4e16b4295b2ab1a7bb499bf86748fafbd1959e220c506ed59f774f", + "size_in_bytes": 32616 + }, + { + "_path": "include/python3.12/bltinmodule.h", + "path_type": "hardlink", + "sha256": "1b5101b4b85409fd910032713906800bbb83580503036469c2a60ac8e80b8f72", + "sha256_in_prefix": "1b5101b4b85409fd910032713906800bbb83580503036469c2a60ac8e80b8f72", + "size_in_bytes": 264 + }, + { + "_path": "include/python3.12/boolobject.h", + "path_type": "hardlink", + "sha256": "84289d5b1a1b7ed6c547f4f081fba70e90a9d60dfa2d2b3155c33cdd2af41340", + "sha256_in_prefix": "84289d5b1a1b7ed6c547f4f081fba70e90a9d60dfa2d2b3155c33cdd2af41340", + "size_in_bytes": 1136 + }, + { + "_path": "include/python3.12/bytearrayobject.h", + "path_type": "hardlink", + "sha256": "0e93963caf43a057fb293ae5183d1b8bb45c9f57926ce8308f67a0f452843e85", + "sha256_in_prefix": "0e93963caf43a057fb293ae5183d1b8bb45c9f57926ce8308f67a0f452843e85", + "size_in_bytes": 1466 + }, + { + "_path": "include/python3.12/bytesobject.h", + "path_type": "hardlink", + "sha256": "de8551db9323e7dc463717a624f2d35dacd17cdf0c7a7f6299128dd06348cf30", + "sha256_in_prefix": "de8551db9323e7dc463717a624f2d35dacd17cdf0c7a7f6299128dd06348cf30", + "size_in_bytes": 2619 + }, + { + "_path": "include/python3.12/ceval.h", + "path_type": "hardlink", + "sha256": "9531cce1b80e804d46a9ef31bd22605f54d0ae0609dc3470946a4d8d4270af3a", + "sha256_in_prefix": "9531cce1b80e804d46a9ef31bd22605f54d0ae0609dc3470946a4d8d4270af3a", + "size_in_bytes": 6267 + }, + { + "_path": "include/python3.12/codecs.h", + "path_type": "hardlink", + "sha256": "0ca3c6e55e7ff62872b47aeeb7379d784b03ebfc61bbd029b67485fe783baac5", + "sha256_in_prefix": "0ca3c6e55e7ff62872b47aeeb7379d784b03ebfc61bbd029b67485fe783baac5", + "size_in_bytes": 7071 + }, + { + "_path": "include/python3.12/compile.h", + "path_type": "hardlink", + "sha256": "1f10c818b29007e6a4446505a1140dd77ca6618ad81e87b502f4e22f4b274406", + "sha256_in_prefix": "1f10c818b29007e6a4446505a1140dd77ca6618ad81e87b502f4e22f4b274406", + "size_in_bytes": 448 + }, + { + "_path": "include/python3.12/complexobject.h", + "path_type": "hardlink", + "sha256": "9356805a24503256cd8914d7b7700357e01f471c211f9241c81981d89d6c3af8", + "sha256_in_prefix": "9356805a24503256cd8914d7b7700357e01f471c211f9241c81981d89d6c3af8", + "size_in_bytes": 728 + }, + { + "_path": "include/python3.12/cpython/abstract.h", + "path_type": "hardlink", + "sha256": "07d8b3b9c7db77e30adef4c4d9c7a4453b8eb1f48341ed5394bd5eebe239c9fd", + "sha256_in_prefix": "07d8b3b9c7db77e30adef4c4d9c7a4453b8eb1f48341ed5394bd5eebe239c9fd", + "size_in_bytes": 7870 + }, + { + "_path": "include/python3.12/cpython/bytearrayobject.h", + "path_type": "hardlink", + "sha256": "ae5e099856657f3b8606701df312866eaa88992f6cfd9f8567456e1588efceb1", + "sha256_in_prefix": "ae5e099856657f3b8606701df312866eaa88992f6cfd9f8567456e1588efceb1", + "size_in_bytes": 1163 + }, + { + "_path": "include/python3.12/cpython/bytesobject.h", + "path_type": "hardlink", + "sha256": "a7535615c2637b60e53c32355b489f49c6bc979be3a58adae5b0049231b43a6c", + "sha256_in_prefix": "a7535615c2637b60e53c32355b489f49c6bc979be3a58adae5b0049231b43a6c", + "size_in_bytes": 4426 + }, + { + "_path": "include/python3.12/cpython/cellobject.h", + "path_type": "hardlink", + "sha256": "844f06178bbce2e9377a46ccc80e2aae85a73750932576a6cc4de934cc508cea", + "sha256_in_prefix": "844f06178bbce2e9377a46ccc80e2aae85a73750932576a6cc4de934cc508cea", + "size_in_bytes": 1076 + }, + { + "_path": "include/python3.12/cpython/ceval.h", + "path_type": "hardlink", + "sha256": "b08c549971f1006e681267dd8a88481353ce4bd89b9d859f81b72cf9bf867895", + "sha256_in_prefix": "b08c549971f1006e681267dd8a88481353ce4bd89b9d859f81b72cf9bf867895", + "size_in_bytes": 1650 + }, + { + "_path": "include/python3.12/cpython/classobject.h", + "path_type": "hardlink", + "sha256": "b38a0ecdebeae2a4d28dfe8a5f2833f676d38be9561ca4bdfdf5087bbe2f9332", + "sha256_in_prefix": "b38a0ecdebeae2a4d28dfe8a5f2833f676d38be9561ca4bdfdf5087bbe2f9332", + "size_in_bytes": 2245 + }, + { + "_path": "include/python3.12/cpython/code.h", + "path_type": "hardlink", + "sha256": "cb01a969c69fec0fc0c58fe6e674d392282b96639e2523d3e69100c771ed0bbd", + "sha256_in_prefix": "cb01a969c69fec0fc0c58fe6e674d392282b96639e2523d3e69100c771ed0bbd", + "size_in_bytes": 16188 + }, + { + "_path": "include/python3.12/cpython/compile.h", + "path_type": "hardlink", + "sha256": "32d7397c6fa5478feb2a4101641fca6dba3ac77abe4deed5c0f713a6cd6564f5", + "sha256_in_prefix": "32d7397c6fa5478feb2a4101641fca6dba3ac77abe4deed5c0f713a6cd6564f5", + "size_in_bytes": 2660 + }, + { + "_path": "include/python3.12/cpython/complexobject.h", + "path_type": "hardlink", + "sha256": "a4c110008e4d791a4577ce6ebee33bc512ec3e3db918bd2c296f00dd79379fcb", + "sha256_in_prefix": "a4c110008e4d791a4577ce6ebee33bc512ec3e3db918bd2c296f00dd79379fcb", + "size_in_bytes": 1248 + }, + { + "_path": "include/python3.12/cpython/context.h", + "path_type": "hardlink", + "sha256": "9e34d54a789cbf0d78d5ebb126e8384342c08dd81d944d10e3d8f0de0bbba10a", + "sha256_in_prefix": "9e34d54a789cbf0d78d5ebb126e8384342c08dd81d944d10e3d8f0de0bbba10a", + "size_in_bytes": 1965 + }, + { + "_path": "include/python3.12/cpython/descrobject.h", + "path_type": "hardlink", + "sha256": "a1ee0124142fe91204d0c5e85169b55341b2167111a1447e3a8ed50f9bd5a12f", + "sha256_in_prefix": "a1ee0124142fe91204d0c5e85169b55341b2167111a1447e3a8ed50f9bd5a12f", + "size_in_bytes": 1642 + }, + { + "_path": "include/python3.12/cpython/dictobject.h", + "path_type": "hardlink", + "sha256": "5ac16d73f22038b12bd06904cf02a14bbdd723234d1d899354f1a041e8659505", + "sha256_in_prefix": "5ac16d73f22038b12bd06904cf02a14bbdd723234d1d899354f1a041e8659505", + "size_in_bytes": 4686 + }, + { + "_path": "include/python3.12/cpython/fileobject.h", + "path_type": "hardlink", + "sha256": "16ab872cbe2bb3351ce3090873440903b1460c1d68aed483c70c31edc4140ba2", + "sha256_in_prefix": "16ab872cbe2bb3351ce3090873440903b1460c1d68aed483c70c31edc4140ba2", + "size_in_bytes": 818 + }, + { + "_path": "include/python3.12/cpython/fileutils.h", + "path_type": "hardlink", + "sha256": "d7a2f703c6fba2efabd0b1cc916ad36074363a27a000987cfad17e21f04d44f1", + "sha256_in_prefix": "d7a2f703c6fba2efabd0b1cc916ad36074363a27a000987cfad17e21f04d44f1", + "size_in_bytes": 232 + }, + { + "_path": "include/python3.12/cpython/floatobject.h", + "path_type": "hardlink", + "sha256": "f1c53f5b87f221db66004b836aa2fc9462aa46c2fbe46b417a8ddc803ce2f585", + "sha256_in_prefix": "f1c53f5b87f221db66004b836aa2fc9462aa46c2fbe46b417a8ddc803ce2f585", + "size_in_bytes": 900 + }, + { + "_path": "include/python3.12/cpython/frameobject.h", + "path_type": "hardlink", + "sha256": "e1421b58c6a25efb56f423a749c313e3f5392f58cc0c7f4f09b0412217a4a734", + "sha256_in_prefix": "e1421b58c6a25efb56f423a749c313e3f5392f58cc0c7f4f09b0412217a4a734", + "size_in_bytes": 1108 + }, + { + "_path": "include/python3.12/cpython/funcobject.h", + "path_type": "hardlink", + "sha256": "744cd5bc453de548ec454f1fb26e58efa581f3a51dee2b09872cb45bc3a5f981", + "sha256_in_prefix": "744cd5bc453de548ec454f1fb26e58efa581f3a51dee2b09872cb45bc3a5f981", + "size_in_bytes": 7150 + }, + { + "_path": "include/python3.12/cpython/genobject.h", + "path_type": "hardlink", + "sha256": "24f9bd2f19341dc73c7deebca17117ea3a94fd89865c0c6548e1bf5882f51d95", + "sha256_in_prefix": "24f9bd2f19341dc73c7deebca17117ea3a94fd89865c0c6548e1bf5882f51d95", + "size_in_bytes": 3316 + }, + { + "_path": "include/python3.12/cpython/import.h", + "path_type": "hardlink", + "sha256": "f3a6cb7ea774d2ffcb64c834dffaf008e8f9f3f10b23600d5522d82176cb241c", + "sha256_in_prefix": "f3a6cb7ea774d2ffcb64c834dffaf008e8f9f3f10b23600d5522d82176cb241c", + "size_in_bytes": 1623 + }, + { + "_path": "include/python3.12/cpython/initconfig.h", + "path_type": "hardlink", + "sha256": "86e3b9d1de6f310415912e2cdfdc276e311c026ec7fdf6190893f6313cd860a3", + "sha256_in_prefix": "86e3b9d1de6f310415912e2cdfdc276e311c026ec7fdf6190893f6313cd860a3", + "size_in_bytes": 7820 + }, + { + "_path": "include/python3.12/cpython/interpreteridobject.h", + "path_type": "hardlink", + "sha256": "8fc79784d556245d7b7f382063ef3797e3aebd0a6b375a95027dd63a5dfa30b6", + "sha256_in_prefix": "8fc79784d556245d7b7f382063ef3797e3aebd0a6b375a95027dd63a5dfa30b6", + "size_in_bytes": 387 + }, + { + "_path": "include/python3.12/cpython/listobject.h", + "path_type": "hardlink", + "sha256": "0ccca44b405add7a8c19d7a5e7701e06ab904cce5c430016b50f7968aef296fe", + "sha256_in_prefix": "0ccca44b405add7a8c19d7a5e7701e06ab904cce5c430016b50f7968aef296fe", + "size_in_bytes": 1633 + }, + { + "_path": "include/python3.12/cpython/longintrepr.h", + "path_type": "hardlink", + "sha256": "e2acf37f668089278081539473eeedc8537b848fcd2eb91f53172701c014b9c3", + "sha256_in_prefix": "e2acf37f668089278081539473eeedc8537b848fcd2eb91f53172701c014b9c3", + "size_in_bytes": 4889 + }, + { + "_path": "include/python3.12/cpython/longobject.h", + "path_type": "hardlink", + "sha256": "b443782d6b69a2cfd141ac13ac8b7a8d69e47bfdae9df984de4991b2d248b8b8", + "sha256_in_prefix": "b443782d6b69a2cfd141ac13ac8b7a8d69e47bfdae9df984de4991b2d248b8b8", + "size_in_bytes": 4679 + }, + { + "_path": "include/python3.12/cpython/memoryobject.h", + "path_type": "hardlink", + "sha256": "62f414f21611a31f453af7c8326b309aad8f79166087a951844921c50cc84dc7", + "sha256_in_prefix": "62f414f21611a31f453af7c8326b309aad8f79166087a951844921c50cc84dc7", + "size_in_bytes": 2272 + }, + { + "_path": "include/python3.12/cpython/methodobject.h", + "path_type": "hardlink", + "sha256": "5beb9f3b68ac72efe403a1b0a3fbbb14a5606a49a2840b9c7e9ff243d82d79b9", + "sha256_in_prefix": "5beb9f3b68ac72efe403a1b0a3fbbb14a5606a49a2840b9c7e9ff243d82d79b9", + "size_in_bytes": 2276 + }, + { + "_path": "include/python3.12/cpython/modsupport.h", + "path_type": "hardlink", + "sha256": "a8d08132874d9d642ade82e62e87a510577b7bd4ab0685a90b044cc3b005232d", + "sha256_in_prefix": "a8d08132874d9d642ade82e62e87a510577b7bd4ab0685a90b044cc3b005232d", + "size_in_bytes": 4336 + }, + { + "_path": "include/python3.12/cpython/object.h", + "path_type": "hardlink", + "sha256": "f412fd84202ef228e6bf239c9a5a408b8d8623481a15452f8f3331dfc6342134", + "sha256_in_prefix": "f412fd84202ef228e6bf239c9a5a408b8d8623481a15452f8f3331dfc6342134", + "size_in_bytes": 21212 + }, + { + "_path": "include/python3.12/cpython/objimpl.h", + "path_type": "hardlink", + "sha256": "d99f0cff4297590a49f6616dbf1b04a06c745bed0a280ae35acc56fb3c47f2f3", + "sha256_in_prefix": "d99f0cff4297590a49f6616dbf1b04a06c745bed0a280ae35acc56fb3c47f2f3", + "size_in_bytes": 3316 + }, + { + "_path": "include/python3.12/cpython/odictobject.h", + "path_type": "hardlink", + "sha256": "97dc6296e890463fc6994247e885df65cd4024dc1b05facfdc984c37d646b919", + "sha256_in_prefix": "97dc6296e890463fc6994247e885df65cd4024dc1b05facfdc984c37d646b919", + "size_in_bytes": 1311 + }, + { + "_path": "include/python3.12/cpython/picklebufobject.h", + "path_type": "hardlink", + "sha256": "7040fb48462296c903f2f0d24d2b54e0de63cf7512dcf8d3048a0cadf7d94fd0", + "sha256_in_prefix": "7040fb48462296c903f2f0d24d2b54e0de63cf7512dcf8d3048a0cadf7d94fd0", + "size_in_bytes": 848 + }, + { + "_path": "include/python3.12/cpython/pthread_stubs.h", + "path_type": "hardlink", + "sha256": "0f3108e0430ee937098c86352d2ced6e3ec7f5cb5bc7e06eebee58cf779fcd89", + "sha256_in_prefix": "0f3108e0430ee937098c86352d2ced6e3ec7f5cb5bc7e06eebee58cf779fcd89", + "size_in_bytes": 3505 + }, + { + "_path": "include/python3.12/cpython/pyctype.h", + "path_type": "hardlink", + "sha256": "10b5ccbc210fd2832e9c34849a3952e8db75f0016add89188358b1da6a8f3dbb", + "sha256_in_prefix": "10b5ccbc210fd2832e9c34849a3952e8db75f0016add89188358b1da6a8f3dbb", + "size_in_bytes": 1387 + }, + { + "_path": "include/python3.12/cpython/pydebug.h", + "path_type": "hardlink", + "sha256": "83d72e867b4fc9ac87efdfcb41c3d30ec20fa239fe6a74d1b85aa92e1f8d9506", + "sha256_in_prefix": "83d72e867b4fc9ac87efdfcb41c3d30ec20fa239fe6a74d1b85aa92e1f8d9506", + "size_in_bytes": 1413 + }, + { + "_path": "include/python3.12/cpython/pyerrors.h", + "path_type": "hardlink", + "sha256": "1f5070d787263e3aa8845dc90b38aaeb0945be83ef2ba993a40b4af926daacad", + "sha256_in_prefix": "1f5070d787263e3aa8845dc90b38aaeb0945be83ef2ba993a40b4af926daacad", + "size_in_bytes": 4276 + }, + { + "_path": "include/python3.12/cpython/pyfpe.h", + "path_type": "hardlink", + "sha256": "ea7bfa7d891a0b5372d8b40a57d1b466b7824296e5c3f8d50b1a7cde084429b7", + "sha256_in_prefix": "ea7bfa7d891a0b5372d8b40a57d1b466b7824296e5c3f8d50b1a7cde084429b7", + "size_in_bytes": 444 + }, + { + "_path": "include/python3.12/cpython/pyframe.h", + "path_type": "hardlink", + "sha256": "0c7ea17874b967892de6f6623aa426d5eaf267a56e6bbb84b3fefa40e59ec1b8", + "sha256_in_prefix": "0c7ea17874b967892de6f6623aa426d5eaf267a56e6bbb84b3fefa40e59ec1b8", + "size_in_bytes": 1479 + }, + { + "_path": "include/python3.12/cpython/pylifecycle.h", + "path_type": "hardlink", + "sha256": "02505815b8bc3e33fe31a11f4f7f960826aa1dce2c4cee6d62d2a0394470c9bf", + "sha256_in_prefix": "02505815b8bc3e33fe31a11f4f7f960826aa1dce2c4cee6d62d2a0394470c9bf", + "size_in_bytes": 3423 + }, + { + "_path": "include/python3.12/cpython/pymem.h", + "path_type": "hardlink", + "sha256": "8a3795a9350b10548e8ad6d37dad69be2abd3870a751e67faa32a19a090608db", + "sha256_in_prefix": "8a3795a9350b10548e8ad6d37dad69be2abd3870a751e67faa32a19a090608db", + "size_in_bytes": 3379 + }, + { + "_path": "include/python3.12/cpython/pystate.h", + "path_type": "hardlink", + "sha256": "11494795dd1d6945fbf8036af5ccf247463e94d405a760924a1c78f78ebfc4ec", + "sha256_in_prefix": "11494795dd1d6945fbf8036af5ccf247463e94d405a760924a1c78f78ebfc4ec", + "size_in_bytes": 17228 + }, + { + "_path": "include/python3.12/cpython/pythonrun.h", + "path_type": "hardlink", + "sha256": "3290ea064e7450aaf43320a5fcac22d9b36acfab43d1d2c3381ade4b726ced8f", + "sha256_in_prefix": "3290ea064e7450aaf43320a5fcac22d9b36acfab43d1d2c3381ade4b726ced8f", + "size_in_bytes": 4903 + }, + { + "_path": "include/python3.12/cpython/pythread.h", + "path_type": "hardlink", + "sha256": "7239113064e41ba5a678b665af17bee1f878d51076f6d82f89d5d52151ebf573", + "sha256_in_prefix": "7239113064e41ba5a678b665af17bee1f878d51076f6d82f89d5d52151ebf573", + "size_in_bytes": 1426 + }, + { + "_path": "include/python3.12/cpython/pytime.h", + "path_type": "hardlink", + "sha256": "64b70f16b9e6845e0378f2f9108952731ca5bd43b33609781dccd5af70d60204", + "sha256_in_prefix": "64b70f16b9e6845e0378f2f9108952731ca5bd43b33609781dccd5af70d60204", + "size_in_bytes": 12375 + }, + { + "_path": "include/python3.12/cpython/setobject.h", + "path_type": "hardlink", + "sha256": "c965bf093325e20c319af5183a8e5723d4d0b373cb6d1b8781df8c1e588963c0", + "sha256_in_prefix": "c965bf093325e20c319af5183a8e5723d4d0b373cb6d1b8781df8c1e588963c0", + "size_in_bytes": 2146 + }, + { + "_path": "include/python3.12/cpython/sysmodule.h", + "path_type": "hardlink", + "sha256": "d4936db24692cccadb19c11accda260787f95e5658f88cfc752d9a49344ee051", + "sha256_in_prefix": "d4936db24692cccadb19c11accda260787f95e5658f88cfc752d9a49344ee051", + "size_in_bytes": 489 + }, + { + "_path": "include/python3.12/cpython/traceback.h", + "path_type": "hardlink", + "sha256": "7898a3c168973e1119fb3b57f144be627c1468082ab0b91d001dd876dd1dbcb6", + "sha256_in_prefix": "7898a3c168973e1119fb3b57f144be627c1468082ab0b91d001dd876dd1dbcb6", + "size_in_bytes": 444 + }, + { + "_path": "include/python3.12/cpython/tupleobject.h", + "path_type": "hardlink", + "sha256": "301c0720038f50d8e9087b38cf1392524abf9e28262b677d841fc1a7e172c3f3", + "sha256_in_prefix": "301c0720038f50d8e9087b38cf1392524abf9e28262b677d841fc1a7e172c3f3", + "size_in_bytes": 1377 + }, + { + "_path": "include/python3.12/cpython/unicodeobject.h", + "path_type": "hardlink", + "sha256": "1fece91b6ddd3b131e4c2783973b9226f1efe6e53a2530da21bb75f18ebad6c5", + "sha256_in_prefix": "1fece91b6ddd3b131e4c2783973b9226f1efe6e53a2530da21bb75f18ebad6c5", + "size_in_bytes": 34467 + }, + { + "_path": "include/python3.12/cpython/warnings.h", + "path_type": "hardlink", + "sha256": "b758a2e42b0c497ea811464f579603d14fc30b50bd6ebe064d8d2a7df7e2bd76", + "sha256_in_prefix": "b758a2e42b0c497ea811464f579603d14fc30b50bd6ebe064d8d2a7df7e2bd76", + "size_in_bytes": 564 + }, + { + "_path": "include/python3.12/cpython/weakrefobject.h", + "path_type": "hardlink", + "sha256": "be0ab05169da7efcd13aba0ddc58604a80328d4e60349df6d4efdd1bf363e1a2", + "sha256_in_prefix": "be0ab05169da7efcd13aba0ddc58604a80328d4e60349df6d4efdd1bf363e1a2", + "size_in_bytes": 2032 + }, + { + "_path": "include/python3.12/datetime.h", + "path_type": "hardlink", + "sha256": "f3d8192cada0f490a67233e615e5974f062501b2876147118ddb042ee4a7f988", + "sha256_in_prefix": "f3d8192cada0f490a67233e615e5974f062501b2876147118ddb042ee4a7f988", + "size_in_bytes": 9769 + }, + { + "_path": "include/python3.12/descrobject.h", + "path_type": "hardlink", + "sha256": "2956a488f4c4c61341e361dac949cfa4a217e0fbd0097892513b02363c9570a7", + "sha256_in_prefix": "2956a488f4c4c61341e361dac949cfa4a217e0fbd0097892513b02363c9570a7", + "size_in_bytes": 3080 + }, + { + "_path": "include/python3.12/dictobject.h", + "path_type": "hardlink", + "sha256": "08f92e2a4421d3e81fa0fa1b60cbe97f2d69897226368481b0ffc41eeb202356", + "sha256_in_prefix": "08f92e2a4421d3e81fa0fa1b60cbe97f2d69897226368481b0ffc41eeb202356", + "size_in_bytes": 3860 + }, + { + "_path": "include/python3.12/dynamic_annotations.h", + "path_type": "hardlink", + "sha256": "3e4366f7d082835049730358d277a5ad7a60e16d1601f5622f0a045a37c152ac", + "sha256_in_prefix": "3e4366f7d082835049730358d277a5ad7a60e16d1601f5622f0a045a37c152ac", + "size_in_bytes": 22471 + }, + { + "_path": "include/python3.12/enumobject.h", + "path_type": "hardlink", + "sha256": "2244fe250db9995068fe74dce0e23fd70c12b03fd94751d98b773be8f64896b6", + "sha256_in_prefix": "2244fe250db9995068fe74dce0e23fd70c12b03fd94751d98b773be8f64896b6", + "size_in_bytes": 253 + }, + { + "_path": "include/python3.12/errcode.h", + "path_type": "hardlink", + "sha256": "e09ffcbb80580103d52992eb5fd8fd01b9930fda5e8f3874bfb9ee7aa2fe99fa", + "sha256_in_prefix": "e09ffcbb80580103d52992eb5fd8fd01b9930fda5e8f3874bfb9ee7aa2fe99fa", + "size_in_bytes": 1779 + }, + { + "_path": "include/python3.12/exports.h", + "path_type": "hardlink", + "sha256": "d02e9937f747660b218062bcdab504b706cad264b4df993f749d9118f2f7b65c", + "sha256_in_prefix": "d02e9937f747660b218062bcdab504b706cad264b4df993f749d9118f2f7b65c", + "size_in_bytes": 1267 + }, + { + "_path": "include/python3.12/fileobject.h", + "path_type": "hardlink", + "sha256": "133e57cf705cbdaa79a0c115b27e748cc24dedb51ea17b441ff65d05df28a674", + "sha256_in_prefix": "133e57cf705cbdaa79a0c115b27e748cc24dedb51ea17b441ff65d05df28a674", + "size_in_bytes": 1650 + }, + { + "_path": "include/python3.12/fileutils.h", + "path_type": "hardlink", + "sha256": "51ae1c2ca70a8005206f653121d1ba3247f59421c96399739845d687980e9b01", + "sha256_in_prefix": "51ae1c2ca70a8005206f653121d1ba3247f59421c96399739845d687980e9b01", + "size_in_bytes": 507 + }, + { + "_path": "include/python3.12/floatobject.h", + "path_type": "hardlink", + "sha256": "2da72b48fa342e53f72848d468c3c11a9d5b62922f2bd71c286331f54f2364a1", + "sha256_in_prefix": "2da72b48fa342e53f72848d468c3c11a9d5b62922f2bd71c286331f54f2364a1", + "size_in_bytes": 1532 + }, + { + "_path": "include/python3.12/frameobject.h", + "path_type": "hardlink", + "sha256": "969cd93065ce79b81bbc67a65d31b742e23f30bf79d6e44a306963d552ed0c35", + "sha256_in_prefix": "969cd93065ce79b81bbc67a65d31b742e23f30bf79d6e44a306963d552ed0c35", + "size_in_bytes": 336 + }, + { + "_path": "include/python3.12/genericaliasobject.h", + "path_type": "hardlink", + "sha256": "0e53a0b18c114be68eccea9ffd1dd577e204b1f0ada4d3aedc8e7ee0c80fc7f8", + "sha256_in_prefix": "0e53a0b18c114be68eccea9ffd1dd577e204b1f0ada4d3aedc8e7ee0c80fc7f8", + "size_in_bytes": 334 + }, + { + "_path": "include/python3.12/import.h", + "path_type": "hardlink", + "sha256": "4113e1b6afa760c3decce2bb765835adda19861394974cfe301e1ccb482e2b94", + "sha256_in_prefix": "4113e1b6afa760c3decce2bb765835adda19861394974cfe301e1ccb482e2b94", + "size_in_bytes": 3033 + }, + { + "_path": "include/python3.12/internal/pycore_abstract.h", + "path_type": "hardlink", + "sha256": "75ecd34cdcd06fc64fcfa550f66975d755619e7cf06fdae8ecbe2de6ec49ce39", + "sha256_in_prefix": "75ecd34cdcd06fc64fcfa550f66975d755619e7cf06fdae8ecbe2de6ec49ce39", + "size_in_bytes": 611 + }, + { + "_path": "include/python3.12/internal/pycore_asdl.h", + "path_type": "hardlink", + "sha256": "b29dace0f84849c4a24bc3745523a36911cd192bad7ec6fb48aba8facff51d3e", + "sha256_in_prefix": "b29dace0f84849c4a24bc3745523a36911cd192bad7ec6fb48aba8facff51d3e", + "size_in_bytes": 3035 + }, + { + "_path": "include/python3.12/internal/pycore_ast.h", + "path_type": "hardlink", + "sha256": "064b6778fa758fb2580fb8770f77dd0d1eb19323df0e345373788c75754910cf", + "sha256_in_prefix": "064b6778fa758fb2580fb8770f77dd0d1eb19323df0e345373788c75754910cf", + "size_in_bytes": 31288 + }, + { + "_path": "include/python3.12/internal/pycore_ast_state.h", + "path_type": "hardlink", + "sha256": "1d76a7b5207c653a86dec97aab5ba1fcc5c75e94333662792a692cb68e5b26c6", + "sha256_in_prefix": "1d76a7b5207c653a86dec97aab5ba1fcc5c75e94333662792a692cb68e5b26c6", + "size_in_bytes": 6749 + }, + { + "_path": "include/python3.12/internal/pycore_atexit.h", + "path_type": "hardlink", + "sha256": "8c5c88b8452894cf8a5f243ceb9021060f0fe8f5689cbc3e705c19c5edc0798a", + "sha256_in_prefix": "8c5c88b8452894cf8a5f243ceb9021060f0fe8f5689cbc3e705c19c5edc0798a", + "size_in_bytes": 1149 + }, + { + "_path": "include/python3.12/internal/pycore_atomic.h", + "path_type": "hardlink", + "sha256": "95e7118e799ad3faafc8e58a29b2d1f1a4bb94e1aac3273e042f379f8e12d4e6", + "sha256_in_prefix": "95e7118e799ad3faafc8e58a29b2d1f1a4bb94e1aac3273e042f379f8e12d4e6", + "size_in_bytes": 16979 + }, + { + "_path": "include/python3.12/internal/pycore_atomic_funcs.h", + "path_type": "hardlink", + "sha256": "9d5cfa13ad863a0cc1b0ab06861c1f8cfbdc7d730b9c4603e5777a608263d399", + "sha256_in_prefix": "9d5cfa13ad863a0cc1b0ab06861c1f8cfbdc7d730b9c4603e5777a608263d399", + "size_in_bytes": 2438 + }, + { + "_path": "include/python3.12/internal/pycore_bitutils.h", + "path_type": "hardlink", + "sha256": "86628b9cbefe4ff000e1190cd36f37b70a2dad6a4e9231cc2466a84579cc2139", + "sha256_in_prefix": "86628b9cbefe4ff000e1190cd36f37b70a2dad6a4e9231cc2466a84579cc2139", + "size_in_bytes": 6062 + }, + { + "_path": "include/python3.12/internal/pycore_blocks_output_buffer.h", + "path_type": "hardlink", + "sha256": "03fed5054d0d78e3711e73995e484fefb81495c063a5b9ef555c0395d7fc1ebc", + "sha256_in_prefix": "03fed5054d0d78e3711e73995e484fefb81495c063a5b9ef555c0395d7fc1ebc", + "size_in_bytes": 8688 + }, + { + "_path": "include/python3.12/internal/pycore_bytes_methods.h", + "path_type": "hardlink", + "sha256": "1534326dbf027e9bb472be5ccf8b82fab48f3282cc7f6a61629b801fc80afc00", + "sha256_in_prefix": "1534326dbf027e9bb472be5ccf8b82fab48f3282cc7f6a61629b801fc80afc00", + "size_in_bytes": 3384 + }, + { + "_path": "include/python3.12/internal/pycore_bytesobject.h", + "path_type": "hardlink", + "sha256": "d3ecf25cf0f0e9815ac24f496e5ccbbf8d57a10e570da81e84f2b5f6e95b59b8", + "sha256_in_prefix": "d3ecf25cf0f0e9815ac24f496e5ccbbf8d57a10e570da81e84f2b5f6e95b59b8", + "size_in_bytes": 1339 + }, + { + "_path": "include/python3.12/internal/pycore_call.h", + "path_type": "hardlink", + "sha256": "5e780aed2dc991455a0e528fc7baca8df61d2e4bec4e137d7e788668b5750ec5", + "sha256_in_prefix": "5e780aed2dc991455a0e528fc7baca8df61d2e4bec4e137d7e788668b5750ec5", + "size_in_bytes": 3920 + }, + { + "_path": "include/python3.12/internal/pycore_ceval.h", + "path_type": "hardlink", + "sha256": "1af22b50c9ececfc4c3a5f37ecb70cc1c0eefad5a2656e6e22fc088cae54e226", + "sha256_in_prefix": "1af22b50c9ececfc4c3a5f37ecb70cc1c0eefad5a2656e6e22fc088cae54e226", + "size_in_bytes": 5265 + }, + { + "_path": "include/python3.12/internal/pycore_ceval_state.h", + "path_type": "hardlink", + "sha256": "f29e3d6dcac96b0067a17845df8483013230805db10c6f3c5ecd02b9134640e7", + "sha256_in_prefix": "f29e3d6dcac96b0067a17845df8483013230805db10c6f3c5ecd02b9134640e7", + "size_in_bytes": 2744 + }, + { + "_path": "include/python3.12/internal/pycore_code.h", + "path_type": "hardlink", + "sha256": "48e78dd1a12e6afa6e54e26f8e7c4f56e20689b84189d503507c7f6c36819092", + "sha256_in_prefix": "48e78dd1a12e6afa6e54e26f8e7c4f56e20689b84189d503507c7f6c36819092", + "size_in_bytes": 15835 + }, + { + "_path": "include/python3.12/internal/pycore_compile.h", + "path_type": "hardlink", + "sha256": "4d386629f5e0ea801a01122833f11363cf9f1584aef6e9692ffd0b95eda37cbc", + "sha256_in_prefix": "4d386629f5e0ea801a01122833f11363cf9f1584aef6e9692ffd0b95eda37cbc", + "size_in_bytes": 3453 + }, + { + "_path": "include/python3.12/internal/pycore_condvar.h", + "path_type": "hardlink", + "sha256": "89a5d9c366c2e1c312e1ace5067d184380242c944deb698b6a4f53b51abd5826", + "sha256_in_prefix": "89a5d9c366c2e1c312e1ace5067d184380242c944deb698b6a4f53b51abd5826", + "size_in_bytes": 2839 + }, + { + "_path": "include/python3.12/internal/pycore_context.h", + "path_type": "hardlink", + "sha256": "974d6bafbe0164d60dd1bc4f09b5eac9bcc9e2d9066924ba2a2ba6d502f115b5", + "sha256_in_prefix": "974d6bafbe0164d60dd1bc4f09b5eac9bcc9e2d9066924ba2a2ba6d502f115b5", + "size_in_bytes": 1301 + }, + { + "_path": "include/python3.12/internal/pycore_descrobject.h", + "path_type": "hardlink", + "sha256": "d9be424b5c2d109b51338016acab6132f299c0640fc069fb0e1d48575089574e", + "sha256_in_prefix": "d9be424b5c2d109b51338016acab6132f299c0640fc069fb0e1d48575089574e", + "size_in_bytes": 499 + }, + { + "_path": "include/python3.12/internal/pycore_dict.h", + "path_type": "hardlink", + "sha256": "4d51e7184d50a5f8785a1cbdc9f6eb36b86201158ae6e3527884ce2b5dd504bf", + "sha256_in_prefix": "4d51e7184d50a5f8785a1cbdc9f6eb36b86201158ae6e3527884ce2b5dd504bf", + "size_in_bytes": 6384 + }, + { + "_path": "include/python3.12/internal/pycore_dict_state.h", + "path_type": "hardlink", + "sha256": "5a15c2bb4020ce4a1d7a4c651e0f98b4becd910f89cd7c4089c80a0419ec4f1c", + "sha256_in_prefix": "5a15c2bb4020ce4a1d7a4c651e0f98b4becd910f89cd7c4089c80a0419ec4f1c", + "size_in_bytes": 1095 + }, + { + "_path": "include/python3.12/internal/pycore_dtoa.h", + "path_type": "hardlink", + "sha256": "a67261c7187a02a6d2ef7fef8207acb85ce5906f4ee970f4f06822f695f489ad", + "sha256_in_prefix": "a67261c7187a02a6d2ef7fef8207acb85ce5906f4ee970f4f06822f695f489ad", + "size_in_bytes": 1626 + }, + { + "_path": "include/python3.12/internal/pycore_emscripten_signal.h", + "path_type": "hardlink", + "sha256": "1acd47a1c09e365be8c7fa51db31307021cc2e471471fc199e26f317df58c4b8", + "sha256_in_prefix": "1acd47a1c09e365be8c7fa51db31307021cc2e471471fc199e26f317df58c4b8", + "size_in_bytes": 562 + }, + { + "_path": "include/python3.12/internal/pycore_exceptions.h", + "path_type": "hardlink", + "sha256": "4590af737d53afcbd7d559434190d2d8ff4f5cd0e923837721aea5ebb000ef68", + "sha256_in_prefix": "4590af737d53afcbd7d559434190d2d8ff4f5cd0e923837721aea5ebb000ef68", + "size_in_bytes": 842 + }, + { + "_path": "include/python3.12/internal/pycore_faulthandler.h", + "path_type": "hardlink", + "sha256": "6444dce1924eae011d27385183ad1a5de6908501cedce2e1531abd834c68cae7", + "sha256_in_prefix": "6444dce1924eae011d27385183ad1a5de6908501cedce2e1531abd834c68cae7", + "size_in_bytes": 2220 + }, + { + "_path": "include/python3.12/internal/pycore_fileutils.h", + "path_type": "hardlink", + "sha256": "ea9cac693c87dc049f199cecd2844592ee08d0283dc0b059c4caab517932af73", + "sha256_in_prefix": "ea9cac693c87dc049f199cecd2844592ee08d0283dc0b059c4caab517932af73", + "size_in_bytes": 7910 + }, + { + "_path": "include/python3.12/internal/pycore_fileutils_windows.h", + "path_type": "hardlink", + "sha256": "9e976ea0f3457c8b40db0a3b2cfea9e9684737f75282400ec0040ae0df1e6385", + "sha256_in_prefix": "9e976ea0f3457c8b40db0a3b2cfea9e9684737f75282400ec0040ae0df1e6385", + "size_in_bytes": 2724 + }, + { + "_path": "include/python3.12/internal/pycore_floatobject.h", + "path_type": "hardlink", + "sha256": "021fef24c4b7e7390c793af7ccf12ddd94b1871e27d26997b37eb3093d5380b5", + "sha256_in_prefix": "021fef24c4b7e7390c793af7ccf12ddd94b1871e27d26997b37eb3093d5380b5", + "size_in_bytes": 1578 + }, + { + "_path": "include/python3.12/internal/pycore_flowgraph.h", + "path_type": "hardlink", + "sha256": "c58cdc30ce8c853404f55881813ec69d6dbf921f2769ec9e289b5155b7a349db", + "sha256_in_prefix": "c58cdc30ce8c853404f55881813ec69d6dbf921f2769ec9e289b5155b7a349db", + "size_in_bytes": 4630 + }, + { + "_path": "include/python3.12/internal/pycore_format.h", + "path_type": "hardlink", + "sha256": "253cc77e6d11ba20d297813e064650fa965b3653f150bd85f805b94db5f3a98d", + "sha256_in_prefix": "253cc77e6d11ba20d297813e064650fa965b3653f150bd85f805b94db5f3a98d", + "size_in_bytes": 480 + }, + { + "_path": "include/python3.12/internal/pycore_frame.h", + "path_type": "hardlink", + "sha256": "97c7e2722af4c30c240b8b3c867a54b2fe49a4207d2e566c6a19a9d190fd0f8a", + "sha256_in_prefix": "97c7e2722af4c30c240b8b3c867a54b2fe49a4207d2e566c6a19a9d190fd0f8a", + "size_in_bytes": 9256 + }, + { + "_path": "include/python3.12/internal/pycore_function.h", + "path_type": "hardlink", + "sha256": "8fad970bd3f31347aed72b92acd17270dbb6ec5333ab5ed6fe43dc9cf2527841", + "sha256_in_prefix": "8fad970bd3f31347aed72b92acd17270dbb6ec5333ab5ed6fe43dc9cf2527841", + "size_in_bytes": 611 + }, + { + "_path": "include/python3.12/internal/pycore_gc.h", + "path_type": "hardlink", + "sha256": "d0349a94dafb16ec4c05ba5a94d3b9e6cec53fe7b5e0d74216ea31996546f9a3", + "sha256_in_prefix": "d0349a94dafb16ec4c05ba5a94d3b9e6cec53fe7b5e0d74216ea31996546f9a3", + "size_in_bytes": 7658 + }, + { + "_path": "include/python3.12/internal/pycore_genobject.h", + "path_type": "hardlink", + "sha256": "a940f41da1e8d9d12c9c438ea0b4f24e72abc494447bcecd9423b76f54e3402a", + "sha256_in_prefix": "a940f41da1e8d9d12c9c438ea0b4f24e72abc494447bcecd9423b76f54e3402a", + "size_in_bytes": 1186 + }, + { + "_path": "include/python3.12/internal/pycore_getopt.h", + "path_type": "hardlink", + "sha256": "e93393067b66b557b0300e05c10ee904d4be54cadfb214c5328a9225ad199452", + "sha256_in_prefix": "e93393067b66b557b0300e05c10ee904d4be54cadfb214c5328a9225ad199452", + "size_in_bytes": 490 + }, + { + "_path": "include/python3.12/internal/pycore_gil.h", + "path_type": "hardlink", + "sha256": "cf455aacd5651e5b43547ebe69bb324eab84238d92665df53c1df32434bd0d9b", + "sha256_in_prefix": "cf455aacd5651e5b43547ebe69bb324eab84238d92665df53c1df32434bd0d9b", + "size_in_bytes": 1565 + }, + { + "_path": "include/python3.12/internal/pycore_global_objects.h", + "path_type": "hardlink", + "sha256": "ce857a319514b1682eb054bf4a017974b0bf211092819b25f23e877a228090df", + "sha256_in_prefix": "ce857a319514b1682eb054bf4a017974b0bf211092819b25f23e877a228090df", + "size_in_bytes": 3035 + }, + { + "_path": "include/python3.12/internal/pycore_global_objects_fini_generated.h", + "path_type": "hardlink", + "sha256": "79fd2e366a02d8b39181f7466a32af1b1c69ec5566bf301b3d9943c552cf9206", + "sha256_in_prefix": "79fd2e366a02d8b39181f7466a32af1b1c69ec5566bf301b3d9943c552cf9206", + "size_in_bytes": 116175 + }, + { + "_path": "include/python3.12/internal/pycore_global_strings.h", + "path_type": "hardlink", + "sha256": "7991d72ba2c0d8c4cc58575bc29a53fb2a61a89f03335e60320df097d58f1adb", + "sha256_in_prefix": "7991d72ba2c0d8c4cc58575bc29a53fb2a61a89f03335e60320df097d58f1adb", + "size_in_bytes": 25665 + }, + { + "_path": "include/python3.12/internal/pycore_hamt.h", + "path_type": "hardlink", + "sha256": "074b31c2f5701cac43d8dc3e4ede40b2befc6dddfcaa2862cfc8f76234c30ae8", + "sha256_in_prefix": "074b31c2f5701cac43d8dc3e4ede40b2befc6dddfcaa2862cfc8f76234c30ae8", + "size_in_bytes": 3742 + }, + { + "_path": "include/python3.12/internal/pycore_hashtable.h", + "path_type": "hardlink", + "sha256": "690488a7e50ad743e1bb685702fbcfac866ace89d2417a247c1171afdc222261", + "sha256_in_prefix": "690488a7e50ad743e1bb685702fbcfac866ace89d2417a247c1171afdc222261", + "size_in_bytes": 4286 + }, + { + "_path": "include/python3.12/internal/pycore_import.h", + "path_type": "hardlink", + "sha256": "e5b179692f05707e7fb182b908ed46f9a75f4a751b20501a74de2a440c387e1d", + "sha256_in_prefix": "e5b179692f05707e7fb182b908ed46f9a75f4a751b20501a74de2a440c387e1d", + "size_in_bytes": 6358 + }, + { + "_path": "include/python3.12/internal/pycore_initconfig.h", + "path_type": "hardlink", + "sha256": "caf13e2c290ae8375636d0e1f3b1851a90396b3747da650d058c282b8743b558", + "sha256_in_prefix": "caf13e2c290ae8375636d0e1f3b1851a90396b3747da650d058c282b8743b558", + "size_in_bytes": 5706 + }, + { + "_path": "include/python3.12/internal/pycore_instruments.h", + "path_type": "hardlink", + "sha256": "dcdb0593cfa908c036d6661f1a776db48642c0fedd243da88161f45ff3c3e3fa", + "sha256_in_prefix": "dcdb0593cfa908c036d6661f1a776db48642c0fedd243da88161f45ff3c3e3fa", + "size_in_bytes": 2998 + }, + { + "_path": "include/python3.12/internal/pycore_interp.h", + "path_type": "hardlink", + "sha256": "23f5d7884f9e0b212fe79879bbcdc5a2c23c22283db38cadbac6f108bf0f1b75", + "sha256_in_prefix": "23f5d7884f9e0b212fe79879bbcdc5a2c23c22283db38cadbac6f108bf0f1b75", + "size_in_bytes": 9086 + }, + { + "_path": "include/python3.12/internal/pycore_intrinsics.h", + "path_type": "hardlink", + "sha256": "e6d6d1eae51b508196615094a4c17189e9822eacb5c0e94102e78aa7136dd9a8", + "sha256_in_prefix": "e6d6d1eae51b508196615094a4c17189e9822eacb5c0e94102e78aa7136dd9a8", + "size_in_bytes": 1397 + }, + { + "_path": "include/python3.12/internal/pycore_list.h", + "path_type": "hardlink", + "sha256": "470a62bb98b383b85ec738a6577424e6cdd51ae235f4e5ea06c5afdedb6e1652", + "sha256_in_prefix": "470a62bb98b383b85ec738a6577424e6cdd51ae235f4e5ea06c5afdedb6e1652", + "size_in_bytes": 1980 + }, + { + "_path": "include/python3.12/internal/pycore_long.h", + "path_type": "hardlink", + "sha256": "84c0c7bd7ba0c2fbbfb106561e32328e478d8350afe756af6a4862c95d921a06", + "sha256_in_prefix": "84c0c7bd7ba0c2fbbfb106561e32328e478d8350afe756af6a4862c95d921a06", + "size_in_bytes": 7805 + }, + { + "_path": "include/python3.12/internal/pycore_memoryobject.h", + "path_type": "hardlink", + "sha256": "c845bb546019ed9999403018740ee5b26f83f8d888c5288895897cb2bd1b5eec", + "sha256_in_prefix": "c845bb546019ed9999403018740ee5b26f83f8d888c5288895897cb2bd1b5eec", + "size_in_bytes": 383 + }, + { + "_path": "include/python3.12/internal/pycore_moduleobject.h", + "path_type": "hardlink", + "sha256": "55a8f42968545a349d8e0b43cd1822b22ae2cf9fa0fb098c6bb843e7af76e165", + "sha256_in_prefix": "55a8f42968545a349d8e0b43cd1822b22ae2cf9fa0fb098c6bb843e7af76e165", + "size_in_bytes": 1192 + }, + { + "_path": "include/python3.12/internal/pycore_namespace.h", + "path_type": "hardlink", + "sha256": "466fe0e3f48e954d8bfe9e0c73fc9378cf79ca37710778ba6698e1c365304956", + "sha256_in_prefix": "466fe0e3f48e954d8bfe9e0c73fc9378cf79ca37710778ba6698e1c365304956", + "size_in_bytes": 392 + }, + { + "_path": "include/python3.12/internal/pycore_object.h", + "path_type": "hardlink", + "sha256": "ce41bd5e4720ffe713fd4f36798c92ec23ca966799805a0e2d4607dfc1d9dc2e", + "sha256_in_prefix": "ce41bd5e4720ffe713fd4f36798c92ec23ca966799805a0e2d4607dfc1d9dc2e", + "size_in_bytes": 14429 + }, + { + "_path": "include/python3.12/internal/pycore_object_state.h", + "path_type": "hardlink", + "sha256": "3f8950c793e7121629508d4472c6b020f51d9eb583e317383b67da7f931c03ee", + "sha256_in_prefix": "3f8950c793e7121629508d4472c6b020f51d9eb583e317383b67da7f931c03ee", + "size_in_bytes": 737 + }, + { + "_path": "include/python3.12/internal/pycore_obmalloc.h", + "path_type": "hardlink", + "sha256": "d8738004c5dbb5520f401919ed55181a48a9e64a3b51930309fc99fb9d219576", + "sha256_in_prefix": "d8738004c5dbb5520f401919ed55181a48a9e64a3b51930309fc99fb9d219576", + "size_in_bytes": 27284 + }, + { + "_path": "include/python3.12/internal/pycore_obmalloc_init.h", + "path_type": "hardlink", + "sha256": "33853ff5ffac15a8622ff6920ff2bd0bf83d1df7ea6d1563916d05992b3203fb", + "sha256_in_prefix": "33853ff5ffac15a8622ff6920ff2bd0bf83d1df7ea6d1563916d05992b3203fb", + "size_in_bytes": 2085 + }, + { + "_path": "include/python3.12/internal/pycore_opcode.h", + "path_type": "hardlink", + "sha256": "432e30c6145dff72096325d17192d0eff9895b367d4590f782e2d8b9d5f78cd6", + "sha256_in_prefix": "432e30c6145dff72096325d17192d0eff9895b367d4590f782e2d8b9d5f78cd6", + "size_in_bytes": 20081 + }, + { + "_path": "include/python3.12/internal/pycore_opcode_utils.h", + "path_type": "hardlink", + "sha256": "98dfb250812d554278dedee98a2e9cb05b2583b22d2af8ba1aeda6b130a21b40", + "sha256_in_prefix": "98dfb250812d554278dedee98a2e9cb05b2583b22d2af8ba1aeda6b130a21b40", + "size_in_bytes": 2686 + }, + { + "_path": "include/python3.12/internal/pycore_parser.h", + "path_type": "hardlink", + "sha256": "91189a016020eb7de0b1ab8ae38145dbec6b561ae5c75cea15980cb76255ba5b", + "sha256_in_prefix": "91189a016020eb7de0b1ab8ae38145dbec6b561ae5c75cea15980cb76255ba5b", + "size_in_bytes": 1358 + }, + { + "_path": "include/python3.12/internal/pycore_pathconfig.h", + "path_type": "hardlink", + "sha256": "ff96c74aae60eba62bec8c6d52f34471caf07792186bc16d76e7a783f61aa0ed", + "sha256_in_prefix": "ff96c74aae60eba62bec8c6d52f34471caf07792186bc16d76e7a783f61aa0ed", + "size_in_bytes": 606 + }, + { + "_path": "include/python3.12/internal/pycore_pyarena.h", + "path_type": "hardlink", + "sha256": "d4f4e513bae78ff985f51ca48fb7d1a4d57055c59393a1eb661e55e6ec3ba61f", + "sha256_in_prefix": "d4f4e513bae78ff985f51ca48fb7d1a4d57055c59393a1eb661e55e6ec3ba61f", + "size_in_bytes": 2733 + }, + { + "_path": "include/python3.12/internal/pycore_pyerrors.h", + "path_type": "hardlink", + "sha256": "6668d80af8838faf87ff2e37a536c2586e1588d1b23a08f04992c58f6c0630a3", + "sha256_in_prefix": "6668d80af8838faf87ff2e37a536c2586e1588d1b23a08f04992c58f6c0630a3", + "size_in_bytes": 2783 + }, + { + "_path": "include/python3.12/internal/pycore_pyhash.h", + "path_type": "hardlink", + "sha256": "7c631d06afad90fa9c2ddc8dc04b7c2855ee5aa6e7ece0b22d0a966a702abf73", + "sha256_in_prefix": "7c631d06afad90fa9c2ddc8dc04b7c2855ee5aa6e7ece0b22d0a966a702abf73", + "size_in_bytes": 709 + }, + { + "_path": "include/python3.12/internal/pycore_pylifecycle.h", + "path_type": "hardlink", + "sha256": "f6a91e690b8e5d3dca52dcdff63d36a6ad9ad85b7ee1edfc14215cc0483059fa", + "sha256_in_prefix": "f6a91e690b8e5d3dca52dcdff63d36a6ad9ad85b7ee1edfc14215cc0483059fa", + "size_in_bytes": 3365 + }, + { + "_path": "include/python3.12/internal/pycore_pymath.h", + "path_type": "hardlink", + "sha256": "6dd3ea0f9a84bfa3a2eb0a2b7fa1af1dc8aadad3e74305e13f194a1586815376", + "sha256_in_prefix": "6dd3ea0f9a84bfa3a2eb0a2b7fa1af1dc8aadad3e74305e13f194a1586815376", + "size_in_bytes": 8600 + }, + { + "_path": "include/python3.12/internal/pycore_pymem.h", + "path_type": "hardlink", + "sha256": "ad0b35bbf5e665e90223499f8954bfcf36448b1634d54501b0c84d08680323ca", + "sha256_in_prefix": "ad0b35bbf5e665e90223499f8954bfcf36448b1634d54501b0c84d08680323ca", + "size_in_bytes": 3040 + }, + { + "_path": "include/python3.12/internal/pycore_pymem_init.h", + "path_type": "hardlink", + "sha256": "82a1418ee1867e5e9a2717e8a1acfec2e2ff3ef07225e30be7c8cd8f6e29a7ba", + "sha256_in_prefix": "82a1418ee1867e5e9a2717e8a1acfec2e2ff3ef07225e30be7c8cd8f6e29a7ba", + "size_in_bytes": 2654 + }, + { + "_path": "include/python3.12/internal/pycore_pystate.h", + "path_type": "hardlink", + "sha256": "c06823811bf5dd3d84f40d6a087452da5915e3ad277afef2202c9e86e833ce00", + "sha256_in_prefix": "c06823811bf5dd3d84f40d6a087452da5915e3ad277afef2202c9e86e833ce00", + "size_in_bytes": 4982 + }, + { + "_path": "include/python3.12/internal/pycore_pythread.h", + "path_type": "hardlink", + "sha256": "ba04eed4d18d6110982cc58800fda11f3899c61fed644ff9e52a4adedb7b750a", + "sha256_in_prefix": "ba04eed4d18d6110982cc58800fda11f3899c61fed644ff9e52a4adedb7b750a", + "size_in_bytes": 2075 + }, + { + "_path": "include/python3.12/internal/pycore_range.h", + "path_type": "hardlink", + "sha256": "824c5023a85a9c1c2dd50fecf442d12c7b2966e0e71a2d291f6f17f7fd8c29bc", + "sha256_in_prefix": "824c5023a85a9c1c2dd50fecf442d12c7b2966e0e71a2d291f6f17f7fd8c29bc", + "size_in_bytes": 346 + }, + { + "_path": "include/python3.12/internal/pycore_runtime.h", + "path_type": "hardlink", + "sha256": "d47fe4de4c245e2f90ce73792337565cae6ce95d8e2cd08bcda43ec92832b1ac", + "sha256_in_prefix": "d47fe4de4c245e2f90ce73792337565cae6ce95d8e2cd08bcda43ec92832b1ac", + "size_in_bytes": 8429 + }, + { + "_path": "include/python3.12/internal/pycore_runtime_init.h", + "path_type": "hardlink", + "sha256": "60d97c6edbd7eaf3841ce88d3f33794b4c3dfead870914f021e1425e11670321", + "sha256_in_prefix": "60d97c6edbd7eaf3841ce88d3f33794b4c3dfead870914f021e1425e11670321", + "size_in_bytes": 6087 + }, + { + "_path": "include/python3.12/internal/pycore_runtime_init_generated.h", + "path_type": "hardlink", + "sha256": "0c209438a3b41fbbfaffc76669325328d074be692d96c99eea255366689e4055", + "sha256_in_prefix": "0c209438a3b41fbbfaffc76669325328d074be692d96c99eea255366689e4055", + "size_in_bytes": 46045 + }, + { + "_path": "include/python3.12/internal/pycore_signal.h", + "path_type": "hardlink", + "sha256": "186835a8702a10bb1f3f63185d50874f24885716707717f620d3ffd0a2039679", + "sha256_in_prefix": "186835a8702a10bb1f3f63185d50874f24885716707717f620d3ffd0a2039679", + "size_in_bytes": 2611 + }, + { + "_path": "include/python3.12/internal/pycore_sliceobject.h", + "path_type": "hardlink", + "sha256": "e8b9ba794081a75bf73f0eb64089a766b5bd04b076d4368a14a83ff43ce909be", + "sha256_in_prefix": "e8b9ba794081a75bf73f0eb64089a766b5bd04b076d4368a14a83ff43ce909be", + "size_in_bytes": 414 + }, + { + "_path": "include/python3.12/internal/pycore_strhex.h", + "path_type": "hardlink", + "sha256": "45783d1137fc33a8d9e457692227e8395a93b27c76205f50ad7bd8f00fe7aefb", + "sha256_in_prefix": "45783d1137fc33a8d9e457692227e8395a93b27c76205f50ad7bd8f00fe7aefb", + "size_in_bytes": 937 + }, + { + "_path": "include/python3.12/internal/pycore_structseq.h", + "path_type": "hardlink", + "sha256": "e1c1be3681fec8c1146d5a084869c1bbabcbe68223382cdab8536c8b88958891", + "sha256_in_prefix": "e1c1be3681fec8c1146d5a084869c1bbabcbe68223382cdab8536c8b88958891", + "size_in_bytes": 923 + }, + { + "_path": "include/python3.12/internal/pycore_symtable.h", + "path_type": "hardlink", + "sha256": "2f532ac82c3415dbc048f35451760a8203a67ca513b85e220fc38f5c10655db5", + "sha256_in_prefix": "2f532ac82c3415dbc048f35451760a8203a67ca513b85e220fc38f5c10655db5", + "size_in_bytes": 6852 + }, + { + "_path": "include/python3.12/internal/pycore_sysmodule.h", + "path_type": "hardlink", + "sha256": "2c22c3f98c917dee3d954957f36713e2ddd96a27b076e05f7360c629f37e983d", + "sha256_in_prefix": "2c22c3f98c917dee3d954957f36713e2ddd96a27b076e05f7360c629f37e983d", + "size_in_bytes": 734 + }, + { + "_path": "include/python3.12/internal/pycore_time.h", + "path_type": "hardlink", + "sha256": "6838118a537e71edaf76290da15cbf2da19499df1ee4e30b15f35bb4b9257b70", + "sha256_in_prefix": "6838118a537e71edaf76290da15cbf2da19499df1ee4e30b15f35bb4b9257b70", + "size_in_bytes": 388 + }, + { + "_path": "include/python3.12/internal/pycore_token.h", + "path_type": "hardlink", + "sha256": "91c75ef718b8e8be2383fdcea502c1e63ebfa6d681afd45672e379ea7e5d3668", + "sha256_in_prefix": "91c75ef718b8e8be2383fdcea502c1e63ebfa6d681afd45672e379ea7e5d3668", + "size_in_bytes": 3050 + }, + { + "_path": "include/python3.12/internal/pycore_traceback.h", + "path_type": "hardlink", + "sha256": "3f9dfb009dc161f2d979f5af76d660611264b5d0b1b4adeeae10d30ee0999ede", + "sha256_in_prefix": "3f9dfb009dc161f2d979f5af76d660611264b5d0b1b4adeeae10d30ee0999ede", + "size_in_bytes": 3501 + }, + { + "_path": "include/python3.12/internal/pycore_tracemalloc.h", + "path_type": "hardlink", + "sha256": "61ac9b846ae579c667d20034c9c4004a07ab3ff039848ddeeec8d9c39ff1331a", + "sha256_in_prefix": "61ac9b846ae579c667d20034c9c4004a07ab3ff039848ddeeec8d9c39ff1331a", + "size_in_bytes": 3075 + }, + { + "_path": "include/python3.12/internal/pycore_tuple.h", + "path_type": "hardlink", + "sha256": "de5677ac0809abf2744ebdd94768b6974e75ea62cc2cee44c4f433e2b818f953", + "sha256_in_prefix": "de5677ac0809abf2744ebdd94768b6974e75ea62cc2cee44c4f433e2b818f953", + "size_in_bytes": 2197 + }, + { + "_path": "include/python3.12/internal/pycore_typeobject.h", + "path_type": "hardlink", + "sha256": "9af7c474e699753e6830949962176eab1f2e3ffa9616a24ab395001fc75db90b", + "sha256_in_prefix": "9af7c474e699753e6830949962176eab1f2e3ffa9616a24ab395001fc75db90b", + "size_in_bytes": 4669 + }, + { + "_path": "include/python3.12/internal/pycore_typevarobject.h", + "path_type": "hardlink", + "sha256": "b925204918e577bfb667a64f5f56e410cba0bc518207ed8535d1fcf1bdd6ab00", + "sha256_in_prefix": "b925204918e577bfb667a64f5f56e410cba0bc518207ed8535d1fcf1bdd6ab00", + "size_in_bytes": 763 + }, + { + "_path": "include/python3.12/internal/pycore_ucnhash.h", + "path_type": "hardlink", + "sha256": "6d9077e875703e5db7daf293a6c7ea3d43d1ee84dec137a950f17a26e9348eb5", + "sha256_in_prefix": "6d9077e875703e5db7daf293a6c7ea3d43d1ee84dec137a950f17a26e9348eb5", + "size_in_bytes": 898 + }, + { + "_path": "include/python3.12/internal/pycore_unicodeobject.h", + "path_type": "hardlink", + "sha256": "916e12522af51502be463a9e722e1e5017827e1d8da62ac68a03887185c1c278", + "sha256_in_prefix": "916e12522af51502be463a9e722e1e5017827e1d8da62ac68a03887185c1c278", + "size_in_bytes": 1966 + }, + { + "_path": "include/python3.12/internal/pycore_unicodeobject_generated.h", + "path_type": "hardlink", + "sha256": "40f9a9c1b38fff0c3b512dd518c8df9a34493775b3c2ffe14f5e854dc4660e06", + "sha256_in_prefix": "40f9a9c1b38fff0c3b512dd518c8df9a34493775b3c2ffe14f5e854dc4660e06", + "size_in_bytes": 91455 + }, + { + "_path": "include/python3.12/internal/pycore_unionobject.h", + "path_type": "hardlink", + "sha256": "f1c5bbdf5660e54872ff1555c179cf6c80f8e04cac41e974b7964e21f82be18c", + "sha256_in_prefix": "f1c5bbdf5660e54872ff1555c179cf6c80f8e04cac41e974b7964e21f82be18c", + "size_in_bytes": 682 + }, + { + "_path": "include/python3.12/internal/pycore_warnings.h", + "path_type": "hardlink", + "sha256": "3229b207245cb9442f09991df7084c8e4cb87cb073a14a2d520bd92634371fcb", + "sha256_in_prefix": "3229b207245cb9442f09991df7084c8e4cb87cb073a14a2d520bd92634371fcb", + "size_in_bytes": 740 + }, + { + "_path": "include/python3.12/interpreteridobject.h", + "path_type": "hardlink", + "sha256": "b497c869333bdf1f79a580a36e9a0ed64fee226daa1d2d45bdfe16c01e52d73c", + "sha256_in_prefix": "b497c869333bdf1f79a580a36e9a0ed64fee226daa1d2d45bdfe16c01e52d73c", + "size_in_bytes": 333 + }, + { + "_path": "include/python3.12/intrcheck.h", + "path_type": "hardlink", + "sha256": "696fe17618c579a8cbaad9b86175f60d43ea0b9e8aaaa1d65ad256d53dc163c1", + "sha256_in_prefix": "696fe17618c579a8cbaad9b86175f60d43ea0b9e8aaaa1d65ad256d53dc163c1", + "size_in_bytes": 772 + }, + { + "_path": "include/python3.12/iterobject.h", + "path_type": "hardlink", + "sha256": "6b16711d2bb6cee55e4288f84142d592eebf07321e32998a5abe2c06deeb77b0", + "sha256_in_prefix": "6b16711d2bb6cee55e4288f84142d592eebf07321e32998a5abe2c06deeb77b0", + "size_in_bytes": 597 + }, + { + "_path": "include/python3.12/listobject.h", + "path_type": "hardlink", + "sha256": "f4cad9a1f48d27a9a7f56702ab0fe785013eb336ea919197600d86a6e54fa5bf", + "sha256_in_prefix": "f4cad9a1f48d27a9a7f56702ab0fe785013eb336ea919197600d86a6e54fa5bf", + "size_in_bytes": 1782 + }, + { + "_path": "include/python3.12/longobject.h", + "path_type": "hardlink", + "sha256": "0567b258763af5e6cb0ecba02135b41b012425a673d4da8c87db1333ac638901", + "sha256_in_prefix": "0567b258763af5e6cb0ecba02135b41b012425a673d4da8c87db1333ac638901", + "size_in_bytes": 3739 + }, + { + "_path": "include/python3.12/marshal.h", + "path_type": "hardlink", + "sha256": "d7f5760ef6496776cee99aca5491789f6ab261a78b156b5758538ea15e1827e5", + "sha256_in_prefix": "d7f5760ef6496776cee99aca5491789f6ab261a78b156b5758538ea15e1827e5", + "size_in_bytes": 827 + }, + { + "_path": "include/python3.12/memoryobject.h", + "path_type": "hardlink", + "sha256": "efb734845a1366d77f6351cbb954c08681d4acfe6a53e41e82dd45fa881e0090", + "sha256_in_prefix": "efb734845a1366d77f6351cbb954c08681d4acfe6a53e41e82dd45fa881e0090", + "size_in_bytes": 1081 + }, + { + "_path": "include/python3.12/methodobject.h", + "path_type": "hardlink", + "sha256": "059e19bd8d418c8bf1481e301340f989317ba7b56de94729a19aae26fee3da62", + "sha256_in_prefix": "059e19bd8d418c8bf1481e301340f989317ba7b56de94729a19aae26fee3da62", + "size_in_bytes": 5076 + }, + { + "_path": "include/python3.12/modsupport.h", + "path_type": "hardlink", + "sha256": "064d1440d862d08f296c1cbe868e417af12b34f770be515461211f5beade04ff", + "sha256_in_prefix": "064d1440d862d08f296c1cbe868e417af12b34f770be515461211f5beade04ff", + "size_in_bytes": 6515 + }, + { + "_path": "include/python3.12/moduleobject.h", + "path_type": "hardlink", + "sha256": "5eb48f5d99322d7912a5c6f2b3a974e283c7a6045f79a503d7e09f3ac15b42ec", + "sha256_in_prefix": "5eb48f5d99322d7912a5c6f2b3a974e283c7a6045f79a503d7e09f3ac15b42ec", + "size_in_bytes": 3559 + }, + { + "_path": "include/python3.12/object.h", + "path_type": "hardlink", + "sha256": "68b97095c521fcb3fab7193e166870b0c040c8f19ac50efb42088364862503a7", + "sha256_in_prefix": "68b97095c521fcb3fab7193e166870b0c040c8f19ac50efb42088364862503a7", + "size_in_bytes": 37155 + }, + { + "_path": "include/python3.12/objimpl.h", + "path_type": "hardlink", + "sha256": "8828a8db3e9f14b5ca2d59b1d8c05f6bf54fae26736ae039b7420c886142dba2", + "sha256_in_prefix": "8828a8db3e9f14b5ca2d59b1d8c05f6bf54fae26736ae039b7420c886142dba2", + "size_in_bytes": 9238 + }, + { + "_path": "include/python3.12/opcode.h", + "path_type": "hardlink", + "sha256": "4e8c6eee859813845b3a9dfe9e08ca4cc607a7f884048f5a6cebef6bdcc5d33d", + "sha256_in_prefix": "4e8c6eee859813845b3a9dfe9e08ca4cc607a7f884048f5a6cebef6bdcc5d33d", + "size_in_bytes": 12808 + }, + { + "_path": "include/python3.12/osdefs.h", + "path_type": "hardlink", + "sha256": "8372e9c507949a88ed3cad5fd0a830190d60a1655e9a3f59ef4d0832c06a041c", + "sha256_in_prefix": "8372e9c507949a88ed3cad5fd0a830190d60a1655e9a3f59ef4d0832c06a041c", + "size_in_bytes": 737 + }, + { + "_path": "include/python3.12/osmodule.h", + "path_type": "hardlink", + "sha256": "c013935b48f48ca8ce249a4d482c55e3fb6f1cfe786c5a32a57969bb74a779d9", + "sha256_in_prefix": "c013935b48f48ca8ce249a4d482c55e3fb6f1cfe786c5a32a57969bb74a779d9", + "size_in_bytes": 291 + }, + { + "_path": "include/python3.12/patchlevel.h", + "path_type": "hardlink", + "sha256": "f2f4800f05108bef77f6164484aba437b86b81e34744cbb5378f7bb2ccc69414", + "sha256_in_prefix": "f2f4800f05108bef77f6164484aba437b86b81e34744cbb5378f7bb2ccc69414", + "size_in_bytes": 1299 + }, + { + "_path": "include/python3.12/py_curses.h", + "path_type": "hardlink", + "sha256": "1aa826cacb9f07611155906d711403a7675ce573d61c888786178bb574dc3087", + "sha256_in_prefix": "1aa826cacb9f07611155906d711403a7675ce573d61c888786178bb574dc3087", + "size_in_bytes": 2473 + }, + { + "_path": "include/python3.12/pybuffer.h", + "path_type": "hardlink", + "sha256": "c95edd830772e922f60f976ac0d98470b48a443ba198b0866a4096003c0740a4", + "sha256_in_prefix": "c95edd830772e922f60f976ac0d98470b48a443ba198b0866a4096003c0740a4", + "size_in_bytes": 5282 + }, + { + "_path": "include/python3.12/pycapsule.h", + "path_type": "hardlink", + "sha256": "6929a47483ea5bb1a7b9b490a876b21beefed11061c94b2963b2608b7f542728", + "sha256_in_prefix": "6929a47483ea5bb1a7b9b490a876b21beefed11061c94b2963b2608b7f542728", + "size_in_bytes": 1727 + }, + { + "_path": "include/python3.12/pyconfig.h", + "path_type": "hardlink", + "sha256": "cb3c5c8cb364d63ee8316929fc3841ed963d69838f29b096b45dc423cda1b1d4", + "sha256_in_prefix": "cb3c5c8cb364d63ee8316929fc3841ed963d69838f29b096b45dc423cda1b1d4", + "size_in_bytes": 55945 + }, + { + "_path": "include/python3.12/pydtrace.h", + "path_type": "hardlink", + "sha256": "7ac591e56e12936a32e3b0b85dae803f8f00bdc91abe01799ca2e4ce69548555", + "sha256_in_prefix": "7ac591e56e12936a32e3b0b85dae803f8f00bdc91abe01799ca2e4ce69548555", + "size_in_bytes": 2404 + }, + { + "_path": "include/python3.12/pyerrors.h", + "path_type": "hardlink", + "sha256": "59bf06c7ba877ec76d09a41aac75e385a2723545388b105864f48f295e2524e0", + "sha256_in_prefix": "59bf06c7ba877ec76d09a41aac75e385a2723545388b105864f48f295e2524e0", + "size_in_bytes": 13017 + }, + { + "_path": "include/python3.12/pyexpat.h", + "path_type": "hardlink", + "sha256": "24eb6f486b4eec69bcd84ec6cc17833040095aabba7a0c4ebe491bb5de02879e", + "sha256_in_prefix": "24eb6f486b4eec69bcd84ec6cc17833040095aabba7a0c4ebe491bb5de02879e", + "size_in_bytes": 2572 + }, + { + "_path": "include/python3.12/pyframe.h", + "path_type": "hardlink", + "sha256": "58513e7017805ee5c49a329a552f72a6be6d88ce2bcfa344f5130582fa75ecb6", + "sha256_in_prefix": "58513e7017805ee5c49a329a552f72a6be6d88ce2bcfa344f5130582fa75ecb6", + "size_in_bytes": 551 + }, + { + "_path": "include/python3.12/pyhash.h", + "path_type": "hardlink", + "sha256": "a6ea755ff42ec955feaf49b1d234a5c2935899309ea59925d1d30f3e62fed67d", + "sha256_in_prefix": "a6ea755ff42ec955feaf49b1d234a5c2935899309ea59925d1d30f3e62fed67d", + "size_in_bytes": 4154 + }, + { + "_path": "include/python3.12/pylifecycle.h", + "path_type": "hardlink", + "sha256": "d313c5f3fe805606061ea78982ca5d5a9f09e687210c8b0fbcb50db596106691", + "sha256_in_prefix": "d313c5f3fe805606061ea78982ca5d5a9f09e687210c8b0fbcb50db596106691", + "size_in_bytes": 2249 + }, + { + "_path": "include/python3.12/pymacconfig.h", + "path_type": "hardlink", + "sha256": "5dcd4fa505975be42c35a4707ab7cb5b6ddf2e896bb8fbb8c1fd9047e5183a3d", + "sha256_in_prefix": "5dcd4fa505975be42c35a4707ab7cb5b6ddf2e896bb8fbb8c1fd9047e5183a3d", + "size_in_bytes": 2810 + }, + { + "_path": "include/python3.12/pymacro.h", + "path_type": "hardlink", + "sha256": "30af4b1a8deb972e716f24d32985b79deadb7f638d0b576a46214962ac4055fa", + "sha256_in_prefix": "30af4b1a8deb972e716f24d32985b79deadb7f638d0b576a46214962ac4055fa", + "size_in_bytes": 6318 + }, + { + "_path": "include/python3.12/pymath.h", + "path_type": "hardlink", + "sha256": "eeea8396e1acd271ba83a568ba572ead47493e492ce998756fe1256bf917b3f9", + "sha256_in_prefix": "eeea8396e1acd271ba83a568ba572ead47493e492ce998756fe1256bf917b3f9", + "size_in_bytes": 1688 + }, + { + "_path": "include/python3.12/pymem.h", + "path_type": "hardlink", + "sha256": "54a5315d7861e989c5099f168d946f5a421337efcd5d44896201016e92a81348", + "sha256_in_prefix": "54a5315d7861e989c5099f168d946f5a421337efcd5d44896201016e92a81348", + "size_in_bytes": 3914 + }, + { + "_path": "include/python3.12/pyport.h", + "path_type": "hardlink", + "sha256": "fb25010bf4b52df6157e29bb4c0bbdc4797b417df0346c7258294f501667ec5e", + "sha256_in_prefix": "fb25010bf4b52df6157e29bb4c0bbdc4797b417df0346c7258294f501667ec5e", + "size_in_bytes": 25516 + }, + { + "_path": "include/python3.12/pystate.h", + "path_type": "hardlink", + "sha256": "065426aaa5fada90d61a17757fbc2e8ce3fb9cc203992990c4ca3cee7f9f80be", + "sha256_in_prefix": "065426aaa5fada90d61a17757fbc2e8ce3fb9cc203992990c4ca3cee7f9f80be", + "size_in_bytes": 4635 + }, + { + "_path": "include/python3.12/pystats.h", + "path_type": "hardlink", + "sha256": "b93db83e29f09ff06b15bf39a21e53de82858ba92cbf48332d1ada1ac028d6f8", + "sha256_in_prefix": "b93db83e29f09ff06b15bf39a21e53de82858ba92cbf48332d1ada1ac028d6f8", + "size_in_bytes": 2741 + }, + { + "_path": "include/python3.12/pystrcmp.h", + "path_type": "hardlink", + "sha256": "f401d8338fb6ecf5f12768ee95cd09c262f880b2ee522ca344b890dbdcde4c88", + "sha256_in_prefix": "f401d8338fb6ecf5f12768ee95cd09c262f880b2ee522ca344b890dbdcde4c88", + "size_in_bytes": 436 + }, + { + "_path": "include/python3.12/pystrtod.h", + "path_type": "hardlink", + "sha256": "8c8e9d1d279216f1c08f0aedac5de49a9b8852a3f838f21e298300e969474ef4", + "sha256_in_prefix": "8c8e9d1d279216f1c08f0aedac5de49a9b8852a3f838f21e298300e969474ef4", + "size_in_bytes": 1557 + }, + { + "_path": "include/python3.12/pythonrun.h", + "path_type": "hardlink", + "sha256": "4749ef95e910632a1d04b912c4f1d615c9d10567cbaf52a2ab2c68c7c3a38d94", + "sha256_in_prefix": "4749ef95e910632a1d04b912c4f1d615c9d10567cbaf52a2ab2c68c7c3a38d94", + "size_in_bytes": 1313 + }, + { + "_path": "include/python3.12/pythread.h", + "path_type": "hardlink", + "sha256": "cd063073710988ea21b54588473542e5f3b2be06f637dc5a028aefd5a7949144", + "sha256_in_prefix": "cd063073710988ea21b54588473542e5f3b2be06f637dc5a028aefd5a7949144", + "size_in_bytes": 4875 + }, + { + "_path": "include/python3.12/pytypedefs.h", + "path_type": "hardlink", + "sha256": "26d09a78c44998e8c0a74ed2d14e5346e4b922892eb79288049b7ac5b6a1e751", + "sha256_in_prefix": "26d09a78c44998e8c0a74ed2d14e5346e4b922892eb79288049b7ac5b6a1e751", + "size_in_bytes": 851 + }, + { + "_path": "include/python3.12/rangeobject.h", + "path_type": "hardlink", + "sha256": "36547ab5862e82b09cbed7b786a4cfc86af1dec5a3778c50825bb266c9a6aec9", + "sha256_in_prefix": "36547ab5862e82b09cbed7b786a4cfc86af1dec5a3778c50825bb266c9a6aec9", + "size_in_bytes": 630 + }, + { + "_path": "include/python3.12/setobject.h", + "path_type": "hardlink", + "sha256": "7ff1b984647598b19ff593b0fa40d44cf5d7bc37d386dd9fac059e560f4a31ca", + "sha256_in_prefix": "7ff1b984647598b19ff593b0fa40d44cf5d7bc37d386dd9fac059e560f4a31ca", + "size_in_bytes": 1557 + }, + { + "_path": "include/python3.12/sliceobject.h", + "path_type": "hardlink", + "sha256": "527719b92e4fa9d5b371c30bc87bc0304ec20099b18c446ad1aa49fd61e5e387", + "sha256_in_prefix": "527719b92e4fa9d5b371c30bc87bc0304ec20099b18c446ad1aa49fd61e5e387", + "size_in_bytes": 2518 + }, + { + "_path": "include/python3.12/structmember.h", + "path_type": "hardlink", + "sha256": "9d4c39dee96e228f60cc8a6960b9e7049875ddbee15541a75629c07777916342", + "sha256_in_prefix": "9d4c39dee96e228f60cc8a6960b9e7049875ddbee15541a75629c07777916342", + "size_in_bytes": 1645 + }, + { + "_path": "include/python3.12/structseq.h", + "path_type": "hardlink", + "sha256": "067f8663a922eb142a3fd12ff18eaa756553bef8a68eaa863f80419dbb8d1ffe", + "sha256_in_prefix": "067f8663a922eb142a3fd12ff18eaa756553bef8a68eaa863f80419dbb8d1ffe", + "size_in_bytes": 1398 + }, + { + "_path": "include/python3.12/sysmodule.h", + "path_type": "hardlink", + "sha256": "09b6f415d4054fee4eb8375a94a724e102bc9a40633d16a437960671b1a9a1b4", + "sha256_in_prefix": "09b6f415d4054fee4eb8375a94a724e102bc9a40633d16a437960671b1a9a1b4", + "size_in_bytes": 1729 + }, + { + "_path": "include/python3.12/traceback.h", + "path_type": "hardlink", + "sha256": "ea59d511687f7f8643c7b8b0996e26f2c92bcc954639c6f98d08f6564b61d06d", + "sha256_in_prefix": "ea59d511687f7f8643c7b8b0996e26f2c92bcc954639c6f98d08f6564b61d06d", + "size_in_bytes": 585 + }, + { + "_path": "include/python3.12/tracemalloc.h", + "path_type": "hardlink", + "sha256": "296084c2140af69ee39e672feab2027411c7b0397a5719aa513802cd6a849d93", + "sha256_in_prefix": "296084c2140af69ee39e672feab2027411c7b0397a5719aa513802cd6a849d93", + "size_in_bytes": 2192 + }, + { + "_path": "include/python3.12/tupleobject.h", + "path_type": "hardlink", + "sha256": "d8de8d64e4b5c466c3bdd04f5664f0eba64a9198b30b5a29409d74a5b5f1def7", + "sha256_in_prefix": "d8de8d64e4b5c466c3bdd04f5664f0eba64a9198b30b5a29409d74a5b5f1def7", + "size_in_bytes": 1615 + }, + { + "_path": "include/python3.12/typeslots.h", + "path_type": "hardlink", + "sha256": "77fe4a71f5e5974c40fd3485d3c9aeb8b7ccf33969cd26feb58c64eda5f86f1d", + "sha256_in_prefix": "77fe4a71f5e5974c40fd3485d3c9aeb8b7ccf33969cd26feb58c64eda5f86f1d", + "size_in_bytes": 2342 + }, + { + "_path": "include/python3.12/unicodeobject.h", + "path_type": "hardlink", + "sha256": "5cc1350da2b00f5187065004a1f5d66764e86a0f20f8faba7d0eadf913297d93", + "sha256_in_prefix": "5cc1350da2b00f5187065004a1f5d66764e86a0f20f8faba7d0eadf913297d93", + "size_in_bytes": 35164 + }, + { + "_path": "include/python3.12/warnings.h", + "path_type": "hardlink", + "sha256": "18fde34b12247460de805fc259ea7f14305fce4779d244c0a7bdc7c73b8f6b51", + "sha256_in_prefix": "18fde34b12247460de805fc259ea7f14305fce4779d244c0a7bdc7c73b8f6b51", + "size_in_bytes": 1129 + }, + { + "_path": "include/python3.12/weakrefobject.h", + "path_type": "hardlink", + "sha256": "031b4bc091cf442b4305f7c5ac9713f32101a5e40617f3cb56c632cb7b15fb5b", + "sha256_in_prefix": "031b4bc091cf442b4305f7c5ac9713f32101a5e40617f3cb56c632cb7b15fb5b", + "size_in_bytes": 1234 + }, + { + "_path": "lib/libpython3.12.so", + "path_type": "softlink", + "sha256": "17226a07141d57dbb008a6c96416322c8a7ae6b14be3ccac4577f7e6a55692b5", + "sha256_in_prefix": "a8de2cd4edf05bda5211291475225effde8ac84713e99b8954ea0a482403c7d6", + "size_in_bytes": 31370144 + }, + { + "_path": "lib/libpython3.12.so.1.0", + "path_type": "hardlink", + "sha256": "17226a07141d57dbb008a6c96416322c8a7ae6b14be3ccac4577f7e6a55692b5", + "sha256_in_prefix": "b4cf498ca7e77b4b82803bc14b841c9a7ca581e81287706aaa9506f44e0df29f", + "size_in_bytes": 31370144, + "file_mode": "binary", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/libpython3.so", + "path_type": "hardlink", + "sha256": "b43d5339fff593903cfbf0e2d7a027886f51c33c11e7912cf3dd5f6903727211", + "sha256_in_prefix": "b43d5339fff593903cfbf0e2d7a027886f51c33c11e7912cf3dd5f6903727211", + "size_in_bytes": 15032 + }, + { + "_path": "lib/pkgconfig/python-3.12-embed.pc", + "path_type": "hardlink", + "sha256": "2c9504fdef92ddb77b51f3ac31caebeac8c6751f687b19713bd49fee4293b008", + "sha256_in_prefix": "da731b861a76c9712aba62df23b755882cadc33d839632a2221002aa9f140466", + "size_in_bytes": 333, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/pkgconfig/python-3.12.pc", + "path_type": "hardlink", + "sha256": "21eb84c76720c3e06bd48f705d54f44f4ac3fa93afa36fcbdbc860a8637d0a81", + "sha256_in_prefix": "b455849627eca566b4a0ead48eed99b4d93e5f2037eb6757b718073adaba84a8", + "size_in_bytes": 319, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/pkgconfig/python3-embed.pc", + "path_type": "softlink", + "sha256": "2c9504fdef92ddb77b51f3ac31caebeac8c6751f687b19713bd49fee4293b008", + "sha256_in_prefix": "2b4ebfe7e669b293dd11c9a7fac4af89923fa6768b66e815f14c442f182b2a5f", + "size_in_bytes": 549 + }, + { + "_path": "lib/pkgconfig/python3.pc", + "path_type": "softlink", + "sha256": "21eb84c76720c3e06bd48f705d54f44f4ac3fa93afa36fcbdbc860a8637d0a81", + "sha256_in_prefix": "fe4bbff5948584c7d40ccd6f5a0c9b2032aa0937fe1631e8589fd7df16d1292f", + "size_in_bytes": 535 + }, + { + "_path": "lib/python3.1", + "path_type": "softlink", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "sha256_in_prefix": "42f2b28d8258c41a63374ac4365007738900f66a9b62a7eb1a2041a2e091d41b", + "size_in_bytes": 0 + }, + { + "_path": "lib/python3.12/LICENSE.txt", + "path_type": "hardlink", + "sha256": "3b2f81fe21d181c499c59a256c8e1968455d6689d269aa85373bfb6af41da3bf", + "sha256_in_prefix": "3b2f81fe21d181c499c59a256c8e1968455d6689d269aa85373bfb6af41da3bf", + "size_in_bytes": 13936 + }, + { + "_path": "lib/python3.12/__future__.py", + "path_type": "hardlink", + "sha256": "981d4c398849f9ebcab72300d9c1fe288fd6d7f28957b3b3fa3a493a5836d95c", + "sha256_in_prefix": "981d4c398849f9ebcab72300d9c1fe288fd6d7f28957b3b3fa3a493a5836d95c", + "size_in_bytes": 5218 + }, + { + "_path": "lib/python3.12/__hello__.py", + "path_type": "hardlink", + "sha256": "a8ce70b199497950f0f06def93115a6814daf1f961934457f59046909901487f", + "sha256_in_prefix": "a8ce70b199497950f0f06def93115a6814daf1f961934457f59046909901487f", + "size_in_bytes": 227 + }, + { + "_path": "lib/python3.12/__phello__/__init__.py", + "path_type": "hardlink", + "sha256": "56f7ed595e767c558ded05def14b682893105daf504500c3443b458ca2431bc6", + "sha256_in_prefix": "56f7ed595e767c558ded05def14b682893105daf504500c3443b458ca2431bc6", + "size_in_bytes": 97 + }, + { + "_path": "lib/python3.12/__phello__/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "91bbcbfdea1a66935a6a20e02033733ef77dfd991faa3a4c91751e66d988b07f", + "sha256_in_prefix": "91bbcbfdea1a66935a6a20e02033733ef77dfd991faa3a4c91751e66d988b07f", + "size_in_bytes": 364 + }, + { + "_path": "lib/python3.12/__phello__/__pycache__/spam.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8d1f8b80f2277df1211013b4da448acb2f5967a45061bd49ab2ed45ae22e7f4a", + "sha256_in_prefix": "8d1f8b80f2277df1211013b4da448acb2f5967a45061bd49ab2ed45ae22e7f4a", + "size_in_bytes": 360 + }, + { + "_path": "lib/python3.12/__phello__/spam.py", + "path_type": "hardlink", + "sha256": "56f7ed595e767c558ded05def14b682893105daf504500c3443b458ca2431bc6", + "sha256_in_prefix": "56f7ed595e767c558ded05def14b682893105daf504500c3443b458ca2431bc6", + "size_in_bytes": 97 + }, + { + "_path": "lib/python3.12/__pycache__/__future__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d1a6d464e71d8ff37267a37624e90ae5abcb1ecef515946f1f02e8c2040497f6", + "sha256_in_prefix": "d1a6d464e71d8ff37267a37624e90ae5abcb1ecef515946f1f02e8c2040497f6", + "size_in_bytes": 4699 + }, + { + "_path": "lib/python3.12/__pycache__/__hello__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "744ef593055c74f0f4597c9f4e2566bfc261a8c3681172bc02403b575b6ae1c0", + "sha256_in_prefix": "744ef593055c74f0f4597c9f4e2566bfc261a8c3681172bc02403b575b6ae1c0", + "size_in_bytes": 865 + }, + { + "_path": "lib/python3.12/__pycache__/_aix_support.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "339925a5131c7118ca40ea195bd458c1cf6ea080f72e7d475d383ab1b3c7ee5e", + "sha256_in_prefix": "339925a5131c7118ca40ea195bd458c1cf6ea080f72e7d475d383ab1b3c7ee5e", + "size_in_bytes": 4754 + }, + { + "_path": "lib/python3.12/__pycache__/_collections_abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3de71afb6cc36d5bbea509a260a360b2ba64017191ccce95176416d8f98c37e3", + "sha256_in_prefix": "3de71afb6cc36d5bbea509a260a360b2ba64017191ccce95176416d8f98c37e3", + "size_in_bytes": 45907 + }, + { + "_path": "lib/python3.12/__pycache__/_compat_pickle.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "dc07704024d2dff84279c51fe34600f6894634bfc82b1e05ee7ca229f37f74a7", + "sha256_in_prefix": "dc07704024d2dff84279c51fe34600f6894634bfc82b1e05ee7ca229f37f74a7", + "size_in_bytes": 7216 + }, + { + "_path": "lib/python3.12/__pycache__/_compression.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "89570216a6c4e7ad28e42aab0095eeb489b38a3a5e33d33ca34085ab59456932", + "sha256_in_prefix": "89570216a6c4e7ad28e42aab0095eeb489b38a3a5e33d33ca34085ab59456932", + "size_in_bytes": 7492 + }, + { + "_path": "lib/python3.12/__pycache__/_markupbase.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b3e15678f2c4d3c966ad655b24aef5ba309a0048f5fc3c0324fd596a47e21ebd", + "sha256_in_prefix": "b3e15678f2c4d3c966ad655b24aef5ba309a0048f5fc3c0324fd596a47e21ebd", + "size_in_bytes": 12274 + }, + { + "_path": "lib/python3.12/__pycache__/_osx_support.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5fa983965cdb008e2a1b5c9efa857d488b0aa32ea946e2d589ca80133bbc1d0b", + "sha256_in_prefix": "5fa983965cdb008e2a1b5c9efa857d488b0aa32ea946e2d589ca80133bbc1d0b", + "size_in_bytes": 17726 + }, + { + "_path": "lib/python3.12/__pycache__/_py_abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1d36179a60f82e38683421e2c1232b5c0fae392583c27db63c26494887c6a4e8", + "sha256_in_prefix": "1d36179a60f82e38683421e2c1232b5c0fae392583c27db63c26494887c6a4e8", + "size_in_bytes": 7049 + }, + { + "_path": "lib/python3.12/__pycache__/_pydatetime.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "eaa3307cbdddf4e4a2c75dec17560ef2f33b407431ebe225b234f6341030cda5", + "sha256_in_prefix": "eaa3307cbdddf4e4a2c75dec17560ef2f33b407431ebe225b234f6341030cda5", + "size_in_bytes": 94188 + }, + { + "_path": "lib/python3.12/__pycache__/_pydecimal.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8c1e94ef45ef23f04d17fe41d85776f7e63d4f8d6cb7edf97bf4cd91887f0297", + "sha256_in_prefix": "8c1e94ef45ef23f04d17fe41d85776f7e63d4f8d6cb7edf97bf4cd91887f0297", + "size_in_bytes": 227802 + }, + { + "_path": "lib/python3.12/__pycache__/_pyio.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da8372192841ea7d0efbd246d8dae8c8cde56229cf71a53ff1e8f679cfbcf0f2", + "sha256_in_prefix": "da8372192841ea7d0efbd246d8dae8c8cde56229cf71a53ff1e8f679cfbcf0f2", + "size_in_bytes": 110264 + }, + { + "_path": "lib/python3.12/__pycache__/_pylong.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c74b9e02831d8eca6c1f07c1258393cd105498ca385bf5d57a8751ff5ba97ca1", + "sha256_in_prefix": "c74b9e02831d8eca6c1f07c1258393cd105498ca385bf5d57a8751ff5ba97ca1", + "size_in_bytes": 9978 + }, + { + "_path": "lib/python3.12/__pycache__/_sitebuiltins.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "494abb1ba87e9ab10dea2826beb6d0efaff53c68101f50818aa5663ba62d9d55", + "sha256_in_prefix": "494abb1ba87e9ab10dea2826beb6d0efaff53c68101f50818aa5663ba62d9d55", + "size_in_bytes": 4755 + }, + { + "_path": "lib/python3.12/__pycache__/_strptime.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "699ddb7350e6c3e21c297f2fc41249d7ca59d13533a47c5c8cf76ff423660969", + "sha256_in_prefix": "699ddb7350e6c3e21c297f2fc41249d7ca59d13533a47c5c8cf76ff423660969", + "size_in_bytes": 24111 + }, + { + "_path": "lib/python3.12/__pycache__/_sysconfigdata__linux_x86_64-linux-gnu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "14c1815a81447cf747169bf1db0cafb2a2207a1215ba2c28139b45e20f0b2445", + "sha256_in_prefix": "14c1815a81447cf747169bf1db0cafb2a2207a1215ba2c28139b45e20f0b2445", + "size_in_bytes": 106116 + }, + { + "_path": "lib/python3.12/__pycache__/_sysconfigdata_x86_64_conda_cos6_linux_gnu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f7694e6a78ae1e2814e9db741fb89d181b5295422140d72e8c6fe5d8ebc7afa7", + "sha256_in_prefix": "f7694e6a78ae1e2814e9db741fb89d181b5295422140d72e8c6fe5d8ebc7afa7", + "size_in_bytes": 108259 + }, + { + "_path": "lib/python3.12/__pycache__/_sysconfigdata_x86_64_conda_linux_gnu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "62517415af5376d9d5e09fd95e59ad68af8ddfd6380a762337f114876e58b25f", + "sha256_in_prefix": "62517415af5376d9d5e09fd95e59ad68af8ddfd6380a762337f114876e58b25f", + "size_in_bytes": 108189 + }, + { + "_path": "lib/python3.12/__pycache__/_threading_local.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3b1fabe23db5356237abd1b977f113dc943c5c994d4189c6644a0c8953cddc34", + "sha256_in_prefix": "3b1fabe23db5356237abd1b977f113dc943c5c994d4189c6644a0c8953cddc34", + "size_in_bytes": 8290 + }, + { + "_path": "lib/python3.12/__pycache__/_weakrefset.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "27b95e8d2b395df3d24c6a0c5ea9766d64a17aa3ae86fa35b364538f0fc9a465", + "sha256_in_prefix": "27b95e8d2b395df3d24c6a0c5ea9766d64a17aa3ae86fa35b364538f0fc9a465", + "size_in_bytes": 11746 + }, + { + "_path": "lib/python3.12/__pycache__/abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e4dbb885961903f6b228f555d62d5ba6cb44b7edb3edd801a4f1fcecfda490c3", + "sha256_in_prefix": "e4dbb885961903f6b228f555d62d5ba6cb44b7edb3edd801a4f1fcecfda490c3", + "size_in_bytes": 8050 + }, + { + "_path": "lib/python3.12/__pycache__/aifc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7ed9e7d5800cad15429ae564914f8101e65e4a69c004d763f948e473a3bb1324", + "sha256_in_prefix": "7ed9e7d5800cad15429ae564914f8101e65e4a69c004d763f948e473a3bb1324", + "size_in_bytes": 42858 + }, + { + "_path": "lib/python3.12/__pycache__/antigravity.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b3d6de0eaae0d0546179a0038b717f5e28ededba24feb1824eeca8df96b361e5", + "sha256_in_prefix": "b3d6de0eaae0d0546179a0038b717f5e28ededba24feb1824eeca8df96b361e5", + "size_in_bytes": 998 + }, + { + "_path": "lib/python3.12/__pycache__/argparse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "64cf2108f2bf70feede23976db32c86bd24688f1d42550b18d89624d70cca658", + "sha256_in_prefix": "64cf2108f2bf70feede23976db32c86bd24688f1d42550b18d89624d70cca658", + "size_in_bytes": 101251 + }, + { + "_path": "lib/python3.12/__pycache__/ast.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9456ab5eb83c1d9fae2147083e9bd0142db1f5906223797c90b78d53601c5d33", + "sha256_in_prefix": "9456ab5eb83c1d9fae2147083e9bd0142db1f5906223797c90b78d53601c5d33", + "size_in_bytes": 100274 + }, + { + "_path": "lib/python3.12/__pycache__/base64.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "801a45e6a6a5f9cc2390414c38fb52ec985de49ef9880f737213b39eabae0217", + "sha256_in_prefix": "801a45e6a6a5f9cc2390414c38fb52ec985de49ef9880f737213b39eabae0217", + "size_in_bytes": 24403 + }, + { + "_path": "lib/python3.12/__pycache__/bdb.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "91f6b2851cb0abaa553fbf36c8e871e1dbb18c4005e3213dcce9b31c24562efd", + "sha256_in_prefix": "91f6b2851cb0abaa553fbf36c8e871e1dbb18c4005e3213dcce9b31c24562efd", + "size_in_bytes": 37354 + }, + { + "_path": "lib/python3.12/__pycache__/bisect.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b3772a867e9b6080e48bf49f34dac5246f89e985f02fd465af1bbb5c80dcde5d", + "sha256_in_prefix": "b3772a867e9b6080e48bf49f34dac5246f89e985f02fd465af1bbb5c80dcde5d", + "size_in_bytes": 3636 + }, + { + "_path": "lib/python3.12/__pycache__/bz2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "42236554515e66cdcb85031c43f6a5e0e104eca07f9d03e0d8164ab82724f3ec", + "sha256_in_prefix": "42236554515e66cdcb85031c43f6a5e0e104eca07f9d03e0d8164ab82724f3ec", + "size_in_bytes": 15128 + }, + { + "_path": "lib/python3.12/__pycache__/cProfile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c3f7424ed3fcd72050a9292c3de6df1a634397cce68768fbc0acf46b19bddd42", + "sha256_in_prefix": "c3f7424ed3fcd72050a9292c3de6df1a634397cce68768fbc0acf46b19bddd42", + "size_in_bytes": 8588 + }, + { + "_path": "lib/python3.12/__pycache__/calendar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "728bd605dad802d7aa886ad5f5244e74f0afb13dd1a95ce567c2a4848106c724", + "sha256_in_prefix": "728bd605dad802d7aa886ad5f5244e74f0afb13dd1a95ce567c2a4848106c724", + "size_in_bytes": 39616 + }, + { + "_path": "lib/python3.12/__pycache__/cgi.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d5c648f2601f5f92f6b952dc6bea4686dea66922402b74d1309d31fb8f6ee0f9", + "sha256_in_prefix": "d5c648f2601f5f92f6b952dc6bea4686dea66922402b74d1309d31fb8f6ee0f9", + "size_in_bytes": 40223 + }, + { + "_path": "lib/python3.12/__pycache__/cgitb.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c0024dce178ec9e1c8ff6f5a60bd665e4cbf9012addb8e646b4392b378dd718c", + "sha256_in_prefix": "c0024dce178ec9e1c8ff6f5a60bd665e4cbf9012addb8e646b4392b378dd718c", + "size_in_bytes": 17327 + }, + { + "_path": "lib/python3.12/__pycache__/chunk.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7c425bf6f66289fb7a4f0dd0b8cdb727e14c3656c135dde753bbebcd1c180335", + "sha256_in_prefix": "7c425bf6f66289fb7a4f0dd0b8cdb727e14c3656c135dde753bbebcd1c180335", + "size_in_bytes": 7305 + }, + { + "_path": "lib/python3.12/__pycache__/cmd.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c3fde725bedf9879c15f2aef30ff7bacd42219f59b5d5c4aad3b53678ebdacc0", + "sha256_in_prefix": "c3fde725bedf9879c15f2aef30ff7bacd42219f59b5d5c4aad3b53678ebdacc0", + "size_in_bytes": 18614 + }, + { + "_path": "lib/python3.12/__pycache__/code.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f7d1965812dcf9a8f92361cec79e481b8a3c64ee56422103a62d708a61532260", + "sha256_in_prefix": "f7d1965812dcf9a8f92361cec79e481b8a3c64ee56422103a62d708a61532260", + "size_in_bytes": 13046 + }, + { + "_path": "lib/python3.12/__pycache__/codecs.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8be776602c9bd03e348ef585ce416a746694105031969bcfb96841c76339cd96", + "sha256_in_prefix": "8be776602c9bd03e348ef585ce416a746694105031969bcfb96841c76339cd96", + "size_in_bytes": 42269 + }, + { + "_path": "lib/python3.12/__pycache__/codeop.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4c5d24cbba0ce5c9b9d46f69b12eb17342f307e39594353988379583ce6def92", + "sha256_in_prefix": "4c5d24cbba0ce5c9b9d46f69b12eb17342f307e39594353988379583ce6def92", + "size_in_bytes": 6911 + }, + { + "_path": "lib/python3.12/__pycache__/colorsys.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "00e3e04dfc83414813e6adabf55e43ab250e9f8f46a211474d0de74711c5e133", + "sha256_in_prefix": "00e3e04dfc83414813e6adabf55e43ab250e9f8f46a211474d0de74711c5e133", + "size_in_bytes": 4637 + }, + { + "_path": "lib/python3.12/__pycache__/compileall.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "453500374a77478702cd530b8e54c7cc7fe5707855ebd5eba64b34dad0f8238c", + "sha256_in_prefix": "453500374a77478702cd530b8e54c7cc7fe5707855ebd5eba64b34dad0f8238c", + "size_in_bytes": 20397 + }, + { + "_path": "lib/python3.12/__pycache__/configparser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bf8f8ce077c1f0b78672083776afb702eac78a4cfd839f889c62b39a54eb96b8", + "sha256_in_prefix": "bf8f8ce077c1f0b78672083776afb702eac78a4cfd839f889c62b39a54eb96b8", + "size_in_bytes": 63577 + }, + { + "_path": "lib/python3.12/__pycache__/contextlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "902decd59a51d725b1382fc02e5f2a00ead02466e975fd42a6ec2163bc40c6e2", + "sha256_in_prefix": "902decd59a51d725b1382fc02e5f2a00ead02466e975fd42a6ec2163bc40c6e2", + "size_in_bytes": 30371 + }, + { + "_path": "lib/python3.12/__pycache__/contextvars.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0afd2c206a28c394332adb705a669142bb44ab6c17f2c4170fd13e997b5e164a", + "sha256_in_prefix": "0afd2c206a28c394332adb705a669142bb44ab6c17f2c4170fd13e997b5e164a", + "size_in_bytes": 256 + }, + { + "_path": "lib/python3.12/__pycache__/copy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a768a924d280429dc8432df82421dc93c8fa1dbe0b643e51f44ac30f80e8dd0c", + "sha256_in_prefix": "a768a924d280429dc8432df82421dc93c8fa1dbe0b643e51f44ac30f80e8dd0c", + "size_in_bytes": 9795 + }, + { + "_path": "lib/python3.12/__pycache__/copyreg.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "74ec13c66d1c8d3ab952d400d33b99df881ceef462398ce5ab390b26034e3cd7", + "sha256_in_prefix": "74ec13c66d1c8d3ab952d400d33b99df881ceef462398ce5ab390b26034e3cd7", + "size_in_bytes": 7409 + }, + { + "_path": "lib/python3.12/__pycache__/crypt.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "949b738869528d69f2570dc3c1291b68093c3a1bf768f8fb865c7cc5d8648ca7", + "sha256_in_prefix": "949b738869528d69f2570dc3c1291b68093c3a1bf768f8fb865c7cc5d8648ca7", + "size_in_bytes": 5356 + }, + { + "_path": "lib/python3.12/__pycache__/csv.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1f9e88a41a338073917c3c9e64c193c3c74d3d66549077c0017a9dfd48fb291a", + "sha256_in_prefix": "1f9e88a41a338073917c3c9e64c193c3c74d3d66549077c0017a9dfd48fb291a", + "size_in_bytes": 17783 + }, + { + "_path": "lib/python3.12/__pycache__/dataclasses.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c7a4c60baae6c18db7182175b943d0a70f6a3d4ecff257e38236a8ca63236e05", + "sha256_in_prefix": "c7a4c60baae6c18db7182175b943d0a70f6a3d4ecff257e38236a8ca63236e05", + "size_in_bytes": 44673 + }, + { + "_path": "lib/python3.12/__pycache__/datetime.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c5ce05b54a37cb2540d851008cc2243655b9ffb7773ec0e9e5886e0563a66287", + "sha256_in_prefix": "c5ce05b54a37cb2540d851008cc2243655b9ffb7773ec0e9e5886e0563a66287", + "size_in_bytes": 404 + }, + { + "_path": "lib/python3.12/__pycache__/decimal.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5e4d5809647575f2829d7cffd351bf70ac7606a4ba35963a357843a444c4e5ef", + "sha256_in_prefix": "5e4d5809647575f2829d7cffd351bf70ac7606a4ba35963a357843a444c4e5ef", + "size_in_bytes": 401 + }, + { + "_path": "lib/python3.12/__pycache__/difflib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9da765a682328b4839edf42a6d2b18261d96e184816592ff94d626696ed91fc5", + "sha256_in_prefix": "9da765a682328b4839edf42a6d2b18261d96e184816592ff94d626696ed91fc5", + "size_in_bytes": 75494 + }, + { + "_path": "lib/python3.12/__pycache__/dis.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c83a7911978d2c374d49f64ac28bd9876bf0a3d62215caf6c09bbb510f6a5ebc", + "sha256_in_prefix": "c83a7911978d2c374d49f64ac28bd9876bf0a3d62215caf6c09bbb510f6a5ebc", + "size_in_bytes": 34555 + }, + { + "_path": "lib/python3.12/__pycache__/doctest.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "07dbb36c89b1d0b7d40f3df05b52f322ff2659094fcef49bf9e217ab4cdac027", + "sha256_in_prefix": "07dbb36c89b1d0b7d40f3df05b52f322ff2659094fcef49bf9e217ab4cdac027", + "size_in_bytes": 105681 + }, + { + "_path": "lib/python3.12/__pycache__/enum.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "26a2b55204dfb76d9de31330ad9e0b65579f7b4efd074df0fab21c8ca16b8216", + "sha256_in_prefix": "26a2b55204dfb76d9de31330ad9e0b65579f7b4efd074df0fab21c8ca16b8216", + "size_in_bytes": 80703 + }, + { + "_path": "lib/python3.12/__pycache__/filecmp.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "75ab611c0c52b474f98da91daf80d7f817eb5170d22abc50b16ce84a475b0494", + "sha256_in_prefix": "75ab611c0c52b474f98da91daf80d7f817eb5170d22abc50b16ce84a475b0494", + "size_in_bytes": 14656 + }, + { + "_path": "lib/python3.12/__pycache__/fileinput.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "422becd19e3ab067f6d501bf12d1de9f40f17e352abfe18cb451a16bcebeccfd", + "sha256_in_prefix": "422becd19e3ab067f6d501bf12d1de9f40f17e352abfe18cb451a16bcebeccfd", + "size_in_bytes": 20275 + }, + { + "_path": "lib/python3.12/__pycache__/fnmatch.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "45f1da1f736004d405cac6a997b2b48b38ec7d617e193ebcbc2fe40281e3b53d", + "sha256_in_prefix": "45f1da1f736004d405cac6a997b2b48b38ec7d617e193ebcbc2fe40281e3b53d", + "size_in_bytes": 6490 + }, + { + "_path": "lib/python3.12/__pycache__/fractions.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9df16a8c0c441b88f780dd657c9360b3cdd1459febc7c16586adf086147bdcaf", + "sha256_in_prefix": "9df16a8c0c441b88f780dd657c9360b3cdd1459febc7c16586adf086147bdcaf", + "size_in_bytes": 36662 + }, + { + "_path": "lib/python3.12/__pycache__/ftplib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bac8ff211f8fdd3e48d6588988c4d2d42476eecd1114683530cb20bc8b045866", + "sha256_in_prefix": "bac8ff211f8fdd3e48d6588988c4d2d42476eecd1114683530cb20bc8b045866", + "size_in_bytes": 42631 + }, + { + "_path": "lib/python3.12/__pycache__/functools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ffe07b2d6a1a2abac105c36f646410c0b81e719e68ee52755b4997455dce4e69", + "sha256_in_prefix": "ffe07b2d6a1a2abac105c36f646410c0b81e719e68ee52755b4997455dce4e69", + "size_in_bytes": 40501 + }, + { + "_path": "lib/python3.12/__pycache__/genericpath.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ae10fa19fd3215a076bbf9d58c4cb5c8a4126a323e750fde9e942aa4d20b33b9", + "sha256_in_prefix": "ae10fa19fd3215a076bbf9d58c4cb5c8a4126a323e750fde9e942aa4d20b33b9", + "size_in_bytes": 6188 + }, + { + "_path": "lib/python3.12/__pycache__/getopt.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3548b341ca3ee59b0b6664278574cc64b363fc112797adc13b2b6ed5a240f9ff", + "sha256_in_prefix": "3548b341ca3ee59b0b6664278574cc64b363fc112797adc13b2b6ed5a240f9ff", + "size_in_bytes": 8358 + }, + { + "_path": "lib/python3.12/__pycache__/getpass.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "083778f37d1be31a04290f466e914d2876a57d3c8cc6acecea56b4449b54dc21", + "sha256_in_prefix": "083778f37d1be31a04290f466e914d2876a57d3c8cc6acecea56b4449b54dc21", + "size_in_bytes": 6845 + }, + { + "_path": "lib/python3.12/__pycache__/gettext.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7df922fb857b6839282f0a9db097301d49ca526c2e3c95da91c7deca2a1d5a39", + "sha256_in_prefix": "7df922fb857b6839282f0a9db097301d49ca526c2e3c95da91c7deca2a1d5a39", + "size_in_bytes": 21847 + }, + { + "_path": "lib/python3.12/__pycache__/glob.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ea946a5d018f822216ae5dd30036f88ae524e328287262f520809dd5bb49d6c2", + "sha256_in_prefix": "ea946a5d018f822216ae5dd30036f88ae524e328287262f520809dd5bb49d6c2", + "size_in_bytes": 9836 + }, + { + "_path": "lib/python3.12/__pycache__/graphlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ab887160cc012cb39a0ad164012468a4e641153950b89dc09cb9d77e561b4916", + "sha256_in_prefix": "ab887160cc012cb39a0ad164012468a4e641153950b89dc09cb9d77e561b4916", + "size_in_bytes": 10322 + }, + { + "_path": "lib/python3.12/__pycache__/gzip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "94fa651f42fecaedb42b6010be35adfc06d2e12f00f88a9848700104b42414b8", + "sha256_in_prefix": "94fa651f42fecaedb42b6010be35adfc06d2e12f00f88a9848700104b42414b8", + "size_in_bytes": 32010 + }, + { + "_path": "lib/python3.12/__pycache__/hashlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7713e2833dbde90aa3ad0850c6def1c92a3ba2b2258e776cb1bb1e4f54c8dee3", + "sha256_in_prefix": "7713e2833dbde90aa3ad0850c6def1c92a3ba2b2258e776cb1bb1e4f54c8dee3", + "size_in_bytes": 8082 + }, + { + "_path": "lib/python3.12/__pycache__/heapq.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2d37aa7d6f388c468f4756a7a342e24e792bc21b4c3f1d0eb762a1e3cdae9e14", + "sha256_in_prefix": "2d37aa7d6f388c468f4756a7a342e24e792bc21b4c3f1d0eb762a1e3cdae9e14", + "size_in_bytes": 17951 + }, + { + "_path": "lib/python3.12/__pycache__/hmac.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "275ed9ac9a096b6755c63c8df5f1a95895baf0733a68085fa00409b24b43b1ca", + "sha256_in_prefix": "275ed9ac9a096b6755c63c8df5f1a95895baf0733a68085fa00409b24b43b1ca", + "size_in_bytes": 10693 + }, + { + "_path": "lib/python3.12/__pycache__/imaplib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cc8d4ac7959cb32a46543f395e042a04400e4c81831379ae9c1aeed9e32026d2", + "sha256_in_prefix": "cc8d4ac7959cb32a46543f395e042a04400e4c81831379ae9c1aeed9e32026d2", + "size_in_bytes": 62884 + }, + { + "_path": "lib/python3.12/__pycache__/imghdr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "06e6c131906e9dea4b9e3f0f00e1df23667afc97da61550a5a868c86807eb54b", + "sha256_in_prefix": "06e6c131906e9dea4b9e3f0f00e1df23667afc97da61550a5a868c86807eb54b", + "size_in_bytes": 6939 + }, + { + "_path": "lib/python3.12/__pycache__/inspect.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "548ce59edd8a6a7c04b30e269780ebe23d104633739f815bd70695c1d8ab2746", + "sha256_in_prefix": "548ce59edd8a6a7c04b30e269780ebe23d104633739f815bd70695c1d8ab2746", + "size_in_bytes": 133441 + }, + { + "_path": "lib/python3.12/__pycache__/io.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "677008af4d599eaf73fa69f0794301d9cec8db0e8a59a93078537f03e0f5c1ec", + "sha256_in_prefix": "677008af4d599eaf73fa69f0794301d9cec8db0e8a59a93078537f03e0f5c1ec", + "size_in_bytes": 4134 + }, + { + "_path": "lib/python3.12/__pycache__/ipaddress.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "16aa98fb175a84dcbfb9f738c50f8f452eb1f696c8fac8be68baed956bc57d19", + "sha256_in_prefix": "16aa98fb175a84dcbfb9f738c50f8f452eb1f696c8fac8be68baed956bc57d19", + "size_in_bytes": 88690 + }, + { + "_path": "lib/python3.12/__pycache__/keyword.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a540d0440d5d22692468bcc8a30dae8f837d2ca65f992207e12f0d188ecbf7a6", + "sha256_in_prefix": "a540d0440d5d22692468bcc8a30dae8f837d2ca65f992207e12f0d188ecbf7a6", + "size_in_bytes": 1036 + }, + { + "_path": "lib/python3.12/__pycache__/linecache.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f651523bc85ee913a66986dc12c41ca09dce2aecc5e4786e30d40572bef45413", + "sha256_in_prefix": "f651523bc85ee913a66986dc12c41ca09dce2aecc5e4786e30d40572bef45413", + "size_in_bytes": 6396 + }, + { + "_path": "lib/python3.12/__pycache__/locale.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "25697de742817e8480a6c56351d733d1873b0c43e0ddae5431182090cb97a754", + "sha256_in_prefix": "25697de742817e8480a6c56351d733d1873b0c43e0ddae5431182090cb97a754", + "size_in_bytes": 59542 + }, + { + "_path": "lib/python3.12/__pycache__/lzma.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "44c63df4ae4856cda1e55d5dbad7523c30060c4669e2b68ed58c3feea0adb72d", + "sha256_in_prefix": "44c63df4ae4856cda1e55d5dbad7523c30060c4669e2b68ed58c3feea0adb72d", + "size_in_bytes": 15850 + }, + { + "_path": "lib/python3.12/__pycache__/mailbox.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5ea5d76a85022e303b2d15913e9d078208fa20b8947b7787863e1ac8ced23d6a", + "sha256_in_prefix": "5ea5d76a85022e303b2d15913e9d078208fa20b8947b7787863e1ac8ced23d6a", + "size_in_bytes": 111613 + }, + { + "_path": "lib/python3.12/__pycache__/mailcap.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a692bd653da198cd791bf52fd68517fb50405c081333d376844b0c5cd298e752", + "sha256_in_prefix": "a692bd653da198cd791bf52fd68517fb50405c081333d376844b0c5cd298e752", + "size_in_bytes": 11150 + }, + { + "_path": "lib/python3.12/__pycache__/mimetypes.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7274c1cdc44431c2fab713e67589547ccf661175b4313caad9c0004e6c243832", + "sha256_in_prefix": "7274c1cdc44431c2fab713e67589547ccf661175b4313caad9c0004e6c243832", + "size_in_bytes": 24180 + }, + { + "_path": "lib/python3.12/__pycache__/modulefinder.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "63b9b12279645d678f1cb48dde4ecbb0a08b258e808d7fbb98371d2572cee982", + "sha256_in_prefix": "63b9b12279645d678f1cb48dde4ecbb0a08b258e808d7fbb98371d2572cee982", + "size_in_bytes": 27939 + }, + { + "_path": "lib/python3.12/__pycache__/netrc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1b10f35d131e13d57b03c61aaf015b6050c67e30861424d5bd087d29d3a50170", + "sha256_in_prefix": "1b10f35d131e13d57b03c61aaf015b6050c67e30861424d5bd087d29d3a50170", + "size_in_bytes": 8898 + }, + { + "_path": "lib/python3.12/__pycache__/nntplib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c032ea7233ed686254e72ff506e41d61de52f02e2d37feae9111a64ad504bb41", + "sha256_in_prefix": "c032ea7233ed686254e72ff506e41d61de52f02e2d37feae9111a64ad504bb41", + "size_in_bytes": 44934 + }, + { + "_path": "lib/python3.12/__pycache__/ntpath.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c724c475fca1af8f7ff780879cdf9ba3c6b12aad02ba000cc8205a828cdd8b49", + "sha256_in_prefix": "c724c475fca1af8f7ff780879cdf9ba3c6b12aad02ba000cc8205a828cdd8b49", + "size_in_bytes": 27089 + }, + { + "_path": "lib/python3.12/__pycache__/nturl2path.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0e629b3cdc68267cbf15c07f47d49023b08fbc96d7e47d499aefe405e3d809b5", + "sha256_in_prefix": "0e629b3cdc68267cbf15c07f47d49023b08fbc96d7e47d499aefe405e3d809b5", + "size_in_bytes": 3029 + }, + { + "_path": "lib/python3.12/__pycache__/numbers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cd3c9989d119cf65ddbfb895b058c12e15341748dedfc84dc1383e7547c90ca0", + "sha256_in_prefix": "cd3c9989d119cf65ddbfb895b058c12e15341748dedfc84dc1383e7547c90ca0", + "size_in_bytes": 13962 + }, + { + "_path": "lib/python3.12/__pycache__/opcode.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "69dc17a72550ec9cb059c8570bd668d39bf9c0cf8b4da0965537b062318c4423", + "sha256_in_prefix": "69dc17a72550ec9cb059c8570bd668d39bf9c0cf8b4da0965537b062318c4423", + "size_in_bytes": 14711 + }, + { + "_path": "lib/python3.12/__pycache__/operator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7f93910da00f4c91883ca8775fb8088a28cd5120231a7ab0d2796799a793d37c", + "sha256_in_prefix": "7f93910da00f4c91883ca8775fb8088a28cd5120231a7ab0d2796799a793d37c", + "size_in_bytes": 17359 + }, + { + "_path": "lib/python3.12/__pycache__/optparse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bdc26a64d69a96a5d81b4295764ab674c22d4546d2450cde483f24d2b6b7b373", + "sha256_in_prefix": "bdc26a64d69a96a5d81b4295764ab674c22d4546d2450cde483f24d2b6b7b373", + "size_in_bytes": 67541 + }, + { + "_path": "lib/python3.12/__pycache__/os.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c66dbc7f2b409ff3f7d17ff7c0850fd81e6e7d468adbfcf2f2e7b8b5f440cafb", + "sha256_in_prefix": "c66dbc7f2b409ff3f7d17ff7c0850fd81e6e7d468adbfcf2f2e7b8b5f440cafb", + "size_in_bytes": 43469 + }, + { + "_path": "lib/python3.12/__pycache__/pathlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ae95341cc8cc3c513f90fad322c321fec262a34a26f6daf0345ac224de10d323", + "sha256_in_prefix": "ae95341cc8cc3c513f90fad322c321fec262a34a26f6daf0345ac224de10d323", + "size_in_bytes": 62057 + }, + { + "_path": "lib/python3.12/__pycache__/pdb.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "01354ab699c386cf67fd2d482f1b6ae933b7c2db6078b647584c7378bb0b7bef", + "sha256_in_prefix": "01354ab699c386cf67fd2d482f1b6ae933b7c2db6078b647584c7378bb0b7bef", + "size_in_bytes": 84914 + }, + { + "_path": "lib/python3.12/__pycache__/pickle.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7ac10f4e53abd4811ae65e4418458e8163767e4b7a258960a8c021a2e988aaec", + "sha256_in_prefix": "7ac10f4e53abd4811ae65e4418458e8163767e4b7a258960a8c021a2e988aaec", + "size_in_bytes": 76171 + }, + { + "_path": "lib/python3.12/__pycache__/pickletools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8f6c24c55407e1267cf074e034727d084d4183437daa1b98fcb0a274f2553595", + "sha256_in_prefix": "8f6c24c55407e1267cf074e034727d084d4183437daa1b98fcb0a274f2553595", + "size_in_bytes": 81123 + }, + { + "_path": "lib/python3.12/__pycache__/pipes.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "de5201987cc38a318b25ba8207222b2ab6b801222d13b6c67a1f0ea6dbe8f98f", + "sha256_in_prefix": "de5201987cc38a318b25ba8207222b2ab6b801222d13b6c67a1f0ea6dbe8f98f", + "size_in_bytes": 10909 + }, + { + "_path": "lib/python3.12/__pycache__/pkgutil.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8e6dbca0de22f501983637c6d6c83943abbd66f1675c3677e39473beb1cac19a", + "sha256_in_prefix": "8e6dbca0de22f501983637c6d6c83943abbd66f1675c3677e39473beb1cac19a", + "size_in_bytes": 19954 + }, + { + "_path": "lib/python3.12/__pycache__/platform.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b46cd41f495b1211e1e19b4cfc7ccc41cb2832a8254d88bca508b7573844995a", + "sha256_in_prefix": "b46cd41f495b1211e1e19b4cfc7ccc41cb2832a8254d88bca508b7573844995a", + "size_in_bytes": 41849 + }, + { + "_path": "lib/python3.12/__pycache__/plistlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "39893e9b9bf5de4b128b8bdd020f2aafb99030d31835e9527343fc5c167bf566", + "sha256_in_prefix": "39893e9b9bf5de4b128b8bdd020f2aafb99030d31835e9527343fc5c167bf566", + "size_in_bytes": 41065 + }, + { + "_path": "lib/python3.12/__pycache__/poplib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "11f751c89fb81c66a4f67177d99bd052ed8a56872a46b25615a7c087416f24f1", + "sha256_in_prefix": "11f751c89fb81c66a4f67177d99bd052ed8a56872a46b25615a7c087416f24f1", + "size_in_bytes": 18441 + }, + { + "_path": "lib/python3.12/__pycache__/posixpath.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "90315a7bb4358cde4eb564c851f2b01955af5a0ff76700900936d8000b13a3c5", + "sha256_in_prefix": "90315a7bb4358cde4eb564c851f2b01955af5a0ff76700900936d8000b13a3c5", + "size_in_bytes": 18026 + }, + { + "_path": "lib/python3.12/__pycache__/pprint.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0df882488e23c40cbd3218e3f0a2bcd8814c0c32eff858313e5600236a81b750", + "sha256_in_prefix": "0df882488e23c40cbd3218e3f0a2bcd8814c0c32eff858313e5600236a81b750", + "size_in_bytes": 29469 + }, + { + "_path": "lib/python3.12/__pycache__/profile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5fa7719d1306bda79805b09f6780421139bea3407f4ee5ab06d7f59f3868703f", + "sha256_in_prefix": "5fa7719d1306bda79805b09f6780421139bea3407f4ee5ab06d7f59f3868703f", + "size_in_bytes": 22535 + }, + { + "_path": "lib/python3.12/__pycache__/pstats.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "af47c07bde9cf3073b3008f758aba9995d2bf4bf98315f4ef5491c198c4488c0", + "sha256_in_prefix": "af47c07bde9cf3073b3008f758aba9995d2bf4bf98315f4ef5491c198c4488c0", + "size_in_bytes": 37917 + }, + { + "_path": "lib/python3.12/__pycache__/pty.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5759c99a2a596015f8b111ef2252b77a30883f9864484616c63b9bb144ff056f", + "sha256_in_prefix": "5759c99a2a596015f8b111ef2252b77a30883f9864484616c63b9bb144ff056f", + "size_in_bytes": 7358 + }, + { + "_path": "lib/python3.12/__pycache__/py_compile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bfcd4356bda928d4f6ad8311bfc22d394772ceab9338931a3656c1a877bcd9d9", + "sha256_in_prefix": "bfcd4356bda928d4f6ad8311bfc22d394772ceab9338931a3656c1a877bcd9d9", + "size_in_bytes": 10025 + }, + { + "_path": "lib/python3.12/__pycache__/pyclbr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "07bc9f02a3f74c3ef1ba265bd0ff8adef5fc678e811b0500696ee72aa45750d8", + "sha256_in_prefix": "07bc9f02a3f74c3ef1ba265bd0ff8adef5fc678e811b0500696ee72aa45750d8", + "size_in_bytes": 14882 + }, + { + "_path": "lib/python3.12/__pycache__/pydoc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "30098eeb58f4692814369f64b9f1dc124c24b205a239961f3ca8ce8670503043", + "sha256_in_prefix": "30098eeb58f4692814369f64b9f1dc124c24b205a239961f3ca8ce8670503043", + "size_in_bytes": 142439 + }, + { + "_path": "lib/python3.12/__pycache__/queue.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "36ae7a1fcba30319b08d00c67fc5a1d4d947632d89a50db26582a62ebb72ae4b", + "sha256_in_prefix": "36ae7a1fcba30319b08d00c67fc5a1d4d947632d89a50db26582a62ebb72ae4b", + "size_in_bytes": 14727 + }, + { + "_path": "lib/python3.12/__pycache__/quopri.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "697f77104628b03886d9783076ce5c7b2ea37cdfdb699b99af738885ab813807", + "sha256_in_prefix": "697f77104628b03886d9783076ce5c7b2ea37cdfdb699b99af738885ab813807", + "size_in_bytes": 9318 + }, + { + "_path": "lib/python3.12/__pycache__/random.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "273e3d8e21797521eb03569a599df8240a38650ff455deccaceb3eeeddf4fc0b", + "sha256_in_prefix": "273e3d8e21797521eb03569a599df8240a38650ff455deccaceb3eeeddf4fc0b", + "size_in_bytes": 33148 + }, + { + "_path": "lib/python3.12/__pycache__/reprlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9628106a0b10e17c8ec9cdbc4829769031f6d18d4e64dcbdde414379bdf1a6c4", + "sha256_in_prefix": "9628106a0b10e17c8ec9cdbc4829769031f6d18d4e64dcbdde414379bdf1a6c4", + "size_in_bytes": 9904 + }, + { + "_path": "lib/python3.12/__pycache__/rlcompleter.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "63b7fc24181d2a11df0dea399f50b2d046f87dded57856887cbb687a0eeab505", + "sha256_in_prefix": "63b7fc24181d2a11df0dea399f50b2d046f87dded57856887cbb687a0eeab505", + "size_in_bytes": 8277 + }, + { + "_path": "lib/python3.12/__pycache__/runpy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a38830c181cbf11492bef3a8249ae01a58fac477846534ba4eec582c25ca2c29", + "sha256_in_prefix": "a38830c181cbf11492bef3a8249ae01a58fac477846534ba4eec582c25ca2c29", + "size_in_bytes": 14380 + }, + { + "_path": "lib/python3.12/__pycache__/sched.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bfc21d7e80eb5e2edc74fd3c08953b473a7656b8f526eb27be4b6e1d28fbef5d", + "sha256_in_prefix": "bfc21d7e80eb5e2edc74fd3c08953b473a7656b8f526eb27be4b6e1d28fbef5d", + "size_in_bytes": 7730 + }, + { + "_path": "lib/python3.12/__pycache__/secrets.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3ec32d5d79014da87dbf7f7a5be8a95d05d71a1561862aefc1c8b7dd8ab0ede3", + "sha256_in_prefix": "3ec32d5d79014da87dbf7f7a5be8a95d05d71a1561862aefc1c8b7dd8ab0ede3", + "size_in_bytes": 2551 + }, + { + "_path": "lib/python3.12/__pycache__/selectors.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "462cd1613922aab3f5645b07deee8f61f803295647557e51214508af6b897fd2", + "sha256_in_prefix": "462cd1613922aab3f5645b07deee8f61f803295647557e51214508af6b897fd2", + "size_in_bytes": 26123 + }, + { + "_path": "lib/python3.12/__pycache__/shelve.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "659c21f9c2cd512de2e27f0b1b6aff805675faa2a299eb3b1aa0d6e520a7a1ec", + "sha256_in_prefix": "659c21f9c2cd512de2e27f0b1b6aff805675faa2a299eb3b1aa0d6e520a7a1ec", + "size_in_bytes": 12908 + }, + { + "_path": "lib/python3.12/__pycache__/shlex.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5ee9ca7d0ef25c80c6f27e160033783d6c97e1dbeda4e8731295f2070fc65d78", + "sha256_in_prefix": "5ee9ca7d0ef25c80c6f27e160033783d6c97e1dbeda4e8731295f2070fc65d78", + "size_in_bytes": 14157 + }, + { + "_path": "lib/python3.12/__pycache__/shutil.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9696938170652caead4a23690e92ba42d2262b5f1e6407775f2ef157051c3051", + "sha256_in_prefix": "9696938170652caead4a23690e92ba42d2262b5f1e6407775f2ef157051c3051", + "size_in_bytes": 68108 + }, + { + "_path": "lib/python3.12/__pycache__/signal.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "505d59ff43450058d571b7d497e09afa0d02cdd8831b3006d921be5551386d78", + "sha256_in_prefix": "505d59ff43450058d571b7d497e09afa0d02cdd8831b3006d921be5551386d78", + "size_in_bytes": 4443 + }, + { + "_path": "lib/python3.12/__pycache__/site.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ac9e9dcf80b9768bdfdd014470eb2f0f129b4f9963fdaeae4f3850f850f0ba8b", + "sha256_in_prefix": "ac9e9dcf80b9768bdfdd014470eb2f0f129b4f9963fdaeae4f3850f850f0ba8b", + "size_in_bytes": 27984 + }, + { + "_path": "lib/python3.12/__pycache__/smtplib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c6feff8ea44169478c3b009bad62a485a5de2181488dd429b79d496418b7ddba", + "sha256_in_prefix": "c6feff8ea44169478c3b009bad62a485a5de2181488dd429b79d496418b7ddba", + "size_in_bytes": 48216 + }, + { + "_path": "lib/python3.12/__pycache__/sndhdr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1de22c6c33aac48d91e89a365d30b97b2ff56681c906601cbcadf333381b86ef", + "sha256_in_prefix": "1de22c6c33aac48d91e89a365d30b97b2ff56681c906601cbcadf333381b86ef", + "size_in_bytes": 10707 + }, + { + "_path": "lib/python3.12/__pycache__/socket.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "05630f4b0cc68253e01bdca0fb284f192323eb75cbc1fb2e24c4be64449acc86", + "sha256_in_prefix": "05630f4b0cc68253e01bdca0fb284f192323eb75cbc1fb2e24c4be64449acc86", + "size_in_bytes": 41812 + }, + { + "_path": "lib/python3.12/__pycache__/socketserver.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f95e19331c6e0aadf8db1785f8b5d26536922295f34f33620f3c36b142ce560a", + "sha256_in_prefix": "f95e19331c6e0aadf8db1785f8b5d26536922295f34f33620f3c36b142ce560a", + "size_in_bytes": 34253 + }, + { + "_path": "lib/python3.12/__pycache__/sre_compile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3a5e54eb556bb42422a13e9692e10523efc15de634ab915290d9b072892fff42", + "sha256_in_prefix": "3a5e54eb556bb42422a13e9692e10523efc15de634ab915290d9b072892fff42", + "size_in_bytes": 620 + }, + { + "_path": "lib/python3.12/__pycache__/sre_constants.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "573fa763db9ab7b87f276f6c2c9fa9dfb247def80a1d17af28a60f89c70b7c6a", + "sha256_in_prefix": "573fa763db9ab7b87f276f6c2c9fa9dfb247def80a1d17af28a60f89c70b7c6a", + "size_in_bytes": 623 + }, + { + "_path": "lib/python3.12/__pycache__/sre_parse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cf4dcdea7663b7997b1d7a8991c47d2708ee44a5e9e40af4447c35a1635d55f5", + "sha256_in_prefix": "cf4dcdea7663b7997b1d7a8991c47d2708ee44a5e9e40af4447c35a1635d55f5", + "size_in_bytes": 616 + }, + { + "_path": "lib/python3.12/__pycache__/ssl.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bd9b9e9146ca1d68ef898534aca875d91d5370eb4313561d0cb307e28c68177c", + "sha256_in_prefix": "bd9b9e9146ca1d68ef898534aca875d91d5370eb4313561d0cb307e28c68177c", + "size_in_bytes": 63006 + }, + { + "_path": "lib/python3.12/__pycache__/stat.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d604efdf45e7fbc9f492b942522c61845b6da9e04297b8312528bd0569e41ef3", + "sha256_in_prefix": "d604efdf45e7fbc9f492b942522c61845b6da9e04297b8312528bd0569e41ef3", + "size_in_bytes": 5226 + }, + { + "_path": "lib/python3.12/__pycache__/statistics.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3f6063558f6d5d726b10c959b04844b29f7488b96d871192b0ba78b7b6f85f7e", + "sha256_in_prefix": "3f6063558f6d5d726b10c959b04844b29f7488b96d871192b0ba78b7b6f85f7e", + "size_in_bytes": 55418 + }, + { + "_path": "lib/python3.12/__pycache__/string.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "587fe20bbbc31a4b43351b0bc56bd76770722fcba80c1cc77872e8cf5066ace6", + "sha256_in_prefix": "587fe20bbbc31a4b43351b0bc56bd76770722fcba80c1cc77872e8cf5066ace6", + "size_in_bytes": 11477 + }, + { + "_path": "lib/python3.12/__pycache__/stringprep.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "332e2ac898ba141f77a7a1e60d9f2c631e113cf13b4beefdd0978f577a4489bb", + "sha256_in_prefix": "332e2ac898ba141f77a7a1e60d9f2c631e113cf13b4beefdd0978f577a4489bb", + "size_in_bytes": 25155 + }, + { + "_path": "lib/python3.12/__pycache__/struct.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f562485ac8eaf64a95265b59d34b3bcb719b2276ff2368c05858167f13b148c8", + "sha256_in_prefix": "f562485ac8eaf64a95265b59d34b3bcb719b2276ff2368c05858167f13b148c8", + "size_in_bytes": 320 + }, + { + "_path": "lib/python3.12/__pycache__/subprocess.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fab23605d0e85aa4a3a48f4d2bd5195973bdb8e70079a7bdd244a276f83d1023", + "sha256_in_prefix": "fab23605d0e85aa4a3a48f4d2bd5195973bdb8e70079a7bdd244a276f83d1023", + "size_in_bytes": 79182 + }, + { + "_path": "lib/python3.12/__pycache__/sunau.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b2e134fce9d600419da6ed9af94247774fa776efea949591ca99a6389f6cdfad", + "sha256_in_prefix": "b2e134fce9d600419da6ed9af94247774fa776efea949591ca99a6389f6cdfad", + "size_in_bytes": 25418 + }, + { + "_path": "lib/python3.12/__pycache__/symtable.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "687dae0039002c47f75691e5d64d5afaa2440dccd15bdd4672ee0c86282cbf78", + "sha256_in_prefix": "687dae0039002c47f75691e5d64d5afaa2440dccd15bdd4672ee0c86282cbf78", + "size_in_bytes": 18776 + }, + { + "_path": "lib/python3.12/__pycache__/sysconfig.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b79e5534d8a37acf44399cc34ee3fd24671d932269e017334823dc0daf36d5e", + "sha256_in_prefix": "5b79e5534d8a37acf44399cc34ee3fd24671d932269e017334823dc0daf36d5e", + "size_in_bytes": 29197 + }, + { + "_path": "lib/python3.12/__pycache__/tabnanny.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8dc75f9addd4c1dd41d2e7d4acdbcd99eb328677da0f7335253e732300a40e18", + "sha256_in_prefix": "8dc75f9addd4c1dd41d2e7d4acdbcd99eb328677da0f7335253e732300a40e18", + "size_in_bytes": 12151 + }, + { + "_path": "lib/python3.12/__pycache__/tarfile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f645d7d0e0784cc294f5a817c876c6c5eb4f34a63ee0155c6d018b17f53943a4", + "sha256_in_prefix": "f645d7d0e0784cc294f5a817c876c6c5eb4f34a63ee0155c6d018b17f53943a4", + "size_in_bytes": 119335 + }, + { + "_path": "lib/python3.12/__pycache__/telnetlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b6d1071a8b8eaf64d029014720f5ce7869c08ef0c95bc4e230f2d369522636d7", + "sha256_in_prefix": "b6d1071a8b8eaf64d029014720f5ce7869c08ef0c95bc4e230f2d369522636d7", + "size_in_bytes": 28418 + }, + { + "_path": "lib/python3.12/__pycache__/tempfile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ef07e87c4b6e3905c20f23c1c8de0f8768e89f24c8bad36c0f24f3488091fa46", + "sha256_in_prefix": "ef07e87c4b6e3905c20f23c1c8de0f8768e89f24c8bad36c0f24f3488091fa46", + "size_in_bytes": 40393 + }, + { + "_path": "lib/python3.12/__pycache__/textwrap.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "878f002cc4390c1f22aa9c3ccb88258360caf5b82e169840909ff6bfa621d618", + "sha256_in_prefix": "878f002cc4390c1f22aa9c3ccb88258360caf5b82e169840909ff6bfa621d618", + "size_in_bytes": 18288 + }, + { + "_path": "lib/python3.12/__pycache__/this.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a6d5649cedccf80201909dded87b1fca8333a5b751dcb166b64fa0772ed4fe1c", + "sha256_in_prefix": "a6d5649cedccf80201909dded87b1fca8333a5b751dcb166b64fa0772ed4fe1c", + "size_in_bytes": 1403 + }, + { + "_path": "lib/python3.12/__pycache__/threading.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "23f00c5bf677fbca295954d09fc572342c56525a2b6a02192c45d357afec528b", + "sha256_in_prefix": "23f00c5bf677fbca295954d09fc572342c56525a2b6a02192c45d357afec528b", + "size_in_bytes": 65341 + }, + { + "_path": "lib/python3.12/__pycache__/timeit.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2f8e72a6f0012d59b9fb2b29a4ac54734164e15a11423322fb189535b7620f99", + "sha256_in_prefix": "2f8e72a6f0012d59b9fb2b29a4ac54734164e15a11423322fb189535b7620f99", + "size_in_bytes": 14859 + }, + { + "_path": "lib/python3.12/__pycache__/token.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "264e8999533abc83c502ac7d1cbbbc5e08bf617be6043a1ccf9ee625c547b600", + "sha256_in_prefix": "264e8999533abc83c502ac7d1cbbbc5e08bf617be6043a1ccf9ee625c547b600", + "size_in_bytes": 3552 + }, + { + "_path": "lib/python3.12/__pycache__/tokenize.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1e253f47d90ebcaae63c31308c7355ecbc0cba95fa92544ed48bdf25eeac9dc0", + "sha256_in_prefix": "1e253f47d90ebcaae63c31308c7355ecbc0cba95fa92544ed48bdf25eeac9dc0", + "size_in_bytes": 24770 + }, + { + "_path": "lib/python3.12/__pycache__/trace.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5cdc506524aae7c4685fc663ad0b82800bdba41470d6f5d78663974e9171070f", + "sha256_in_prefix": "5cdc506524aae7c4685fc663ad0b82800bdba41470d6f5d78663974e9171070f", + "size_in_bytes": 33019 + }, + { + "_path": "lib/python3.12/__pycache__/traceback.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e304522c0ec1cdc3737c986809271fd6f6be2a2a79fcd20fe623cfea24836887", + "sha256_in_prefix": "e304522c0ec1cdc3737c986809271fd6f6be2a2a79fcd20fe623cfea24836887", + "size_in_bytes": 51518 + }, + { + "_path": "lib/python3.12/__pycache__/tracemalloc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2b5795d388562b455cfe7d6bf354eb1c254fbaf224dee3f67bbc3e4738a400d8", + "sha256_in_prefix": "2b5795d388562b455cfe7d6bf354eb1c254fbaf224dee3f67bbc3e4738a400d8", + "size_in_bytes": 26902 + }, + { + "_path": "lib/python3.12/__pycache__/tty.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2fd320bd8a946b97ebd260dc01aeb28832e86a9933d29e21e4cf02c29117d5fc", + "sha256_in_prefix": "2fd320bd8a946b97ebd260dc01aeb28832e86a9933d29e21e4cf02c29117d5fc", + "size_in_bytes": 2663 + }, + { + "_path": "lib/python3.12/__pycache__/turtle.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0cab50c2432b4b3478a74695679729fb23896db50fe6e7d7f923079b451b101d", + "sha256_in_prefix": "0cab50c2432b4b3478a74695679729fb23896db50fe6e7d7f923079b451b101d", + "size_in_bytes": 184627 + }, + { + "_path": "lib/python3.12/__pycache__/types.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e31682b06ac02c4bd699ff473a362c939d11a4b4a26dc4567c7ac490587c1f14", + "sha256_in_prefix": "e31682b06ac02c4bd699ff473a362c939d11a4b4a26dc4567c7ac490587c1f14", + "size_in_bytes": 14934 + }, + { + "_path": "lib/python3.12/__pycache__/typing.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8b02e869c196f46811b3ecd9a3708ad7d2f18f78a403778cd472d18815b2daa7", + "sha256_in_prefix": "8b02e869c196f46811b3ecd9a3708ad7d2f18f78a403778cd472d18815b2daa7", + "size_in_bytes": 141855 + }, + { + "_path": "lib/python3.12/__pycache__/uu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "95a0d42a2fa8d02e9b6a8879c113edfdd8aea5c1498b6fd77f84eb4bc2699383", + "sha256_in_prefix": "95a0d42a2fa8d02e9b6a8879c113edfdd8aea5c1498b6fd77f84eb4bc2699383", + "size_in_bytes": 7811 + }, + { + "_path": "lib/python3.12/__pycache__/uuid.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "964fd016ac79b12c8ca2173d954d194ae95d566f1db5303e4a03dfd53269e6d4", + "sha256_in_prefix": "964fd016ac79b12c8ca2173d954d194ae95d566f1db5303e4a03dfd53269e6d4", + "size_in_bytes": 33002 + }, + { + "_path": "lib/python3.12/__pycache__/warnings.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8ba6d6def2f5207c0c2fa01a1061788efbe082808fcf8d629de5859dd7561e66", + "sha256_in_prefix": "8ba6d6def2f5207c0c2fa01a1061788efbe082808fcf8d629de5859dd7561e66", + "size_in_bytes": 23787 + }, + { + "_path": "lib/python3.12/__pycache__/wave.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "856fdb2c8cd2faa9a66b38bbfe67de82b58d22496ee6da9efe7369d9034d9b3b", + "sha256_in_prefix": "856fdb2c8cd2faa9a66b38bbfe67de82b58d22496ee6da9efe7369d9034d9b3b", + "size_in_bytes": 32079 + }, + { + "_path": "lib/python3.12/__pycache__/weakref.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "031718859997d432c8aa01ffb7018492226bfd377c11e3372db8004b5c7b9bbb", + "sha256_in_prefix": "031718859997d432c8aa01ffb7018492226bfd377c11e3372db8004b5c7b9bbb", + "size_in_bytes": 31343 + }, + { + "_path": "lib/python3.12/__pycache__/webbrowser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "40afe3b6fc2af4c37ace581e2d550ede56715f62d919f6ccdf2333d20940d2c2", + "sha256_in_prefix": "40afe3b6fc2af4c37ace581e2d550ede56715f62d919f6ccdf2333d20940d2c2", + "size_in_bytes": 26348 + }, + { + "_path": "lib/python3.12/__pycache__/xdrlib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "02de4164fe65b46acf71328dedef44d6a0b3b8a15804ac513479faf9e391f416", + "sha256_in_prefix": "02de4164fe65b46acf71328dedef44d6a0b3b8a15804ac513479faf9e391f416", + "size_in_bytes": 11836 + }, + { + "_path": "lib/python3.12/__pycache__/zipapp.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bcb29b8dbffbbc8cb58576fcf59afee8173734edf2f621988a2cb1991ce52f20", + "sha256_in_prefix": "bcb29b8dbffbbc8cb58576fcf59afee8173734edf2f621988a2cb1991ce52f20", + "size_in_bytes": 9972 + }, + { + "_path": "lib/python3.12/__pycache__/zipimport.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "74cd9b391d46c20efdd424512eb8afee85619e29ae0148d65cb6869af37634c2", + "sha256_in_prefix": "74cd9b391d46c20efdd424512eb8afee85619e29ae0148d65cb6869af37634c2", + "size_in_bytes": 24470 + }, + { + "_path": "lib/python3.12/_aix_support.py", + "path_type": "hardlink", + "sha256": "0982f187c62fbfc1e8d368c8eb4104b56df71009a6b2823565a699e7b4cd945c", + "sha256_in_prefix": "0982f187c62fbfc1e8d368c8eb4104b56df71009a6b2823565a699e7b4cd945c", + "size_in_bytes": 4021 + }, + { + "_path": "lib/python3.12/_collections_abc.py", + "path_type": "hardlink", + "sha256": "90324ee3e1c4ca5319f7242d4b7c1e90eb8418b3f999d07c853aa488356282e6", + "sha256_in_prefix": "90324ee3e1c4ca5319f7242d4b7c1e90eb8418b3f999d07c853aa488356282e6", + "size_in_bytes": 32082 + }, + { + "_path": "lib/python3.12/_compat_pickle.py", + "path_type": "hardlink", + "sha256": "12c8356a3d40bd0a336f13d7c6e2bed50d5c1a876563766a3175a6b328b5855e", + "sha256_in_prefix": "12c8356a3d40bd0a336f13d7c6e2bed50d5c1a876563766a3175a6b328b5855e", + "size_in_bytes": 8761 + }, + { + "_path": "lib/python3.12/_compression.py", + "path_type": "hardlink", + "sha256": "3ad5d60627477a60939ee44fc1bb3a05dbe8fb52f0f75039b8f5d8f1a278b981", + "sha256_in_prefix": "3ad5d60627477a60939ee44fc1bb3a05dbe8fb52f0f75039b8f5d8f1a278b981", + "size_in_bytes": 5681 + }, + { + "_path": "lib/python3.12/_markupbase.py", + "path_type": "hardlink", + "sha256": "cb14dd6f2e2439eb70b806cd49d19911363d424c2b6b9f4b73c9c08022d47030", + "sha256_in_prefix": "cb14dd6f2e2439eb70b806cd49d19911363d424c2b6b9f4b73c9c08022d47030", + "size_in_bytes": 14653 + }, + { + "_path": "lib/python3.12/_osx_support.py", + "path_type": "hardlink", + "sha256": "363d3240acbba18a270bd3161f1ddb478f8492dc14fc451b2dc314db5c5ee09c", + "sha256_in_prefix": "363d3240acbba18a270bd3161f1ddb478f8492dc14fc451b2dc314db5c5ee09c", + "size_in_bytes": 22023 + }, + { + "_path": "lib/python3.12/_py_abc.py", + "path_type": "hardlink", + "sha256": "f9c6fe3dd9b51bd7d93f867356e9d362600c924febfd903ee1c6e298860dca92", + "sha256_in_prefix": "f9c6fe3dd9b51bd7d93f867356e9d362600c924febfd903ee1c6e298860dca92", + "size_in_bytes": 6189 + }, + { + "_path": "lib/python3.12/_pydatetime.py", + "path_type": "hardlink", + "sha256": "8d5c6bb703d9b47f87bc20cb8003aaeee2dae7562a381e1623735f1ff8abccd3", + "sha256_in_prefix": "8d5c6bb703d9b47f87bc20cb8003aaeee2dae7562a381e1623735f1ff8abccd3", + "size_in_bytes": 92097 + }, + { + "_path": "lib/python3.12/_pydecimal.py", + "path_type": "hardlink", + "sha256": "c7108f0dc0beedb245daede78c9be602a64d47d3fb988e166e0474aa5bf317ea", + "sha256_in_prefix": "c7108f0dc0beedb245daede78c9be602a64d47d3fb988e166e0474aa5bf317ea", + "size_in_bytes": 229220 + }, + { + "_path": "lib/python3.12/_pyio.py", + "path_type": "hardlink", + "sha256": "22a2730be3230802593c75c930387e635809c6d82420e5234ef8d9cd1166ac8d", + "sha256_in_prefix": "22a2730be3230802593c75c930387e635809c6d82420e5234ef8d9cd1166ac8d", + "size_in_bytes": 93593 + }, + { + "_path": "lib/python3.12/_pylong.py", + "path_type": "hardlink", + "sha256": "79e219a7d1cab0b3d954fab7937c58ef965a3a132bdb885dda17bbb9fdfab16c", + "sha256_in_prefix": "79e219a7d1cab0b3d954fab7937c58ef965a3a132bdb885dda17bbb9fdfab16c", + "size_in_bytes": 9047 + }, + { + "_path": "lib/python3.12/_sitebuiltins.py", + "path_type": "hardlink", + "sha256": "b9388bc1d6d12ed6be12da420ab1feca40f99c0e33ec315d92b1e01cb69b25bc", + "sha256_in_prefix": "b9388bc1d6d12ed6be12da420ab1feca40f99c0e33ec315d92b1e01cb69b25bc", + "size_in_bytes": 3128 + }, + { + "_path": "lib/python3.12/_strptime.py", + "path_type": "hardlink", + "sha256": "302a4b9cf8fa7511c9142b110601f069fe195fec8217a49de46b340df2eafc32", + "sha256_in_prefix": "302a4b9cf8fa7511c9142b110601f069fe195fec8217a49de46b340df2eafc32", + "size_in_bytes": 24615 + }, + { + "_path": "lib/python3.12/_sysconfigdata__linux_x86_64-linux-gnu.py", + "path_type": "hardlink", + "sha256": "6ced255a34af860874d08ab2d42e1e7f1f3eed842267485f56099ab2e7cb2bea", + "sha256_in_prefix": "a348214a89f217bdc7f7803cc3f9b55b64553bf39f7466c7fb6a077434fb364c", + "size_in_bytes": 72539, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/_sysconfigdata__linux_x86_64-linux-gnu.py.orig", + "path_type": "hardlink", + "sha256": "b74948336a96837048de7f93d3e2c5d8a5f9580eb36804a9ef4b1cc201a6d5cf", + "sha256_in_prefix": "e5aaa12b1402ab0e6a8143462be9df61caac11473d6393c31f60a5d456e01ac4", + "size_in_bytes": 79849, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/_sysconfigdata_x86_64_conda_cos6_linux_gnu.py", + "path_type": "hardlink", + "sha256": "f612b39ea91650f533aa37c425aa644d5540ba3ec7fb13866761703482f5195e", + "sha256_in_prefix": "cd97cba4783c4505ea80f77d162c7929abcd7c6c77fc2ecbd15c740445043bc8", + "size_in_bytes": 76182, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/_sysconfigdata_x86_64_conda_linux_gnu.py", + "path_type": "hardlink", + "sha256": "638669009a84dbf99391605dc0d52149794b2c4ecffda7eb7d04276bd2e35b66", + "sha256_in_prefix": "8ad85c2bb5d922c2c56a77d4d6d15fc2914bd1cc49dd65317ebb91c5eec83040", + "size_in_bytes": 76102, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/_threading_local.py", + "path_type": "hardlink", + "sha256": "e1bf3dae66d0bfa63c8bb8a1d10c611203c35c636f7f5191fd56105788ef29cb", + "sha256_in_prefix": "e1bf3dae66d0bfa63c8bb8a1d10c611203c35c636f7f5191fd56105788ef29cb", + "size_in_bytes": 7220 + }, + { + "_path": "lib/python3.12/_weakrefset.py", + "path_type": "hardlink", + "sha256": "91895a451d06e9f521a1171b31b9b19bc9740f35af00d4fa106338ab7167c9ac", + "sha256_in_prefix": "91895a451d06e9f521a1171b31b9b19bc9740f35af00d4fa106338ab7167c9ac", + "size_in_bytes": 5893 + }, + { + "_path": "lib/python3.12/abc.py", + "path_type": "hardlink", + "sha256": "e558702a95cdce3febd289da021715d2b92bc43995b8a1bc58dfa1c3d8010287", + "sha256_in_prefix": "e558702a95cdce3febd289da021715d2b92bc43995b8a1bc58dfa1c3d8010287", + "size_in_bytes": 6538 + }, + { + "_path": "lib/python3.12/aifc.py", + "path_type": "hardlink", + "sha256": "e027e8a33567890ad7f84fea3be423cc0f6e49a33a31bbf279c2d0f64b6f8345", + "sha256_in_prefix": "e027e8a33567890ad7f84fea3be423cc0f6e49a33a31bbf279c2d0f64b6f8345", + "size_in_bytes": 34211 + }, + { + "_path": "lib/python3.12/antigravity.py", + "path_type": "hardlink", + "sha256": "8a5ee63e1b79ba2733e7ff4290b6eefea60e7f3a1ccb6bb519535aaf92b44967", + "sha256_in_prefix": "8a5ee63e1b79ba2733e7ff4290b6eefea60e7f3a1ccb6bb519535aaf92b44967", + "size_in_bytes": 500 + }, + { + "_path": "lib/python3.12/argparse.py", + "path_type": "hardlink", + "sha256": "2acf90321c8d7cc2fb3e1b0a248ec8df8431c4c095e99604aa71faec48455100", + "sha256_in_prefix": "2acf90321c8d7cc2fb3e1b0a248ec8df8431c4c095e99604aa71faec48455100", + "size_in_bytes": 101454 + }, + { + "_path": "lib/python3.12/ast.py", + "path_type": "hardlink", + "sha256": "d16626aa5c054bcc45221e56f84e55051b046caf0f8be1fe4902ea71534fb735", + "sha256_in_prefix": "d16626aa5c054bcc45221e56f84e55051b046caf0f8be1fe4902ea71534fb735", + "size_in_bytes": 64260 + }, + { + "_path": "lib/python3.12/asyncio/__init__.py", + "path_type": "hardlink", + "sha256": "61102f2b5f8fb832f0558cb66391f227970b3dd34ea2a621455587b4295e89a1", + "sha256_in_prefix": "61102f2b5f8fb832f0558cb66391f227970b3dd34ea2a621455587b4295e89a1", + "size_in_bytes": 1220 + }, + { + "_path": "lib/python3.12/asyncio/__main__.py", + "path_type": "hardlink", + "sha256": "eb22d0fa0c480025270feb1e7f962510666287fe2ccaeb7f309d32637507d061", + "sha256_in_prefix": "eb22d0fa0c480025270feb1e7f962510666287fe2ccaeb7f309d32637507d061", + "size_in_bytes": 3343 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "81b5c56b01fe402f3ba8673879016f382571a1730b00e999560aa0cc98482cba", + "sha256_in_prefix": "81b5c56b01fe402f3ba8673879016f382571a1730b00e999560aa0cc98482cba", + "size_in_bytes": 1452 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "54dac9a9ef4787a7cb997152411a9e2e9a67b769d94b31e3b7e462a026ebd974", + "sha256_in_prefix": "54dac9a9ef4787a7cb997152411a9e2e9a67b769d94b31e3b7e462a026ebd974", + "size_in_bytes": 5170 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/base_events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c5236ec7c79a2f7679de9b5cd9ddf21617eef0bbab8f290a2d982134fc61b1a6", + "sha256_in_prefix": "c5236ec7c79a2f7679de9b5cd9ddf21617eef0bbab8f290a2d982134fc61b1a6", + "size_in_bytes": 86605 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/base_futures.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e47a068ab5aa6d3ff40b062cb8075d14d65087b0da0e6d2dd10b52bb4ab651da", + "sha256_in_prefix": "e47a068ab5aa6d3ff40b062cb8075d14d65087b0da0e6d2dd10b52bb4ab651da", + "size_in_bytes": 3081 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/base_subprocess.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e4c9984c16179145018e4ee1de1005ac8f0c7b2c041bd00f7a0ccdd28235c422", + "sha256_in_prefix": "e4c9984c16179145018e4ee1de1005ac8f0c7b2c041bd00f7a0ccdd28235c422", + "size_in_bytes": 16097 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/base_tasks.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b7e0228ad6a2814e6e959d233571cc550dcab44c651cd48c86d6e9d0b1d8bc9", + "sha256_in_prefix": "5b7e0228ad6a2814e6e959d233571cc550dcab44c651cd48c86d6e9d0b1d8bc9", + "size_in_bytes": 4082 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/constants.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f903a1b4ae6b0f7963190114538b24882b61e83304a73111e5a309aa3b784b09", + "sha256_in_prefix": "f903a1b4ae6b0f7963190114538b24882b61e83304a73111e5a309aa3b784b09", + "size_in_bytes": 950 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/coroutines.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2a115f03f07952aff7eed047efe11aab05fe3c4891697a39d89f6f0bd8bfff60", + "sha256_in_prefix": "2a115f03f07952aff7eed047efe11aab05fe3c4891697a39d89f6f0bd8bfff60", + "size_in_bytes": 3764 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "601c0b9c7fe40c73748975d0f88831d98ee22d0e28ce03da8d8df367d445fc57", + "sha256_in_prefix": "601c0b9c7fe40c73748975d0f88831d98ee22d0e28ce03da8d8df367d445fc57", + "size_in_bytes": 36748 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/exceptions.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c99a9191cf9f2264c2ce0185594ba29e1f0ccbdaf2b2d65512ab725df2863d84", + "sha256_in_prefix": "c99a9191cf9f2264c2ce0185594ba29e1f0ccbdaf2b2d65512ab725df2863d84", + "size_in_bytes": 3076 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/format_helpers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aff85dc2c5065bf27337b9142f28c52f88612e8ff77f81852e0f78de566957ab", + "sha256_in_prefix": "aff85dc2c5065bf27337b9142f28c52f88612e8ff77f81852e0f78de566957ab", + "size_in_bytes": 3860 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/futures.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ab042360ae85d1c84fd7e8e7b655725eb406ddac0bb01640d628e09946aea412", + "sha256_in_prefix": "ab042360ae85d1c84fd7e8e7b655725eb406ddac0bb01640d628e09946aea412", + "size_in_bytes": 17251 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/locks.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d26a42603576d8a2f6b2c69fe2c901cb74d09354ac3280b7c1ce34be96cad95d", + "sha256_in_prefix": "d26a42603576d8a2f6b2c69fe2c901cb74d09354ac3280b7c1ce34be96cad95d", + "size_in_bytes": 27497 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/log.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5602b5b9191bef1cb3ae3ed28f838abc2e2ae8144718e1c262f7fcb139eb2c79", + "sha256_in_prefix": "5602b5b9191bef1cb3ae3ed28f838abc2e2ae8144718e1c262f7fcb139eb2c79", + "size_in_bytes": 276 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/mixins.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9062a0a9791074b45a8c9cf93c179119e62b2bac4045518874758579913dd899", + "sha256_in_prefix": "9062a0a9791074b45a8c9cf93c179119e62b2bac4045518874758579913dd899", + "size_in_bytes": 1031 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/proactor_events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "54a2455fa85f17efede3f6e9ee9f52bfdcb07dea02ef9ee0dd609c16e6822cdb", + "sha256_in_prefix": "54a2455fa85f17efede3f6e9ee9f52bfdcb07dea02ef9ee0dd609c16e6822cdb", + "size_in_bytes": 44553 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/protocols.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "508fe5036c60bfa91e9f7f2468f8ac4cb4ddcfabe8b943dba8ba8841ac9e0f76", + "sha256_in_prefix": "508fe5036c60bfa91e9f7f2468f8ac4cb4ddcfabe8b943dba8ba8841ac9e0f76", + "size_in_bytes": 8777 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/queues.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a6093f97c9f304536bb0fa52a21ca80e84089b3dacc620ccb0f757205bf554a5", + "sha256_in_prefix": "a6093f97c9f304536bb0fa52a21ca80e84089b3dacc620ccb0f757205bf554a5", + "size_in_bytes": 11936 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/runners.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "386c6a4446c84e4031345725260b50d2cbdfd17fa3fd52ba69a6adb61910e65e", + "sha256_in_prefix": "386c6a4446c84e4031345725260b50d2cbdfd17fa3fd52ba69a6adb61910e65e", + "size_in_bytes": 9931 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/selector_events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f993b9830d78e18c1b796f10844fa29e1b3f19f4b2356a194c252cf2e10402c2", + "sha256_in_prefix": "f993b9830d78e18c1b796f10844fa29e1b3f19f4b2356a194c252cf2e10402c2", + "size_in_bytes": 63071 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/sslproto.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bd17ef1b936b4a115e8d512a3c028de40ebdf7602b45f133d6cfca244f5e93c8", + "sha256_in_prefix": "bd17ef1b936b4a115e8d512a3c028de40ebdf7602b45f133d6cfca244f5e93c8", + "size_in_bytes": 41542 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/staggered.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "92444fe9ccd906abaefc43dfaff1771cce9e3df3f233bf76719e6191406b6b3c", + "sha256_in_prefix": "92444fe9ccd906abaefc43dfaff1771cce9e3df3f233bf76719e6191406b6b3c", + "size_in_bytes": 6235 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/streams.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "54f1f3cf81d42f51cef880beca3336115136538d714f2e718e23f66ba6fc618a", + "sha256_in_prefix": "54f1f3cf81d42f51cef880beca3336115136538d714f2e718e23f66ba6fc618a", + "size_in_bytes": 33375 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/subprocess.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6f7691e6f9859fa401268dbffc001eb1b7e9a036667598a49f863224b8956211", + "sha256_in_prefix": "6f7691e6f9859fa401268dbffc001eb1b7e9a036667598a49f863224b8956211", + "size_in_bytes": 12091 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/taskgroups.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3452713198772d9730e7f9073ec40ecda12f1715313cb0177e9c6b1a9c6a2878", + "sha256_in_prefix": "3452713198772d9730e7f9073ec40ecda12f1715313cb0177e9c6b1a9c6a2878", + "size_in_bytes": 7922 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/tasks.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "80979be6c940806ae5d581c5a519e9279e15224e5e633cf89966a8b33fd26f6b", + "sha256_in_prefix": "80979be6c940806ae5d581c5a519e9279e15224e5e633cf89966a8b33fd26f6b", + "size_in_bytes": 40366 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/threads.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f7161690d5cfb00fa2cb2f90c6a806346ff6ffdc0a2239713ed98bf09109f759", + "sha256_in_prefix": "f7161690d5cfb00fa2cb2f90c6a806346ff6ffdc0a2239713ed98bf09109f759", + "size_in_bytes": 1253 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/timeouts.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8c2dd8b3eae3dd6fefa7d1a1bd26cd75031db0fd160a7e039f1a0fa95e8a6ebd", + "sha256_in_prefix": "8c2dd8b3eae3dd6fefa7d1a1bd26cd75031db0fd160a7e039f1a0fa95e8a6ebd", + "size_in_bytes": 7792 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/transports.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "12f18492bc3c5e04989b742be8de7e3a414f28f55559047d214ee5401bbfec49", + "sha256_in_prefix": "12f18492bc3c5e04989b742be8de7e3a414f28f55559047d214ee5401bbfec49", + "size_in_bytes": 13999 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/trsock.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "50b2599e2b631a1bdb9b62dd9f82d0a3115ba073cc766f798a7f79aba57e7b30", + "sha256_in_prefix": "50b2599e2b631a1bdb9b62dd9f82d0a3115ba073cc766f798a7f79aba57e7b30", + "size_in_bytes": 5074 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/unix_events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bf83407bcbf421a05a23aa91b8c82e5ec34a3c3687f5e7a7b4aeed5902fd0b05", + "sha256_in_prefix": "bf83407bcbf421a05a23aa91b8c82e5ec34a3c3687f5e7a7b4aeed5902fd0b05", + "size_in_bytes": 67809 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/windows_events.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "23e7e59464916331f58e37fae9866e5964babba6feaa72ffcd845b9695d7b41f", + "sha256_in_prefix": "23e7e59464916331f58e37fae9866e5964babba6feaa72ffcd845b9695d7b41f", + "size_in_bytes": 41534 + }, + { + "_path": "lib/python3.12/asyncio/__pycache__/windows_utils.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0110b4bb15918dcb9260558bdd8994bdce84c54cf1603c8cfd6141738a641b67", + "sha256_in_prefix": "0110b4bb15918dcb9260558bdd8994bdce84c54cf1603c8cfd6141738a641b67", + "size_in_bytes": 7333 + }, + { + "_path": "lib/python3.12/asyncio/base_events.py", + "path_type": "hardlink", + "sha256": "4bf27730499a68f6a5b726204670590cb3425c9331941dd2036a0ad101af39cb", + "sha256_in_prefix": "4bf27730499a68f6a5b726204670590cb3425c9331941dd2036a0ad101af39cb", + "size_in_bytes": 77971 + }, + { + "_path": "lib/python3.12/asyncio/base_futures.py", + "path_type": "hardlink", + "sha256": "2f3798c4b82f5ac77647908b157c924f734f36871d98970e72849ea9a9a07856", + "sha256_in_prefix": "2f3798c4b82f5ac77647908b157c924f734f36871d98970e72849ea9a9a07856", + "size_in_bytes": 1974 + }, + { + "_path": "lib/python3.12/asyncio/base_subprocess.py", + "path_type": "hardlink", + "sha256": "d69ba8f97bf8c89564cadce49427574ddb98103a5db6f04b98798240332e7adf", + "sha256_in_prefix": "d69ba8f97bf8c89564cadce49427574ddb98103a5db6f04b98798240332e7adf", + "size_in_bytes": 8869 + }, + { + "_path": "lib/python3.12/asyncio/base_tasks.py", + "path_type": "hardlink", + "sha256": "56efac65b63db927af336fa55eb5bda93c97a2defa4734ea8d695ed20fd6712a", + "sha256_in_prefix": "56efac65b63db927af336fa55eb5bda93c97a2defa4734ea8d695ed20fd6712a", + "size_in_bytes": 2672 + }, + { + "_path": "lib/python3.12/asyncio/constants.py", + "path_type": "hardlink", + "sha256": "873fc2f9e66313c3c19c337269e704f204b59f9e91d6ecbec59f68335484d338", + "sha256_in_prefix": "873fc2f9e66313c3c19c337269e704f204b59f9e91d6ecbec59f68335484d338", + "size_in_bytes": 1413 + }, + { + "_path": "lib/python3.12/asyncio/coroutines.py", + "path_type": "hardlink", + "sha256": "2feec17557c230a80cc2a6391bbb1c44b9f3341820b05667e36a4eb12b749436", + "sha256_in_prefix": "2feec17557c230a80cc2a6391bbb1c44b9f3341820b05667e36a4eb12b749436", + "size_in_bytes": 3342 + }, + { + "_path": "lib/python3.12/asyncio/events.py", + "path_type": "hardlink", + "sha256": "6a18b7eee5926622c146e61a7eb39726b4656e07ca41d36b06936ffb2354f0ed", + "sha256_in_prefix": "6a18b7eee5926622c146e61a7eb39726b4656e07ca41d36b06936ffb2354f0ed", + "size_in_bytes": 29339 + }, + { + "_path": "lib/python3.12/asyncio/exceptions.py", + "path_type": "hardlink", + "sha256": "a5971f88be14cd1417d59adf539ae48c5d818f95362a4e0eb00017e3690ab37b", + "sha256_in_prefix": "a5971f88be14cd1417d59adf539ae48c5d818f95362a4e0eb00017e3690ab37b", + "size_in_bytes": 1752 + }, + { + "_path": "lib/python3.12/asyncio/format_helpers.py", + "path_type": "hardlink", + "sha256": "6377b672b3f4ba8b6f0f7a5f0ea00cde24c8cddc0ca764e3329f302763477f59", + "sha256_in_prefix": "6377b672b3f4ba8b6f0f7a5f0ea00cde24c8cddc0ca764e3329f302763477f59", + "size_in_bytes": 2404 + }, + { + "_path": "lib/python3.12/asyncio/futures.py", + "path_type": "hardlink", + "sha256": "7308533f98987fd96acb2cef27d16e2b05ff3efad406db4b0d4d39a2a8f6971d", + "sha256_in_prefix": "7308533f98987fd96acb2cef27d16e2b05ff3efad406db4b0d4d39a2a8f6971d", + "size_in_bytes": 14210 + }, + { + "_path": "lib/python3.12/asyncio/locks.py", + "path_type": "hardlink", + "sha256": "808bece72e0a4c6ab34299ffe555c927a8db475066ce8dc4ba614588fff720db", + "sha256_in_prefix": "808bece72e0a4c6ab34299ffe555c927a8db475066ce8dc4ba614588fff720db", + "size_in_bytes": 18994 + }, + { + "_path": "lib/python3.12/asyncio/log.py", + "path_type": "hardlink", + "sha256": "80e4cc3ded4b138baba486519e7444801a23d6ac35f229d336a407a96af7e8d2", + "sha256_in_prefix": "80e4cc3ded4b138baba486519e7444801a23d6ac35f229d336a407a96af7e8d2", + "size_in_bytes": 124 + }, + { + "_path": "lib/python3.12/asyncio/mixins.py", + "path_type": "hardlink", + "sha256": "8f4a3e16eca845ebfba422550cbcee7340ec8166d2bff6b750a8ed0de6b9ae3c", + "sha256_in_prefix": "8f4a3e16eca845ebfba422550cbcee7340ec8166d2bff6b750a8ed0de6b9ae3c", + "size_in_bytes": 481 + }, + { + "_path": "lib/python3.12/asyncio/proactor_events.py", + "path_type": "hardlink", + "sha256": "199d554fda7ec1a7e6a53e78f3f00f6e84dff27f0ed74107846d63106c895955", + "sha256_in_prefix": "199d554fda7ec1a7e6a53e78f3f00f6e84dff27f0ed74107846d63106c895955", + "size_in_bytes": 33385 + }, + { + "_path": "lib/python3.12/asyncio/protocols.py", + "path_type": "hardlink", + "sha256": "1d1b49988c338b4ef06e30f9e92d9db2e00080c341f0a3f573bb8312deb8aff6", + "sha256_in_prefix": "1d1b49988c338b4ef06e30f9e92d9db2e00080c341f0a3f573bb8312deb8aff6", + "size_in_bytes": 6957 + }, + { + "_path": "lib/python3.12/asyncio/queues.py", + "path_type": "hardlink", + "sha256": "8f020744ebd1f557dcb051a1530b504447660df906c2127a94bbcc8450ea7ef9", + "sha256_in_prefix": "8f020744ebd1f557dcb051a1530b504447660df906c2127a94bbcc8450ea7ef9", + "size_in_bytes": 7974 + }, + { + "_path": "lib/python3.12/asyncio/runners.py", + "path_type": "hardlink", + "sha256": "005535b70acf976133dda890b7c7f9076401fd7b532afeb27a1a68e863219072", + "sha256_in_prefix": "005535b70acf976133dda890b7c7f9076401fd7b532afeb27a1a68e863219072", + "size_in_bytes": 7159 + }, + { + "_path": "lib/python3.12/asyncio/selector_events.py", + "path_type": "hardlink", + "sha256": "a32d9cc6afcc03d3004ce07379cc1875f749111d2e3478e59260a3b82256b9b6", + "sha256_in_prefix": "a32d9cc6afcc03d3004ce07379cc1875f749111d2e3478e59260a3b82256b9b6", + "size_in_bytes": 48241 + }, + { + "_path": "lib/python3.12/asyncio/sslproto.py", + "path_type": "hardlink", + "sha256": "c747273038c3d27d0447f84eace19faf6c0e2730a0aa89639f9a40af41b5d180", + "sha256_in_prefix": "c747273038c3d27d0447f84eace19faf6c0e2730a0aa89639f9a40af41b5d180", + "size_in_bytes": 31739 + }, + { + "_path": "lib/python3.12/asyncio/staggered.py", + "path_type": "hardlink", + "sha256": "ff289bdc20a50ad9620393479d785bc653e71c2e3298f53ab27907cd136498e9", + "sha256_in_prefix": "ff289bdc20a50ad9620393479d785bc653e71c2e3298f53ab27907cd136498e9", + "size_in_bytes": 5992 + }, + { + "_path": "lib/python3.12/asyncio/streams.py", + "path_type": "hardlink", + "sha256": "6ec5c70fd95b0d51cc1e81cd21e8abe8c1b69650148d6bb75ab4aa4797319bd4", + "sha256_in_prefix": "6ec5c70fd95b0d51cc1e81cd21e8abe8c1b69650148d6bb75ab4aa4797319bd4", + "size_in_bytes": 27619 + }, + { + "_path": "lib/python3.12/asyncio/subprocess.py", + "path_type": "hardlink", + "sha256": "7b70605716334f63cc482123b2aaa3b7c5bb7138eeab63a037bd8068d43307c1", + "sha256_in_prefix": "7b70605716334f63cc482123b2aaa3b7c5bb7138eeab63a037bd8068d43307c1", + "size_in_bytes": 7737 + }, + { + "_path": "lib/python3.12/asyncio/taskgroups.py", + "path_type": "hardlink", + "sha256": "04895039b4870219ba5b94d42f3dccf996b4bf26108a54c47f30326eae4af0cc", + "sha256_in_prefix": "04895039b4870219ba5b94d42f3dccf996b4bf26108a54c47f30326eae4af0cc", + "size_in_bytes": 8747 + }, + { + "_path": "lib/python3.12/asyncio/tasks.py", + "path_type": "hardlink", + "sha256": "6f6aad82d597fea1800004075b9a2481604da0035f1143af1eb267823ec460e3", + "sha256_in_prefix": "6f6aad82d597fea1800004075b9a2481604da0035f1143af1eb267823ec460e3", + "size_in_bytes": 37362 + }, + { + "_path": "lib/python3.12/asyncio/threads.py", + "path_type": "hardlink", + "sha256": "39d37295383641565f0c08bd992e2f661dc8051eb17e890b834fce96bde0910e", + "sha256_in_prefix": "39d37295383641565f0c08bd992e2f661dc8051eb17e890b834fce96bde0910e", + "size_in_bytes": 790 + }, + { + "_path": "lib/python3.12/asyncio/timeouts.py", + "path_type": "hardlink", + "sha256": "3e40ca0dca3e54776579797837cd4936d73d04aae09fe0cf83ce1e5449d00163", + "sha256_in_prefix": "3e40ca0dca3e54776579797837cd4936d73d04aae09fe0cf83ce1e5449d00163", + "size_in_bytes": 5321 + }, + { + "_path": "lib/python3.12/asyncio/transports.py", + "path_type": "hardlink", + "sha256": "940108bc133de399f38928cad3274f463096168d8a3ee5148f2478d3cb636f1c", + "sha256_in_prefix": "940108bc133de399f38928cad3274f463096168d8a3ee5148f2478d3cb636f1c", + "size_in_bytes": 10722 + }, + { + "_path": "lib/python3.12/asyncio/trsock.py", + "path_type": "hardlink", + "sha256": "c0eac37debcc51b702b808f6b7ed3e417343f5ff5f57125dad600a27eb082328", + "sha256_in_prefix": "c0eac37debcc51b702b808f6b7ed3e417343f5ff5f57125dad600a27eb082328", + "size_in_bytes": 2475 + }, + { + "_path": "lib/python3.12/asyncio/unix_events.py", + "path_type": "hardlink", + "sha256": "1fff06cce78763800f05f4d2bebfcdbc07ebf9564ca7e7222e0d91e39dee08c9", + "sha256_in_prefix": "1fff06cce78763800f05f4d2bebfcdbc07ebf9564ca7e7222e0d91e39dee08c9", + "size_in_bytes": 53124 + }, + { + "_path": "lib/python3.12/asyncio/windows_events.py", + "path_type": "hardlink", + "sha256": "163927e5834c10c6c106d81cf3cfd568fd1ced7fa34d857836447d3c4cc7a9d3", + "sha256_in_prefix": "163927e5834c10c6c106d81cf3cfd568fd1ced7fa34d857836447d3c4cc7a9d3", + "size_in_bytes": 32587 + }, + { + "_path": "lib/python3.12/asyncio/windows_utils.py", + "path_type": "hardlink", + "sha256": "e6fcffefa2521666bc2aed0f5caf8e862c1c1014ad12d2ab5fbce09c2df9c6f0", + "sha256_in_prefix": "e6fcffefa2521666bc2aed0f5caf8e862c1c1014ad12d2ab5fbce09c2df9c6f0", + "size_in_bytes": 5060 + }, + { + "_path": "lib/python3.12/base64.py", + "path_type": "hardlink", + "sha256": "8a07aa038a9a36984d07a6703aea20a477477fdd4f24dc2c8763e493adca653b", + "sha256_in_prefix": "8a07aa038a9a36984d07a6703aea20a477477fdd4f24dc2c8763e493adca653b", + "size_in_bytes": 20603 + }, + { + "_path": "lib/python3.12/bdb.py", + "path_type": "hardlink", + "sha256": "314d8bf11b4824d47471ad25dab64bda895e39673fb744e88e7f622a3dd374f2", + "sha256_in_prefix": "314d8bf11b4824d47471ad25dab64bda895e39673fb744e88e7f622a3dd374f2", + "size_in_bytes": 32463 + }, + { + "_path": "lib/python3.12/bisect.py", + "path_type": "hardlink", + "sha256": "f1cf7b85fc36b5da249813fc5ab97d9464f8cc1bc817f7146206fa2713e35999", + "sha256_in_prefix": "f1cf7b85fc36b5da249813fc5ab97d9464f8cc1bc817f7146206fa2713e35999", + "size_in_bytes": 3423 + }, + { + "_path": "lib/python3.12/bz2.py", + "path_type": "hardlink", + "sha256": "76ab3252924e71e859d7d90e8d3db13b6554975cfcac0fdadced4de7f8779330", + "sha256_in_prefix": "76ab3252924e71e859d7d90e8d3db13b6554975cfcac0fdadced4de7f8779330", + "size_in_bytes": 11847 + }, + { + "_path": "lib/python3.12/cProfile.py", + "path_type": "hardlink", + "sha256": "c4c3edb84862431dffd6c044f5c02bb27f94e5b79a708bce195a7981efcb43bc", + "sha256_in_prefix": "c4c3edb84862431dffd6c044f5c02bb27f94e5b79a708bce195a7981efcb43bc", + "size_in_bytes": 6556 + }, + { + "_path": "lib/python3.12/calendar.py", + "path_type": "hardlink", + "sha256": "fb3fbcc0a0c8f33941153c425e5c39aedae687c86fcb001bf3a9526a9584459c", + "sha256_in_prefix": "fb3fbcc0a0c8f33941153c425e5c39aedae687c86fcb001bf3a9526a9584459c", + "size_in_bytes": 25418 + }, + { + "_path": "lib/python3.12/cgi.py", + "path_type": "hardlink", + "sha256": "f132666784c29a3e275f50596f87bb8abc388a94fcdb70be130000e01a9a6b78", + "sha256_in_prefix": "f132666784c29a3e275f50596f87bb8abc388a94fcdb70be130000e01a9a6b78", + "size_in_bytes": 34420 + }, + { + "_path": "lib/python3.12/cgitb.py", + "path_type": "hardlink", + "sha256": "08bbcca13a431551da73a2144c13f21e68cb79ac82223fbe5e60fcf89ce10f9c", + "sha256_in_prefix": "08bbcca13a431551da73a2144c13f21e68cb79ac82223fbe5e60fcf89ce10f9c", + "size_in_bytes": 12421 + }, + { + "_path": "lib/python3.12/chunk.py", + "path_type": "hardlink", + "sha256": "4817eb94eeb8835c3325433f68f17e0ebbf7c96065ecf6aba3af7852f9a5314b", + "sha256_in_prefix": "4817eb94eeb8835c3325433f68f17e0ebbf7c96065ecf6aba3af7852f9a5314b", + "size_in_bytes": 5500 + }, + { + "_path": "lib/python3.12/cmd.py", + "path_type": "hardlink", + "sha256": "fb82a8c4e44e5b559c88d516d79051534cec69a463df97defe05ac8a261f0a0d", + "sha256_in_prefix": "fb82a8c4e44e5b559c88d516d79051534cec69a463df97defe05ac8a261f0a0d", + "size_in_bytes": 14873 + }, + { + "_path": "lib/python3.12/code.py", + "path_type": "hardlink", + "sha256": "b191c6d6190382bcbb2826d7faf5521479abd733deb25d3cf3fba879b65b6953", + "sha256_in_prefix": "b191c6d6190382bcbb2826d7faf5521479abd733deb25d3cf3fba879b65b6953", + "size_in_bytes": 10695 + }, + { + "_path": "lib/python3.12/codecs.py", + "path_type": "hardlink", + "sha256": "7b7839e53a77961153240aecfe11edc8054d05b1dedd83894450dae21ec05785", + "sha256_in_prefix": "7b7839e53a77961153240aecfe11edc8054d05b1dedd83894450dae21ec05785", + "size_in_bytes": 36870 + }, + { + "_path": "lib/python3.12/codeop.py", + "path_type": "hardlink", + "sha256": "3fb545862a1f9030c0d8f1ae6c72457d14a26d67a9b45de455e49900ff84a3a9", + "sha256_in_prefix": "3fb545862a1f9030c0d8f1ae6c72457d14a26d67a9b45de455e49900ff84a3a9", + "size_in_bytes": 5908 + }, + { + "_path": "lib/python3.12/collections/__init__.py", + "path_type": "hardlink", + "sha256": "0af967cd58036507b3d0fbc33b7a996c61dbb52a94b0b738c8bef12cd4cc7dd4", + "sha256_in_prefix": "0af967cd58036507b3d0fbc33b7a996c61dbb52a94b0b738c8bef12cd4cc7dd4", + "size_in_bytes": 52378 + }, + { + "_path": "lib/python3.12/collections/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da88a1690de36e64cb332a23f2746addeac960ce6e29ae45e50096134224fa5d", + "sha256_in_prefix": "da88a1690de36e64cb332a23f2746addeac960ce6e29ae45e50096134224fa5d", + "size_in_bytes": 73084 + }, + { + "_path": "lib/python3.12/collections/__pycache__/abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0819c3f2da5a013bc030d4f2d1fc71e3b835a1b3a61bbcf648de8199e11289fc", + "sha256_in_prefix": "0819c3f2da5a013bc030d4f2d1fc71e3b835a1b3a61bbcf648de8199e11289fc", + "size_in_bytes": 244 + }, + { + "_path": "lib/python3.12/collections/abc.py", + "path_type": "hardlink", + "sha256": "9cb4208f99128a0489b6c8e6c61637617dd7d4250c59e065491957eda084dd10", + "sha256_in_prefix": "9cb4208f99128a0489b6c8e6c61637617dd7d4250c59e065491957eda084dd10", + "size_in_bytes": 119 + }, + { + "_path": "lib/python3.12/colorsys.py", + "path_type": "hardlink", + "sha256": "d9800f8e81d46e63ca6f2e7d6ac5f344d85afb92c3cf6d103b5f977f1ad66ac2", + "sha256_in_prefix": "d9800f8e81d46e63ca6f2e7d6ac5f344d85afb92c3cf6d103b5f977f1ad66ac2", + "size_in_bytes": 4062 + }, + { + "_path": "lib/python3.12/compileall.py", + "path_type": "hardlink", + "sha256": "588f003bb5088ce380f3c335febaec1318811d275e5554b106655c4ceebabcfb", + "sha256_in_prefix": "588f003bb5088ce380f3c335febaec1318811d275e5554b106655c4ceebabcfb", + "size_in_bytes": 20507 + }, + { + "_path": "lib/python3.12/concurrent/__init__.py", + "path_type": "hardlink", + "sha256": "87ad5c8954dd56fbbca04517bf87477ff4dce575170c7dd1281d7ef1f4214ac8", + "sha256_in_prefix": "87ad5c8954dd56fbbca04517bf87477ff4dce575170c7dd1281d7ef1f4214ac8", + "size_in_bytes": 38 + }, + { + "_path": "lib/python3.12/concurrent/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3000f4393d5ae0f9787ec45afa8941da8e0b0bd9314d83869ac19c0159606a31", + "sha256_in_prefix": "3000f4393d5ae0f9787ec45afa8941da8e0b0bd9314d83869ac19c0159606a31", + "size_in_bytes": 134 + }, + { + "_path": "lib/python3.12/concurrent/futures/__init__.py", + "path_type": "hardlink", + "sha256": "9bcec785db3eddc6d462883957ba6d3ff4370501fece505101444bae542883e8", + "sha256_in_prefix": "9bcec785db3eddc6d462883957ba6d3ff4370501fece505101444bae542883e8", + "size_in_bytes": 1558 + }, + { + "_path": "lib/python3.12/concurrent/futures/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "22d44553fe481d03f6fbe245d3e3c4b6b2a15cf4f88cf0613c25721a1e3f62f4", + "sha256_in_prefix": "22d44553fe481d03f6fbe245d3e3c4b6b2a15cf4f88cf0613c25721a1e3f62f4", + "size_in_bytes": 1245 + }, + { + "_path": "lib/python3.12/concurrent/futures/__pycache__/_base.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0034c4fa5d692890a93fb3e44bf8e4e978f98fdbab6efc939df04cea56ebb64d", + "sha256_in_prefix": "0034c4fa5d692890a93fb3e44bf8e4e978f98fdbab6efc939df04cea56ebb64d", + "size_in_bytes": 32183 + }, + { + "_path": "lib/python3.12/concurrent/futures/__pycache__/process.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "231bf473f6dd5ffc0ea74590bb548883ebd05aaec5b797a27d5e36c3aaad8b00", + "sha256_in_prefix": "231bf473f6dd5ffc0ea74590bb548883ebd05aaec5b797a27d5e36c3aaad8b00", + "size_in_bytes": 35732 + }, + { + "_path": "lib/python3.12/concurrent/futures/__pycache__/thread.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e4ec2736383c5adf67995d744c62fc6d9b845844ea5c28b373e544b6b22b304f", + "sha256_in_prefix": "e4ec2736383c5adf67995d744c62fc6d9b845844ea5c28b373e544b6b22b304f", + "size_in_bytes": 10196 + }, + { + "_path": "lib/python3.12/concurrent/futures/_base.py", + "path_type": "hardlink", + "sha256": "8c6d5f09f7c535d40fa1c30ebfcb35e0601c2abf32286a82cf151af7ddf72473", + "sha256_in_prefix": "8c6d5f09f7c535d40fa1c30ebfcb35e0601c2abf32286a82cf151af7ddf72473", + "size_in_bytes": 22833 + }, + { + "_path": "lib/python3.12/concurrent/futures/process.py", + "path_type": "hardlink", + "sha256": "d902a4365e8380d839b2dda00419e286b6d292ca17a00a56bee7b7dac8ad5aa7", + "sha256_in_prefix": "d902a4365e8380d839b2dda00419e286b6d292ca17a00a56bee7b7dac8ad5aa7", + "size_in_bytes": 36351 + }, + { + "_path": "lib/python3.12/concurrent/futures/thread.py", + "path_type": "hardlink", + "sha256": "33f69dd18c908992bce91ad3aa6bd809a42684e2b66caaa09ad4934ca0a29f58", + "sha256_in_prefix": "33f69dd18c908992bce91ad3aa6bd809a42684e2b66caaa09ad4934ca0a29f58", + "size_in_bytes": 8884 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/Makefile", + "path_type": "hardlink", + "sha256": "c04fe9bfe51911f5d0e66b3dd087822579e6548a4058999576d1e641b4a10a61", + "sha256_in_prefix": "0aa0388a983d75a3060fd109079c2542a32d6006e59559daef28e38164496c76", + "size_in_bytes": 183346, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup", + "path_type": "hardlink", + "sha256": "17c83234ffe6302e7eaf62a363571fe6cc240b8b97bed7e503b85429fd10a5ca", + "sha256_in_prefix": "17c83234ffe6302e7eaf62a363571fe6cc240b8b97bed7e503b85429fd10a5ca", + "size_in_bytes": 11525 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.bootstrap", + "path_type": "hardlink", + "sha256": "2917936af36bd7d641c737f72f68599fd13c26a28faebba7c07799879b1b9b31", + "sha256_in_prefix": "2917936af36bd7d641c737f72f68599fd13c26a28faebba7c07799879b1b9b31", + "size_in_bytes": 902 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.local", + "path_type": "hardlink", + "sha256": "d29e734b34f3f8cb4a8c2b9305b6e7f378214ecd13928f2671db2c7ee0f7b378", + "sha256_in_prefix": "d29e734b34f3f8cb4a8c2b9305b6e7f378214ecd13928f2671db2c7ee0f7b378", + "size_in_bytes": 41 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/Setup.stdlib", + "path_type": "hardlink", + "sha256": "c5682d6662a3543a65dc68fb666a16ebb1f1d0e782f1b82431b04d65604f02dc", + "sha256_in_prefix": "c5682d6662a3543a65dc68fb666a16ebb1f1d0e782f1b82431b04d65604f02dc", + "size_in_bytes": 6267 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/__pycache__/python-config.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b4407bd50f8fa259d9b883439247ebe51d9fcff13e36170f41610b784908aa6b", + "sha256_in_prefix": "b4407bd50f8fa259d9b883439247ebe51d9fcff13e36170f41610b784908aa6b", + "size_in_bytes": 3176 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/config.c", + "path_type": "hardlink", + "sha256": "227adbaf93184fa0695dcf0db5e3eb339435da5f44a9c44ff4fbf2158b0a66f9", + "sha256_in_prefix": "227adbaf93184fa0695dcf0db5e3eb339435da5f44a9c44ff4fbf2158b0a66f9", + "size_in_bytes": 3485 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/config.c.in", + "path_type": "hardlink", + "sha256": "5c76ef60a799f420b09b047dc1087728e5ed08ba82f6c7664c4d4f1d1d715b21", + "sha256_in_prefix": "5c76ef60a799f420b09b047dc1087728e5ed08ba82f6c7664c4d4f1d1d715b21", + "size_in_bytes": 1752 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/install-sh", + "path_type": "hardlink", + "sha256": "3d7488bebd0cfc9b5c440c55d5b44f1c6e2e3d3e19894821bae4a27f9307f1d2", + "sha256_in_prefix": "3d7488bebd0cfc9b5c440c55d5b44f1c6e2e3d3e19894821bae4a27f9307f1d2", + "size_in_bytes": 15358 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/makesetup", + "path_type": "hardlink", + "sha256": "0615264cbe9f3a4fce27de0054839ea814f2fe6f6091a0e17b18b5b15c665cfa", + "sha256_in_prefix": "0615264cbe9f3a4fce27de0054839ea814f2fe6f6091a0e17b18b5b15c665cfa", + "size_in_bytes": 9312 + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/python-config.py", + "path_type": "hardlink", + "sha256": "7abfff7a8a211fa60b172e113e0df064b40b87a83b497f0476d1a9614cff7d79", + "sha256_in_prefix": "004cdc5705b278fcf918456558bbdf2b697b05839da550b064ed5cfb529b816e", + "size_in_bytes": 2073, + "file_mode": "text", + "prefix_placeholder": "/home/conda/feedstock_root/build_artifacts/python-split_1713204800955/_h_env_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehold_placehol" + }, + { + "_path": "lib/python3.12/config-3.12-x86_64-linux-gnu/python.o", + "path_type": "hardlink", + "sha256": "d04a597d52a548fcfc68a34af839dc2a6a6ab5cf4707890b014c230b2a276d01", + "sha256_in_prefix": "d04a597d52a548fcfc68a34af839dc2a6a6ab5cf4707890b014c230b2a276d01", + "size_in_bytes": 10800 + }, + { + "_path": "lib/python3.12/configparser.py", + "path_type": "hardlink", + "sha256": "8d822edd41d1085e0c697f1926f3f98e5c7889b4072361ae88726464b37f6460", + "sha256_in_prefix": "8d822edd41d1085e0c697f1926f3f98e5c7889b4072361ae88726464b37f6460", + "size_in_bytes": 53789 + }, + { + "_path": "lib/python3.12/contextlib.py", + "path_type": "hardlink", + "sha256": "8b7a477f978a8532852fd81e241c78182516bc4975d672d580a5848a76e11eb6", + "sha256_in_prefix": "8b7a477f978a8532852fd81e241c78182516bc4975d672d580a5848a76e11eb6", + "size_in_bytes": 27637 + }, + { + "_path": "lib/python3.12/contextvars.py", + "path_type": "hardlink", + "sha256": "5ed260be8d1f4fe92261b7810b4bb1e8539c42093d7493f677d076e1a87f459a", + "sha256_in_prefix": "5ed260be8d1f4fe92261b7810b4bb1e8539c42093d7493f677d076e1a87f459a", + "size_in_bytes": 129 + }, + { + "_path": "lib/python3.12/copy.py", + "path_type": "hardlink", + "sha256": "cbd25547933176fcf6bb05c2adc9f4796d15ac20b9b82dcf890daea7203daeab", + "sha256_in_prefix": "cbd25547933176fcf6bb05c2adc9f4796d15ac20b9b82dcf890daea7203daeab", + "size_in_bytes": 8412 + }, + { + "_path": "lib/python3.12/copyreg.py", + "path_type": "hardlink", + "sha256": "c8eda41f05c6bf95a4da4726a530409d2485ae060b8d019b3a8034389a15d3e9", + "sha256_in_prefix": "c8eda41f05c6bf95a4da4726a530409d2485ae060b8d019b3a8034389a15d3e9", + "size_in_bytes": 7614 + }, + { + "_path": "lib/python3.12/crypt.py", + "path_type": "hardlink", + "sha256": "208df2ff33c19056345dcf5474abef1a58da799e2f3bab09d1d28b77ad3c623d", + "sha256_in_prefix": "208df2ff33c19056345dcf5474abef1a58da799e2f3bab09d1d28b77ad3c623d", + "size_in_bytes": 3913 + }, + { + "_path": "lib/python3.12/csv.py", + "path_type": "hardlink", + "sha256": "46004923196e98a67f87d30da64d070027c81f144f5ac91242fbfae33507dda8", + "sha256_in_prefix": "46004923196e98a67f87d30da64d070027c81f144f5ac91242fbfae33507dda8", + "size_in_bytes": 16386 + }, + { + "_path": "lib/python3.12/ctypes/__init__.py", + "path_type": "hardlink", + "sha256": "0782592567ad71097198a3afe985ac3e2ea0b9b5e75452402c9460c89a86318a", + "sha256_in_prefix": "0782592567ad71097198a3afe985ac3e2ea0b9b5e75452402c9460c89a86318a", + "size_in_bytes": 18182 + }, + { + "_path": "lib/python3.12/ctypes/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8cdbd586a4292f3af9b3f1ab5ed3747fa842225c6b9593a9a1133c4b5ac211a1", + "sha256_in_prefix": "8cdbd586a4292f3af9b3f1ab5ed3747fa842225c6b9593a9a1133c4b5ac211a1", + "size_in_bytes": 23444 + }, + { + "_path": "lib/python3.12/ctypes/__pycache__/_aix.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6228babd9898f97e1485919186ad7aeb989c1c914503d5187078fc9719b47593", + "sha256_in_prefix": "6228babd9898f97e1485919186ad7aeb989c1c914503d5187078fc9719b47593", + "size_in_bytes": 12346 + }, + { + "_path": "lib/python3.12/ctypes/__pycache__/_endian.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "91ff899e87576a55e83db1b60b620af26c79aae8ea3eb1c960042a30585c3a8e", + "sha256_in_prefix": "91ff899e87576a55e83db1b60b620af26c79aae8ea3eb1c960042a30585c3a8e", + "size_in_bytes": 3375 + }, + { + "_path": "lib/python3.12/ctypes/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d3e800c24830ff745650261402622d82e3e97e411984affd25b81b64d7027944", + "sha256_in_prefix": "d3e800c24830ff745650261402622d82e3e97e411984affd25b81b64d7027944", + "size_in_bytes": 17244 + }, + { + "_path": "lib/python3.12/ctypes/__pycache__/wintypes.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b4fe14e664de14a2be3c7fe70d9a1f89311524f07af6b394d6f17c230bfcff99", + "sha256_in_prefix": "b4fe14e664de14a2be3c7fe70d9a1f89311524f07af6b394d6f17c230bfcff99", + "size_in_bytes": 8490 + }, + { + "_path": "lib/python3.12/ctypes/_aix.py", + "path_type": "hardlink", + "sha256": "540e2821fa36981bde5c6ffb8f972474b06db4a37c1854c0e0e379b75d2b0fa3", + "sha256_in_prefix": "540e2821fa36981bde5c6ffb8f972474b06db4a37c1854c0e0e379b75d2b0fa3", + "size_in_bytes": 12505 + }, + { + "_path": "lib/python3.12/ctypes/_endian.py", + "path_type": "hardlink", + "sha256": "c5d692bdce10dfee242752620061bab684633bc72445a3def484961ef1bdbf3a", + "sha256_in_prefix": "c5d692bdce10dfee242752620061bab684633bc72445a3def484961ef1bdbf3a", + "size_in_bytes": 2535 + }, + { + "_path": "lib/python3.12/ctypes/macholib/README.ctypes", + "path_type": "hardlink", + "sha256": "dc29d1da83b6a0a09a41647e4111eee878ed079c2d6b54a98fd6d8b88dd581f2", + "sha256_in_prefix": "dc29d1da83b6a0a09a41647e4111eee878ed079c2d6b54a98fd6d8b88dd581f2", + "size_in_bytes": 296 + }, + { + "_path": "lib/python3.12/ctypes/macholib/__init__.py", + "path_type": "hardlink", + "sha256": "1e77c01eec8f167ed10b754f153c0c743c8e5196ae9c81dffc08f129ab56dbfd", + "sha256_in_prefix": "1e77c01eec8f167ed10b754f153c0c743c8e5196ae9c81dffc08f129ab56dbfd", + "size_in_bytes": 154 + }, + { + "_path": "lib/python3.12/ctypes/macholib/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6c63540c5e58dd498a37845dfb54597774f1b6f2bbf83443fcabf66804dd4622", + "sha256_in_prefix": "6c63540c5e58dd498a37845dfb54597774f1b6f2bbf83443fcabf66804dd4622", + "size_in_bytes": 311 + }, + { + "_path": "lib/python3.12/ctypes/macholib/__pycache__/dyld.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fe8c8439d8e9cab6163c766be6cb14153034300f346dab11c21f06630fb5ff82", + "sha256_in_prefix": "fe8c8439d8e9cab6163c766be6cb14153034300f346dab11c21f06630fb5ff82", + "size_in_bytes": 6973 + }, + { + "_path": "lib/python3.12/ctypes/macholib/__pycache__/dylib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6342793d27fd24e0535d8cdf68276bac639dcc38779508c2dc85c7bd1b87505b", + "sha256_in_prefix": "6342793d27fd24e0535d8cdf68276bac639dcc38779508c2dc85c7bd1b87505b", + "size_in_bytes": 1274 + }, + { + "_path": "lib/python3.12/ctypes/macholib/__pycache__/framework.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "002d58c530f55e0c99da39baeddd67fa64ba8af7e7ddd9799cd44b4e956c93e7", + "sha256_in_prefix": "002d58c530f55e0c99da39baeddd67fa64ba8af7e7ddd9799cd44b4e956c93e7", + "size_in_bytes": 1404 + }, + { + "_path": "lib/python3.12/ctypes/macholib/dyld.py", + "path_type": "hardlink", + "sha256": "f43f287127958d63815859486720c9a703ed9dd2371261e74e88cf7d9c45a2cd", + "sha256_in_prefix": "f43f287127958d63815859486720c9a703ed9dd2371261e74e88cf7d9c45a2cd", + "size_in_bytes": 5156 + }, + { + "_path": "lib/python3.12/ctypes/macholib/dylib.py", + "path_type": "hardlink", + "sha256": "f19ee056b18165cc6735efab0b4ca3508be9405b9646c38113316c15e8278a6f", + "sha256_in_prefix": "f19ee056b18165cc6735efab0b4ca3508be9405b9646c38113316c15e8278a6f", + "size_in_bytes": 960 + }, + { + "_path": "lib/python3.12/ctypes/macholib/fetch_macholib", + "path_type": "hardlink", + "sha256": "a9f6faacdb1aa00ac2f68043cd445171de9639a732b861bd5e64090a2865ab23", + "sha256_in_prefix": "a9f6faacdb1aa00ac2f68043cd445171de9639a732b861bd5e64090a2865ab23", + "size_in_bytes": 84 + }, + { + "_path": "lib/python3.12/ctypes/macholib/fetch_macholib.bat", + "path_type": "hardlink", + "sha256": "7497fbdbb98afca4ac455e3a057c59bcdebaf1280e25c94741dc301f05cb53e5", + "sha256_in_prefix": "7497fbdbb98afca4ac455e3a057c59bcdebaf1280e25c94741dc301f05cb53e5", + "size_in_bytes": 75 + }, + { + "_path": "lib/python3.12/ctypes/macholib/framework.py", + "path_type": "hardlink", + "sha256": "302439e40d9cbdd61b8b7cffd0b7e1278a6811b635044ee366a36e0d991f62da", + "sha256_in_prefix": "302439e40d9cbdd61b8b7cffd0b7e1278a6811b635044ee366a36e0d991f62da", + "size_in_bytes": 1105 + }, + { + "_path": "lib/python3.12/ctypes/util.py", + "path_type": "hardlink", + "sha256": "35e5eda9cac8f82b922bcc4a7d303a8dae9216444158a7c21f8b96b7309f3bc7", + "sha256_in_prefix": "35e5eda9cac8f82b922bcc4a7d303a8dae9216444158a7c21f8b96b7309f3bc7", + "size_in_bytes": 14936 + }, + { + "_path": "lib/python3.12/ctypes/wintypes.py", + "path_type": "hardlink", + "sha256": "5c4d9ba1a21683838ed1d1f007b6038304e42aacf34c576e820311d26cb243f3", + "sha256_in_prefix": "5c4d9ba1a21683838ed1d1f007b6038304e42aacf34c576e820311d26cb243f3", + "size_in_bytes": 5629 + }, + { + "_path": "lib/python3.12/curses/__init__.py", + "path_type": "hardlink", + "sha256": "d8730e360dd00ec046bdd85cae41fe83c907c6ae3716a964158fce8f31ab28b0", + "sha256_in_prefix": "d8730e360dd00ec046bdd85cae41fe83c907c6ae3716a964158fce8f31ab28b0", + "size_in_bytes": 3369 + }, + { + "_path": "lib/python3.12/curses/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "170003b6d681e7edbd5e00071df896a992f75b44019f0988eb2237d900219e96", + "sha256_in_prefix": "170003b6d681e7edbd5e00071df896a992f75b44019f0988eb2237d900219e96", + "size_in_bytes": 2796 + }, + { + "_path": "lib/python3.12/curses/__pycache__/ascii.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4c92d7db372b8ae2ee733bc03f8c27a27b7bef4ba5da482086a4c41ba08afba3", + "sha256_in_prefix": "4c92d7db372b8ae2ee733bc03f8c27a27b7bef4ba5da482086a4c41ba08afba3", + "size_in_bytes": 5017 + }, + { + "_path": "lib/python3.12/curses/__pycache__/has_key.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "db429f7f0837313ff914732f941a43fdc475ad035750bf8ee85f5474f39fa719", + "sha256_in_prefix": "db429f7f0837313ff914732f941a43fdc475ad035750bf8ee85f5474f39fa719", + "size_in_bytes": 10370 + }, + { + "_path": "lib/python3.12/curses/__pycache__/panel.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "684e3f0ad39fda8c4473328642a052c232b16327ba5ab0aacac2f8e1b3662998", + "sha256_in_prefix": "684e3f0ad39fda8c4473328642a052c232b16327ba5ab0aacac2f8e1b3662998", + "size_in_bytes": 235 + }, + { + "_path": "lib/python3.12/curses/__pycache__/textpad.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "eadfa3c3fc254a5b7ef466b9cffad905422630a248b6f5bb67d24b84922fe318", + "sha256_in_prefix": "eadfa3c3fc254a5b7ef466b9cffad905422630a248b6f5bb67d24b84922fe318", + "size_in_bytes": 12224 + }, + { + "_path": "lib/python3.12/curses/ascii.py", + "path_type": "hardlink", + "sha256": "780dd8bbaf0ee7e832f164c1772953e694a9cd1031d1ab1471af65344d3645e6", + "sha256_in_prefix": "780dd8bbaf0ee7e832f164c1772953e694a9cd1031d1ab1471af65344d3645e6", + "size_in_bytes": 2543 + }, + { + "_path": "lib/python3.12/curses/has_key.py", + "path_type": "hardlink", + "sha256": "15a052812d9ae80124bb25b3f5b9ffae38e2b03073774e163abf3d773140cfb3", + "sha256_in_prefix": "15a052812d9ae80124bb25b3f5b9ffae38e2b03073774e163abf3d773140cfb3", + "size_in_bytes": 5634 + }, + { + "_path": "lib/python3.12/curses/panel.py", + "path_type": "hardlink", + "sha256": "13ef404a30da1825a612ca3e453db88c305d45deef4441c4c9e2ef7ee0ef50c7", + "sha256_in_prefix": "13ef404a30da1825a612ca3e453db88c305d45deef4441c4c9e2ef7ee0ef50c7", + "size_in_bytes": 87 + }, + { + "_path": "lib/python3.12/curses/textpad.py", + "path_type": "hardlink", + "sha256": "6fd91c3fd9f4a6f213979a2c1df6b737c49c95d9c3acf22cf40cfdb1f88fb737", + "sha256_in_prefix": "6fd91c3fd9f4a6f213979a2c1df6b737c49c95d9c3acf22cf40cfdb1f88fb737", + "size_in_bytes": 7754 + }, + { + "_path": "lib/python3.12/dataclasses.py", + "path_type": "hardlink", + "sha256": "0e449d55d6206b0022f541ba32be88fafc934ff71d9aa65f31f101ca6147f2ae", + "sha256_in_prefix": "0e449d55d6206b0022f541ba32be88fafc934ff71d9aa65f31f101ca6147f2ae", + "size_in_bytes": 61753 + }, + { + "_path": "lib/python3.12/datetime.py", + "path_type": "hardlink", + "sha256": "ef20dc6b3554cd585dddffdc573f1f9a7a54c522f2a3fb4576c44edbb1e14238", + "sha256_in_prefix": "ef20dc6b3554cd585dddffdc573f1f9a7a54c522f2a3fb4576c44edbb1e14238", + "size_in_bytes": 268 + }, + { + "_path": "lib/python3.12/dbm/__init__.py", + "path_type": "hardlink", + "sha256": "389407b292f30c38a334599d2546ca1fea316b038a5252f985bbccfce6c8453b", + "sha256_in_prefix": "389407b292f30c38a334599d2546ca1fea316b038a5252f985bbccfce6c8453b", + "size_in_bytes": 5882 + }, + { + "_path": "lib/python3.12/dbm/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "90b1ab171077131d2ee116a470fb15e26ed9302f46d49885248e2672f4d9cc0f", + "sha256_in_prefix": "90b1ab171077131d2ee116a470fb15e26ed9302f46d49885248e2672f4d9cc0f", + "size_in_bytes": 6251 + }, + { + "_path": "lib/python3.12/dbm/__pycache__/dumb.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "de7f299696c57bd4ff2ce558224895cb31b6ad1fe93dc34470ef68cb41ad0f0e", + "sha256_in_prefix": "de7f299696c57bd4ff2ce558224895cb31b6ad1fe93dc34470ef68cb41ad0f0e", + "size_in_bytes": 13011 + }, + { + "_path": "lib/python3.12/dbm/__pycache__/gnu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "76dd04f4e1a8b93a5e064dd8595ba440dd6cb0bf94f177b524b8fad209d83a4a", + "sha256_in_prefix": "76dd04f4e1a8b93a5e064dd8595ba440dd6cb0bf94f177b524b8fad209d83a4a", + "size_in_bytes": 211 + }, + { + "_path": "lib/python3.12/dbm/__pycache__/ndbm.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ce168cacdfa3f10d0ef9b53cd3b289225eec0c4d12ea5f7a2be4692cfb5ad4b4", + "sha256_in_prefix": "ce168cacdfa3f10d0ef9b53cd3b289225eec0c4d12ea5f7a2be4692cfb5ad4b4", + "size_in_bytes": 210 + }, + { + "_path": "lib/python3.12/dbm/dumb.py", + "path_type": "hardlink", + "sha256": "c99202d9eb4e25a023715a1b804c886fdb7d9f957730959bb071a57d607443b5", + "sha256_in_prefix": "c99202d9eb4e25a023715a1b804c886fdb7d9f957730959bb071a57d607443b5", + "size_in_bytes": 11594 + }, + { + "_path": "lib/python3.12/dbm/gnu.py", + "path_type": "hardlink", + "sha256": "36cd4904f50e00c4df4ad9d450b3970e150957425f47c00cf979ba73eff49778", + "sha256_in_prefix": "36cd4904f50e00c4df4ad9d450b3970e150957425f47c00cf979ba73eff49778", + "size_in_bytes": 72 + }, + { + "_path": "lib/python3.12/dbm/ndbm.py", + "path_type": "hardlink", + "sha256": "1bcc2d9b2fad1901f3421a174eeecb5b8ccc6763283b87bbe0705b404c71904b", + "sha256_in_prefix": "1bcc2d9b2fad1901f3421a174eeecb5b8ccc6763283b87bbe0705b404c71904b", + "size_in_bytes": 70 + }, + { + "_path": "lib/python3.12/decimal.py", + "path_type": "hardlink", + "sha256": "000c00bad31d126b054c6ec7f3e02b27c0f9a4d579f987d3c4f879cee1bacb81", + "sha256_in_prefix": "000c00bad31d126b054c6ec7f3e02b27c0f9a4d579f987d3c4f879cee1bacb81", + "size_in_bytes": 320 + }, + { + "_path": "lib/python3.12/difflib.py", + "path_type": "hardlink", + "sha256": "0c6afc23568d55b3e9ac914f9c5361e3033e778aa5b58d3cc82835fc5c638679", + "sha256_in_prefix": "0c6afc23568d55b3e9ac914f9c5361e3033e778aa5b58d3cc82835fc5c638679", + "size_in_bytes": 83308 + }, + { + "_path": "lib/python3.12/dis.py", + "path_type": "hardlink", + "sha256": "f6f02f5966fed0b1ce95768dc59d7905c64f60f454d79eed67fbeaa724069031", + "sha256_in_prefix": "f6f02f5966fed0b1ce95768dc59d7905c64f60f454d79eed67fbeaa724069031", + "size_in_bytes": 30209 + }, + { + "_path": "lib/python3.12/doctest.py", + "path_type": "hardlink", + "sha256": "271e595a4fb4e4291bedf697d33aa7efab4468299b9b98c9acb28354fc6229b8", + "sha256_in_prefix": "271e595a4fb4e4291bedf697d33aa7efab4468299b9b98c9acb28354fc6229b8", + "size_in_bytes": 106479 + }, + { + "_path": "lib/python3.12/email/__init__.py", + "path_type": "hardlink", + "sha256": "e4f46e3414c4602c9abb8b404a45e84412fc49dbe38a3d163f9575132dc7c93e", + "sha256_in_prefix": "e4f46e3414c4602c9abb8b404a45e84412fc49dbe38a3d163f9575132dc7c93e", + "size_in_bytes": 1764 + }, + { + "_path": "lib/python3.12/email/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a95fc11de979679d131a5afa4fde3f04d4e5dc3ec6bc03321e2c5cb2cdbabe42", + "sha256_in_prefix": "a95fc11de979679d131a5afa4fde3f04d4e5dc3ec6bc03321e2c5cb2cdbabe42", + "size_in_bytes": 1914 + }, + { + "_path": "lib/python3.12/email/__pycache__/_encoded_words.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "59ab7e008d618f40239cac6d54d4da3e1b1837ee49d6d64f6c11c933185cc292", + "sha256_in_prefix": "59ab7e008d618f40239cac6d54d4da3e1b1837ee49d6d64f6c11c933185cc292", + "size_in_bytes": 8301 + }, + { + "_path": "lib/python3.12/email/__pycache__/_header_value_parser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5a3f1282ddecb420848eca52d1eb123e99983c4e0c3309ae46ae04df6fabc969", + "sha256_in_prefix": "5a3f1282ddecb420848eca52d1eb123e99983c4e0c3309ae46ae04df6fabc969", + "size_in_bytes": 131187 + }, + { + "_path": "lib/python3.12/email/__pycache__/_parseaddr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1a0c00f0afb4c823da8be9daf3297cfe3183d5d70f15e087ecf1d6ce81a7a4df", + "sha256_in_prefix": "1a0c00f0afb4c823da8be9daf3297cfe3183d5d70f15e087ecf1d6ce81a7a4df", + "size_in_bytes": 23260 + }, + { + "_path": "lib/python3.12/email/__pycache__/_policybase.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3181378cbec619c7dfb1466c84be9405af9a49e5e2d22e6c7c24aab7b191c802", + "sha256_in_prefix": "3181378cbec619c7dfb1466c84be9405af9a49e5e2d22e6c7c24aab7b191c802", + "size_in_bytes": 18187 + }, + { + "_path": "lib/python3.12/email/__pycache__/base64mime.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f5bec286611a57579b12b8aa608feaf3e57d68b81eb74288e8d28bb7d9b40aa0", + "sha256_in_prefix": "f5bec286611a57579b12b8aa608feaf3e57d68b81eb74288e8d28bb7d9b40aa0", + "size_in_bytes": 3945 + }, + { + "_path": "lib/python3.12/email/__pycache__/charset.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "809225b9f3c133fdc8233fc3f337fb1f921a4abb0c60662ae9ee8ebc4fae874f", + "sha256_in_prefix": "809225b9f3c133fdc8233fc3f337fb1f921a4abb0c60662ae9ee8ebc4fae874f", + "size_in_bytes": 15243 + }, + { + "_path": "lib/python3.12/email/__pycache__/contentmanager.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fc65bebe125a3c341b588e9fba47df77e722729402476fd59d7a6f0df8ab4210", + "sha256_in_prefix": "fc65bebe125a3c341b588e9fba47df77e722729402476fd59d7a6f0df8ab4210", + "size_in_bytes": 12394 + }, + { + "_path": "lib/python3.12/email/__pycache__/encoders.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "119cdd408a4d2996cec6b4726207b6959b317dca08be6fde1dcc798a0604c281", + "sha256_in_prefix": "119cdd408a4d2996cec6b4726207b6959b317dca08be6fde1dcc798a0604c281", + "size_in_bytes": 2084 + }, + { + "_path": "lib/python3.12/email/__pycache__/errors.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cab60552842e64ac553be2956ea41f1828021aca166b4d4d9412cd49d0d01181", + "sha256_in_prefix": "cab60552842e64ac553be2956ea41f1828021aca166b4d4d9412cd49d0d01181", + "size_in_bytes": 6835 + }, + { + "_path": "lib/python3.12/email/__pycache__/feedparser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4a664258df7b5360f6f6bd8326fafafb42349dc4cbb17dc0f4f2780042c52463", + "sha256_in_prefix": "4a664258df7b5360f6f6bd8326fafafb42349dc4cbb17dc0f4f2780042c52463", + "size_in_bytes": 19843 + }, + { + "_path": "lib/python3.12/email/__pycache__/generator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3a6a8289f3dacb23d0fa490896368ffa8ef6092dcf0d44edcb13c96359cb88c5", + "sha256_in_prefix": "3a6a8289f3dacb23d0fa490896368ffa8ef6092dcf0d44edcb13c96359cb88c5", + "size_in_bytes": 19927 + }, + { + "_path": "lib/python3.12/email/__pycache__/header.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8897bb5a4ec70c152eb852b8ab013326f868fd5bf07fae91bf5096bc209724e2", + "sha256_in_prefix": "8897bb5a4ec70c152eb852b8ab013326f868fd5bf07fae91bf5096bc209724e2", + "size_in_bytes": 24569 + }, + { + "_path": "lib/python3.12/email/__pycache__/headerregistry.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2949e15c0f9600c76bc624a60cf06e939e7be6d03ae42a64cbadc8e20761f37d", + "sha256_in_prefix": "2949e15c0f9600c76bc624a60cf06e939e7be6d03ae42a64cbadc8e20761f37d", + "size_in_bytes": 30954 + }, + { + "_path": "lib/python3.12/email/__pycache__/iterators.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ec1eb00d8b69be15276508604e1bef3f86fe92dd11fdcc872aeb52dca240e259", + "sha256_in_prefix": "ec1eb00d8b69be15276508604e1bef3f86fe92dd11fdcc872aeb52dca240e259", + "size_in_bytes": 2814 + }, + { + "_path": "lib/python3.12/email/__pycache__/message.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a72fbcbf15074064ef9cc3cf343739273859872af72c3d914c290ab17d1c628b", + "sha256_in_prefix": "a72fbcbf15074064ef9cc3cf343739273859872af72c3d914c290ab17d1c628b", + "size_in_bytes": 53029 + }, + { + "_path": "lib/python3.12/email/__pycache__/parser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c64713c1f75d539a39884240ccf662c1f9d2a7fadf9da70b1e36a392b74eed25", + "sha256_in_prefix": "c64713c1f75d539a39884240ccf662c1f9d2a7fadf9da70b1e36a392b74eed25", + "size_in_bytes": 6741 + }, + { + "_path": "lib/python3.12/email/__pycache__/policy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e45dbbc86b5402e155d19608f32664d82c6f87ee7a4866f1796c85ba622a7310", + "sha256_in_prefix": "e45dbbc86b5402e155d19608f32664d82c6f87ee7a4866f1796c85ba622a7310", + "size_in_bytes": 11773 + }, + { + "_path": "lib/python3.12/email/__pycache__/quoprimime.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2078e5fc97b0d27e2327ef604f6ce5d7d51372688185e1fa9e9a79d7299b4932", + "sha256_in_prefix": "2078e5fc97b0d27e2327ef604f6ce5d7d51372688185e1fa9e9a79d7299b4932", + "size_in_bytes": 9963 + }, + { + "_path": "lib/python3.12/email/__pycache__/utils.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ef4ed07804439b72be5aec721204a9e40f94ce0d942f0fffd87e7a129166ab2c", + "sha256_in_prefix": "ef4ed07804439b72be5aec721204a9e40f94ce0d942f0fffd87e7a129166ab2c", + "size_in_bytes": 12750 + }, + { + "_path": "lib/python3.12/email/_encoded_words.py", + "path_type": "hardlink", + "sha256": "4178321600c0a19ca04cfe8542ce44487f339d15d89a473b58cea63c0b230217", + "sha256_in_prefix": "4178321600c0a19ca04cfe8542ce44487f339d15d89a473b58cea63c0b230217", + "size_in_bytes": 8541 + }, + { + "_path": "lib/python3.12/email/_header_value_parser.py", + "path_type": "hardlink", + "sha256": "d0a5c01818b2f63c31038b568134ade0a6ecf263dcd387c02dbe7123858694bd", + "sha256_in_prefix": "d0a5c01818b2f63c31038b568134ade0a6ecf263dcd387c02dbe7123858694bd", + "size_in_bytes": 107257 + }, + { + "_path": "lib/python3.12/email/_parseaddr.py", + "path_type": "hardlink", + "sha256": "4308932872acbf4a674312a45a49b870e48026e3dfedc878ee2f512ddf2f30ba", + "sha256_in_prefix": "4308932872acbf4a674312a45a49b870e48026e3dfedc878ee2f512ddf2f30ba", + "size_in_bytes": 17821 + }, + { + "_path": "lib/python3.12/email/_policybase.py", + "path_type": "hardlink", + "sha256": "967a41672b54f3443eac096968ad189d75c77be7eb42611b4d81d12a41605be9", + "sha256_in_prefix": "967a41672b54f3443eac096968ad189d75c77be7eb42611b4d81d12a41605be9", + "size_in_bytes": 15073 + }, + { + "_path": "lib/python3.12/email/architecture.rst", + "path_type": "hardlink", + "sha256": "f2b2ba7497fd02d13abcfc2a98099283a94b09e8b4f2c1c822ecacde3bec3eae", + "sha256_in_prefix": "f2b2ba7497fd02d13abcfc2a98099283a94b09e8b4f2c1c822ecacde3bec3eae", + "size_in_bytes": 9561 + }, + { + "_path": "lib/python3.12/email/base64mime.py", + "path_type": "hardlink", + "sha256": "e2b4b87a5f42a8c5780e343f675513bbcc6abdd23fa14f8f1a7d4f7d72304770", + "sha256_in_prefix": "e2b4b87a5f42a8c5780e343f675513bbcc6abdd23fa14f8f1a7d4f7d72304770", + "size_in_bytes": 3551 + }, + { + "_path": "lib/python3.12/email/charset.py", + "path_type": "hardlink", + "sha256": "a90653f13a4dc5eb3205079dda1d62561a8bf9a7b45585f5dbf90aa31a966680", + "sha256_in_prefix": "a90653f13a4dc5eb3205079dda1d62561a8bf9a7b45585f5dbf90aa31a966680", + "size_in_bytes": 17063 + }, + { + "_path": "lib/python3.12/email/contentmanager.py", + "path_type": "hardlink", + "sha256": "2d81026aef17e4786b15d9ec0629304987e3f275a0fd0a421a81b4ed87234b2c", + "sha256_in_prefix": "2d81026aef17e4786b15d9ec0629304987e3f275a0fd0a421a81b4ed87234b2c", + "size_in_bytes": 10588 + }, + { + "_path": "lib/python3.12/email/encoders.py", + "path_type": "hardlink", + "sha256": "690b275529788cc48e8f541a2aef321dc31e92f75764ac7924896db72d8a9555", + "sha256_in_prefix": "690b275529788cc48e8f541a2aef321dc31e92f75764ac7924896db72d8a9555", + "size_in_bytes": 1778 + }, + { + "_path": "lib/python3.12/email/errors.py", + "path_type": "hardlink", + "sha256": "33fc889cbff57bb78c913bb6c24c5d52bd02f3cba0f4b1cb2913340294a6ec1a", + "sha256_in_prefix": "33fc889cbff57bb78c913bb6c24c5d52bd02f3cba0f4b1cb2913340294a6ec1a", + "size_in_bytes": 3735 + }, + { + "_path": "lib/python3.12/email/feedparser.py", + "path_type": "hardlink", + "sha256": "6046239fcdd6977d1c25841581cabedaeec8046cc5fedcb8ff2d6450a36442bd", + "sha256_in_prefix": "6046239fcdd6977d1c25841581cabedaeec8046cc5fedcb8ff2d6450a36442bd", + "size_in_bytes": 22796 + }, + { + "_path": "lib/python3.12/email/generator.py", + "path_type": "hardlink", + "sha256": "96b0ef100b03b7d04b71c859923a5e9ee27dd3426a9dcc1b20c17f4e4a97f315", + "sha256_in_prefix": "96b0ef100b03b7d04b71c859923a5e9ee27dd3426a9dcc1b20c17f4e4a97f315", + "size_in_bytes": 20195 + }, + { + "_path": "lib/python3.12/email/header.py", + "path_type": "hardlink", + "sha256": "4d9baa908ad5288dd8fad8cf20b3802ffac77ba1642727804a633b201c56e5ca", + "sha256_in_prefix": "4d9baa908ad5288dd8fad8cf20b3802ffac77ba1642727804a633b201c56e5ca", + "size_in_bytes": 24092 + }, + { + "_path": "lib/python3.12/email/headerregistry.py", + "path_type": "hardlink", + "sha256": "fada56c25b6a457c6a62af43f9f929bbc29424103ce65f40f114adb4fdf3d39f", + "sha256_in_prefix": "fada56c25b6a457c6a62af43f9f929bbc29424103ce65f40f114adb4fdf3d39f", + "size_in_bytes": 20819 + }, + { + "_path": "lib/python3.12/email/iterators.py", + "path_type": "hardlink", + "sha256": "1080a2d03779176d6d45f6ecd976dbe69f5579f7e4e83b75224c3f92fd258102", + "sha256_in_prefix": "1080a2d03779176d6d45f6ecd976dbe69f5579f7e4e83b75224c3f92fd258102", + "size_in_bytes": 2129 + }, + { + "_path": "lib/python3.12/email/message.py", + "path_type": "hardlink", + "sha256": "5dca7305c5218c06527d699e6b526eaf0c34bb6c2dda155d4e7f0815429e677c", + "sha256_in_prefix": "5dca7305c5218c06527d699e6b526eaf0c34bb6c2dda155d4e7f0815429e677c", + "size_in_bytes": 48110 + }, + { + "_path": "lib/python3.12/email/mime/__init__.py", + "path_type": "hardlink", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "sha256_in_prefix": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "size_in_bytes": 0 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "42bb8b67ffd96e8ec923d8a74af60c5c581f6d3305359eae0c9c6b3dfb686279", + "sha256_in_prefix": "42bb8b67ffd96e8ec923d8a74af60c5c581f6d3305359eae0c9c6b3dfb686279", + "size_in_bytes": 134 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/application.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d8f9771fdf10cd57e658c5940e2620531a75450d6102d369ce6d666dc3f943a8", + "sha256_in_prefix": "d8f9771fdf10cd57e658c5940e2620531a75450d6102d369ce6d666dc3f943a8", + "size_in_bytes": 1660 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/audio.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2e3a31774d5273d6d4800e52c46233b8666b36b3dce9e13a768aa08844d06d2f", + "sha256_in_prefix": "2e3a31774d5273d6d4800e52c46233b8666b36b3dce9e13a768aa08844d06d2f", + "size_in_bytes": 3445 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/base.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7cf5e35d587138b88be09111aeb11ade440759645e174ed51eb562dda322bf30", + "sha256_in_prefix": "7cf5e35d587138b88be09111aeb11ade440759645e174ed51eb562dda322bf30", + "size_in_bytes": 1293 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/image.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aff496e1b558a16be1d02786d1f99c76b9d33b618ddfeac3f6e82fea95c86283", + "sha256_in_prefix": "aff496e1b558a16be1d02786d1f99c76b9d33b618ddfeac3f6e82fea95c86283", + "size_in_bytes": 5709 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/message.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "05c06a74be4bd9267e0253db24125bb747cd91b520e1c406f6dc7ba698d56951", + "sha256_in_prefix": "05c06a74be4bd9267e0253db24125bb747cd91b520e1c406f6dc7ba698d56951", + "size_in_bytes": 1557 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/multipart.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a998bf1dcc3a9e433f79690e2ce8552e5c620966b317e2835a8119450cdb762d", + "sha256_in_prefix": "a998bf1dcc3a9e433f79690e2ce8552e5c620966b317e2835a8119450cdb762d", + "size_in_bytes": 1705 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/nonmultipart.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c485b544cca12a685a0b2e5c15babff58c0d5c5293809c649991793eb14793a5", + "sha256_in_prefix": "c485b544cca12a685a0b2e5c15babff58c0d5c5293809c649991793eb14793a5", + "size_in_bytes": 854 + }, + { + "_path": "lib/python3.12/email/mime/__pycache__/text.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2afbeb9712ba4c58f8cc8a3637212689dd171a2b8922b12034c9a2c698ed76cb", + "sha256_in_prefix": "2afbeb9712ba4c58f8cc8a3637212689dd171a2b8922b12034c9a2c698ed76cb", + "size_in_bytes": 1492 + }, + { + "_path": "lib/python3.12/email/mime/application.py", + "path_type": "hardlink", + "sha256": "b82a944ccba03e7e7eec46232e50ffe4ce2c32f4b0e26662e6bde30d533584ae", + "sha256_in_prefix": "b82a944ccba03e7e7eec46232e50ffe4ce2c32f4b0e26662e6bde30d533584ae", + "size_in_bytes": 1321 + }, + { + "_path": "lib/python3.12/email/mime/audio.py", + "path_type": "hardlink", + "sha256": "856263b25a3384a7450a1a0b9869fb897b84f893b2e7147c7e045ae50d132cd3", + "sha256_in_prefix": "856263b25a3384a7450a1a0b9869fb897b84f893b2e7147c7e045ae50d132cd3", + "size_in_bytes": 3094 + }, + { + "_path": "lib/python3.12/email/mime/base.py", + "path_type": "hardlink", + "sha256": "9a7b36653b5657525a0aeeaa72d4a0b09f598e6edc29c139c2dc2612b7d29fb8", + "sha256_in_prefix": "9a7b36653b5657525a0aeeaa72d4a0b09f598e6edc29c139c2dc2612b7d29fb8", + "size_in_bytes": 914 + }, + { + "_path": "lib/python3.12/email/mime/image.py", + "path_type": "hardlink", + "sha256": "460be5b50cfcaab8e72a73f24f14ab062cedf1a40a775b8b0d80c13aed44bb5e", + "sha256_in_prefix": "460be5b50cfcaab8e72a73f24f14ab062cedf1a40a775b8b0d80c13aed44bb5e", + "size_in_bytes": 3726 + }, + { + "_path": "lib/python3.12/email/mime/message.py", + "path_type": "hardlink", + "sha256": "30fccea73b874b5ddaccbd3c64936833749ff039f08d40524c1b0b25b8e8e2b8", + "sha256_in_prefix": "30fccea73b874b5ddaccbd3c64936833749ff039f08d40524c1b0b25b8e8e2b8", + "size_in_bytes": 1315 + }, + { + "_path": "lib/python3.12/email/mime/multipart.py", + "path_type": "hardlink", + "sha256": "8bf2beca6de95d66f12968380a428d3bb0a28a8a6ea2078da521511e1ed80a38", + "sha256_in_prefix": "8bf2beca6de95d66f12968380a428d3bb0a28a8a6ea2078da521511e1ed80a38", + "size_in_bytes": 1619 + }, + { + "_path": "lib/python3.12/email/mime/nonmultipart.py", + "path_type": "hardlink", + "sha256": "4eb9ad32603d66fc9d55aebcc4d3cf759edd9e95a591d38690659afb2e57b050", + "sha256_in_prefix": "4eb9ad32603d66fc9d55aebcc4d3cf759edd9e95a591d38690659afb2e57b050", + "size_in_bytes": 689 + }, + { + "_path": "lib/python3.12/email/mime/text.py", + "path_type": "hardlink", + "sha256": "71c56a41675a36801259c9946f7b7bf838e6c29c453ba8c34d89401f2b972d6c", + "sha256_in_prefix": "71c56a41675a36801259c9946f7b7bf838e6c29c453ba8c34d89401f2b972d6c", + "size_in_bytes": 1394 + }, + { + "_path": "lib/python3.12/email/parser.py", + "path_type": "hardlink", + "sha256": "88890ea9994c55ff7d6c1fd570fece2785f51ed407ee95df4aff946e250bcd66", + "sha256_in_prefix": "88890ea9994c55ff7d6c1fd570fece2785f51ed407ee95df4aff946e250bcd66", + "size_in_bytes": 4975 + }, + { + "_path": "lib/python3.12/email/policy.py", + "path_type": "hardlink", + "sha256": "56a2a90d973c06668f6f113d67f26cf348af10b33eece2a6b812e34da45258d8", + "sha256_in_prefix": "56a2a90d973c06668f6f113d67f26cf348af10b33eece2a6b812e34da45258d8", + "size_in_bytes": 10519 + }, + { + "_path": "lib/python3.12/email/quoprimime.py", + "path_type": "hardlink", + "sha256": "77b454bd3ba3b5e3776be28ae3a0fd8de5d1e50d5b8ee10dd539c37c2bd68082", + "sha256_in_prefix": "77b454bd3ba3b5e3776be28ae3a0fd8de5d1e50d5b8ee10dd539c37c2bd68082", + "size_in_bytes": 9864 + }, + { + "_path": "lib/python3.12/email/utils.py", + "path_type": "hardlink", + "sha256": "b337be3534f81d662c0368e99cca165252f5b865bb1fb00cdef525bb2833e460", + "sha256_in_prefix": "b337be3534f81d662c0368e99cca165252f5b865bb1fb00cdef525bb2833e460", + "size_in_bytes": 12292 + }, + { + "_path": "lib/python3.12/encodings/__init__.py", + "path_type": "hardlink", + "sha256": "78c4744d407690f321565488710b5aaf6486b5afa8d185637aa1e7633ab59cd8", + "sha256_in_prefix": "78c4744d407690f321565488710b5aaf6486b5afa8d185637aa1e7633ab59cd8", + "size_in_bytes": 5884 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c1e7dc3cbf11ee604b776a40faf9e5f5bebef84e8efa1fcc2e8853c104d2ca32", + "sha256_in_prefix": "c1e7dc3cbf11ee604b776a40faf9e5f5bebef84e8efa1fcc2e8853c104d2ca32", + "size_in_bytes": 5785 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/aliases.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d80acde8a65b473dce390751419a5c68e06f3e8c01bf7349a792062578982544", + "sha256_in_prefix": "d80acde8a65b473dce390751419a5c68e06f3e8c01bf7349a792062578982544", + "size_in_bytes": 12403 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/ascii.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "acaf96b60330bb07b40075726f3d8e5b3f1bc122e430f001df727839fef59dfa", + "sha256_in_prefix": "acaf96b60330bb07b40075726f3d8e5b3f1bc122e430f001df727839fef59dfa", + "size_in_bytes": 2510 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/base64_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7a71614e0571394cb3469d52cb1e91775eb66fa3f01608f72d742b1f1c2bf50a", + "sha256_in_prefix": "7a71614e0571394cb3469d52cb1e91775eb66fa3f01608f72d742b1f1c2bf50a", + "size_in_bytes": 2978 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/big5.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9fe003a5f14cfd0395600ad02416bc6060a3c14e4d1fbcfaeb557a563c3ffd2e", + "sha256_in_prefix": "9fe003a5f14cfd0395600ad02416bc6060a3c14e4d1fbcfaeb557a563c3ffd2e", + "size_in_bytes": 1985 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/big5hkscs.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8e836d4e1d82965c8bb98c121fbfd2754aa4e705616a0819e0aa911a93cb73c5", + "sha256_in_prefix": "8e836d4e1d82965c8bb98c121fbfd2754aa4e705616a0819e0aa911a93cb73c5", + "size_in_bytes": 1995 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/bz2_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1da08f5eb0ef6d8f7770c8320ac1fbc7d6e52f118efb4f290fc8e21ebae7e57f", + "sha256_in_prefix": "1da08f5eb0ef6d8f7770c8320ac1fbc7d6e52f118efb4f290fc8e21ebae7e57f", + "size_in_bytes": 4332 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/charmap.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ce14a012833e6a27fed24db1ab32794fcd66d22da3ffcea62ef05176656f2d27", + "sha256_in_prefix": "ce14a012833e6a27fed24db1ab32794fcd66d22da3ffcea62ef05176656f2d27", + "size_in_bytes": 3854 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp037.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b53a5a0b45ed03b090f1281a53ba6132f4fa0f12b3ff91b5d0638f7ce23d5e32", + "sha256_in_prefix": "b53a5a0b45ed03b090f1281a53ba6132f4fa0f12b3ff91b5d0638f7ce23d5e32", + "size_in_bytes": 3102 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1006.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "94dd83cf2152c3527981ee60b96222fbd82ba7bfb95b563cf02c7fe1328a75ba", + "sha256_in_prefix": "94dd83cf2152c3527981ee60b96222fbd82ba7bfb95b563cf02c7fe1328a75ba", + "size_in_bytes": 3178 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1026.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "60f4ba6b237681d07c6742bc73c1ffd94949396102b642b25ef7b65509f5cf88", + "sha256_in_prefix": "60f4ba6b237681d07c6742bc73c1ffd94949396102b642b25ef7b65509f5cf88", + "size_in_bytes": 3106 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1125.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7f5d8777ef76d6a8f18d8c8a0c68339224937444fd3e94d0ec261190566a0552", + "sha256_in_prefix": "7f5d8777ef76d6a8f18d8c8a0c68339224937444fd3e94d0ec261190566a0552", + "size_in_bytes": 13646 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1140.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "283ccfb2c81785924d15afa0235ad172b6341a33f30b5fc593244f08d4cf1584", + "sha256_in_prefix": "283ccfb2c81785924d15afa0235ad172b6341a33f30b5fc593244f08d4cf1584", + "size_in_bytes": 3092 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1250.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "545a9bf404e172b7e52bcc18b505e71e08ef623a733c066d65749967f762a565", + "sha256_in_prefix": "545a9bf404e172b7e52bcc18b505e71e08ef623a733c066d65749967f762a565", + "size_in_bytes": 3129 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1251.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ef5970e1393768c2fde6cc26c82f0ad4aa94323fa305a92555c1bb13731bccd9", + "sha256_in_prefix": "ef5970e1393768c2fde6cc26c82f0ad4aa94323fa305a92555c1bb13731bccd9", + "size_in_bytes": 3126 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1252.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b32874ba248863b4da117652a4f358af1257096a578ec53e10f29701066cbc7", + "sha256_in_prefix": "5b32874ba248863b4da117652a4f358af1257096a578ec53e10f29701066cbc7", + "size_in_bytes": 3129 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1253.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8e0d4ae6e204db83e6db0bb4285b2ad1854ab8c7032a527c6f9bceb9a0c0d130", + "sha256_in_prefix": "8e0d4ae6e204db83e6db0bb4285b2ad1854ab8c7032a527c6f9bceb9a0c0d130", + "size_in_bytes": 3142 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1254.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2fe5dc036497974638f0efecba8c9ecdeae0d8d9eb1cfd3fd1bbcfa0567558d9", + "sha256_in_prefix": "2fe5dc036497974638f0efecba8c9ecdeae0d8d9eb1cfd3fd1bbcfa0567558d9", + "size_in_bytes": 3131 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1255.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "41e8c9fddfed66a9be6ce771827c62ac44ad97d5ca9f6b9049c3004cfc5d9a05", + "sha256_in_prefix": "41e8c9fddfed66a9be6ce771827c62ac44ad97d5ca9f6b9049c3004cfc5d9a05", + "size_in_bytes": 3150 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1256.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aa2963f91163161389c306050e737519c133e8cc46725af1e42f07cdec7b7505", + "sha256_in_prefix": "aa2963f91163161389c306050e737519c133e8cc46725af1e42f07cdec7b7505", + "size_in_bytes": 3128 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1257.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8be0ef91d80aa2d8a4c40d603f21867c49b416d19a13f25fbf67b22fd2e64aa1", + "sha256_in_prefix": "8be0ef91d80aa2d8a4c40d603f21867c49b416d19a13f25fbf67b22fd2e64aa1", + "size_in_bytes": 3136 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp1258.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e55506f3f1bab8c68d548fc2ce3a4fa28acab551e2f4a4774cbbf7c22dfa45bf", + "sha256_in_prefix": "e55506f3f1bab8c68d548fc2ce3a4fa28acab551e2f4a4774cbbf7c22dfa45bf", + "size_in_bytes": 3134 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp273.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "27acc7f963fb5788bd95a17ded20179b6cf66a09cee223003ccc20d8fc584e28", + "sha256_in_prefix": "27acc7f963fb5788bd95a17ded20179b6cf66a09cee223003ccc20d8fc584e28", + "size_in_bytes": 3088 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp424.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f2ec78bf35efa008ef5edb867d153707a228e2e1ee959342cbbe699234ddb5e1", + "sha256_in_prefix": "f2ec78bf35efa008ef5edb867d153707a228e2e1ee959342cbbe699234ddb5e1", + "size_in_bytes": 3132 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp437.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "21f51b22b7bfcb75d9031c47818e62d143073b7d957b0461df31c4929faaa860", + "sha256_in_prefix": "21f51b22b7bfcb75d9031c47818e62d143073b7d957b0461df31c4929faaa860", + "size_in_bytes": 13279 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp500.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f03db4d33ab9fd2de222a0968cef41ac2f606ea433dae3faf313ffbfd3df58a1", + "sha256_in_prefix": "f03db4d33ab9fd2de222a0968cef41ac2f606ea433dae3faf313ffbfd3df58a1", + "size_in_bytes": 3102 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp720.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f7f87c1d886c8dae9a5f2312fe9c0a2503a7cbe820628a29de45850e4bf1a50a", + "sha256_in_prefix": "f7f87c1d886c8dae9a5f2312fe9c0a2503a7cbe820628a29de45850e4bf1a50a", + "size_in_bytes": 3199 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp737.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a70a44aeb46636a2290a4068ab66e86f5a18cd89b2b53a0ef97cbbce8c68648e", + "sha256_in_prefix": "a70a44aeb46636a2290a4068ab66e86f5a18cd89b2b53a0ef97cbbce8c68648e", + "size_in_bytes": 13681 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp775.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e054cdcfaaf0aeaabbe70e7c6f6971967ab29ef9c4718f27960a0c846434f43a", + "sha256_in_prefix": "e054cdcfaaf0aeaabbe70e7c6f6971967ab29ef9c4718f27960a0c846434f43a", + "size_in_bytes": 13319 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp850.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a5ce162e5e2b1ff5e2140e3100c29aaa01642a6f7927d71c310de087189a2162", + "sha256_in_prefix": "a5ce162e5e2b1ff5e2140e3100c29aaa01642a6f7927d71c310de087189a2162", + "size_in_bytes": 12860 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp852.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e204cbd1cce4c255fe0fe7579e74add964197b30314325d14fe32f5765ad1bfd", + "sha256_in_prefix": "e204cbd1cce4c255fe0fe7579e74add964197b30314325d14fe32f5765ad1bfd", + "size_in_bytes": 13335 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp855.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "acfb460f8a33ae3b10dfc2f48d70d53d822f799f20e515bb3e25ccc1ba0dbcc5", + "sha256_in_prefix": "acfb460f8a33ae3b10dfc2f48d70d53d822f799f20e515bb3e25ccc1ba0dbcc5", + "size_in_bytes": 13648 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp856.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4592977d62d7bd17d2cd74ed240072dae27122c3e466ab9cded6d4f875814105", + "sha256_in_prefix": "4592977d62d7bd17d2cd74ed240072dae27122c3e466ab9cded6d4f875814105", + "size_in_bytes": 3164 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp857.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bc1bc473aded5cf7da317ff4faac2be4017b15cf2c8d7cf5615f4f12c0ef76fd", + "sha256_in_prefix": "bc1bc473aded5cf7da317ff4faac2be4017b15cf2c8d7cf5615f4f12c0ef76fd", + "size_in_bytes": 12661 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp858.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b0f5bb1bccbb689e6626efa1e609aecab07d16a4c21a244a5f4358b8c5a5508", + "sha256_in_prefix": "5b0f5bb1bccbb689e6626efa1e609aecab07d16a4c21a244a5f4358b8c5a5508", + "size_in_bytes": 12830 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp860.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c04c7962ad810a1bf3ea52dd43bf0e03beb16dd8afa8a94b93bdc382b94c76b5", + "sha256_in_prefix": "c04c7962ad810a1bf3ea52dd43bf0e03beb16dd8afa8a94b93bdc382b94c76b5", + "size_in_bytes": 13250 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp861.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2565b07b6baac7c4ba096fc13eda79e718b29f67c7bf1c3f5c50aa43607727c5", + "sha256_in_prefix": "2565b07b6baac7c4ba096fc13eda79e718b29f67c7bf1c3f5c50aa43607727c5", + "size_in_bytes": 13275 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp862.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "78223fa7881f4f17fdd17a9606553c78cdf5f40045d481fce775a038f765affd", + "sha256_in_prefix": "78223fa7881f4f17fdd17a9606553c78cdf5f40045d481fce775a038f765affd", + "size_in_bytes": 13508 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp863.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4a79bbdc0216ce44fc67215a7e3b81235a311379d6f957c24e76dfe27be94df3", + "sha256_in_prefix": "4a79bbdc0216ce44fc67215a7e3b81235a311379d6f957c24e76dfe27be94df3", + "size_in_bytes": 13271 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp864.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "67a7e95a79515c63bfd2827d4ef18ccdce03a7a0add32783b1712e420b3f24ae", + "sha256_in_prefix": "67a7e95a79515c63bfd2827d4ef18ccdce03a7a0add32783b1712e420b3f24ae", + "size_in_bytes": 13316 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp865.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7aa8bd64e1f96318751f74d012ea53c65a0b349216cf3211c5dfbed0fadd6e2d", + "sha256_in_prefix": "7aa8bd64e1f96318751f74d012ea53c65a0b349216cf3211c5dfbed0fadd6e2d", + "size_in_bytes": 13275 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp866.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e299aebe474e56de04213d3e77a49568f3e5a93458b81544871e30a865cd097c", + "sha256_in_prefix": "e299aebe474e56de04213d3e77a49568f3e5a93458b81544871e30a865cd097c", + "size_in_bytes": 13688 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp869.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "666df9c30a341f89a0ca04d38cca6c2453ee5fd592a156b5cd85b71c74488b14", + "sha256_in_prefix": "666df9c30a341f89a0ca04d38cca6c2453ee5fd592a156b5cd85b71c74488b14", + "size_in_bytes": 13218 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp874.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "dca3e7429b443ca21903d1efb173970d9457ac81b1096c05f4326c29fccdf7cf", + "sha256_in_prefix": "dca3e7429b443ca21903d1efb173970d9457ac81b1096c05f4326c29fccdf7cf", + "size_in_bytes": 3230 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp875.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4fcb985ae6d045212a2b63924f4d86fd4f33ec5a274c159ab700335f0942a0c1", + "sha256_in_prefix": "4fcb985ae6d045212a2b63924f4d86fd4f33ec5a274c159ab700335f0942a0c1", + "size_in_bytes": 3099 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp932.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2ba8b70121a0ac2884389b0c9c8287b938c82f70ff20285740f6d5cbcc197c12", + "sha256_in_prefix": "2ba8b70121a0ac2884389b0c9c8287b938c82f70ff20285740f6d5cbcc197c12", + "size_in_bytes": 1987 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp949.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aa464b2922e1b97f4f99a0124db88696517a32ee0ac863a6f3ceda6238ad21e2", + "sha256_in_prefix": "aa464b2922e1b97f4f99a0124db88696517a32ee0ac863a6f3ceda6238ad21e2", + "size_in_bytes": 1987 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/cp950.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "670eb4ba7c985cf9fec3b49b55aaee9e3487e366e3cab9f8abe85d6113494614", + "sha256_in_prefix": "670eb4ba7c985cf9fec3b49b55aaee9e3487e366e3cab9f8abe85d6113494614", + "size_in_bytes": 1987 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/euc_jis_2004.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a9660b9b787d5488bd36f0c32b6c44ce44863cb220a294033f94988551b5962e", + "sha256_in_prefix": "a9660b9b787d5488bd36f0c32b6c44ce44863cb220a294033f94988551b5962e", + "size_in_bytes": 2001 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/euc_jisx0213.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "53a0d9df0d5d388c5752e5485794b99f2d41b70b885ef9d6fd0436ac0a217f6a", + "sha256_in_prefix": "53a0d9df0d5d388c5752e5485794b99f2d41b70b885ef9d6fd0436ac0a217f6a", + "size_in_bytes": 2001 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/euc_jp.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1c43fb230392309e4f1dbe2c6061745abcad8815758a5db2e0e4673c9d517fd3", + "sha256_in_prefix": "1c43fb230392309e4f1dbe2c6061745abcad8815758a5db2e0e4673c9d517fd3", + "size_in_bytes": 1989 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/euc_kr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8475be34d17319d485d1485a3c67c7894ae76698830b8d9dcbcec4e60ff6de1d", + "sha256_in_prefix": "8475be34d17319d485d1485a3c67c7894ae76698830b8d9dcbcec4e60ff6de1d", + "size_in_bytes": 1989 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/gb18030.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8797d18380cf53b7d8064675796151c64b23a6ed0c429aa6e2cf4bb386ee57b2", + "sha256_in_prefix": "8797d18380cf53b7d8064675796151c64b23a6ed0c429aa6e2cf4bb386ee57b2", + "size_in_bytes": 1991 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/gb2312.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "03229f0c7a3576574b88eef02d724dcee5a58a361427b23f5b9d0a524bb27deb", + "sha256_in_prefix": "03229f0c7a3576574b88eef02d724dcee5a58a361427b23f5b9d0a524bb27deb", + "size_in_bytes": 1989 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/gbk.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1801437080c0c55b69dba9709127feb39fce7f5bc1bb795eff7fb95611650f19", + "sha256_in_prefix": "1801437080c0c55b69dba9709127feb39fce7f5bc1bb795eff7fb95611650f19", + "size_in_bytes": 1983 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/hex_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ce8492dc9bae67b96f9188000e40abca1387f3dd42521aa2b11ca99d25ed348b", + "sha256_in_prefix": "ce8492dc9bae67b96f9188000e40abca1387f3dd42521aa2b11ca99d25ed348b", + "size_in_bytes": 2965 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/hp_roman8.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cab997052d49381d81115d4e096cb4a5b57eb0249d360bf17bc334d889b2e8a7", + "sha256_in_prefix": "cab997052d49381d81115d4e096cb4a5b57eb0249d360bf17bc334d889b2e8a7", + "size_in_bytes": 3303 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/hz.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f434050c1ea167c9be1e2448897df63dc5943b8e6384f5e9f8892e85a908057d", + "sha256_in_prefix": "f434050c1ea167c9be1e2448897df63dc5943b8e6384f5e9f8892e85a908057d", + "size_in_bytes": 1981 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/idna.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "54a6756037b0c4072b26f5d83c11f4fb022beed521caddbb3d8dfb185eea01b2", + "sha256_in_prefix": "54a6756037b0c4072b26f5d83c11f4fb022beed521caddbb3d8dfb185eea01b2", + "size_in_bytes": 9911 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b12fd52ab8ba1e3f50d5dd3334e045c72d8a49733f14b11798a8c43ccf0ccd4c", + "sha256_in_prefix": "b12fd52ab8ba1e3f50d5dd3334e045c72d8a49733f14b11798a8c43ccf0ccd4c", + "size_in_bytes": 2002 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp_1.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ef656f540e4cd5a2dead7bc857f3d52d62fdba5c91c3096b3c9e68c4a836bbde", + "sha256_in_prefix": "ef656f540e4cd5a2dead7bc857f3d52d62fdba5c91c3096b3c9e68c4a836bbde", + "size_in_bytes": 2006 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp_2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ca04dd763c4cc292e480926d772c10c488efcabc0b981a1ab2ef474d33282e1a", + "sha256_in_prefix": "ca04dd763c4cc292e480926d772c10c488efcabc0b981a1ab2ef474d33282e1a", + "size_in_bytes": 2006 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp_2004.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9fcdfb96726277947a59f5cb1a5cf401d2eb5fd4eadb05696353da961e9503f8", + "sha256_in_prefix": "9fcdfb96726277947a59f5cb1a5cf401d2eb5fd4eadb05696353da961e9503f8", + "size_in_bytes": 2013 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp_3.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "be71efd5e3225a09b4d1d4055c26bd4c0b808921ce3a3e37c1a39226d974ca15", + "sha256_in_prefix": "be71efd5e3225a09b4d1d4055c26bd4c0b808921ce3a3e37c1a39226d974ca15", + "size_in_bytes": 2006 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_jp_ext.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3b91ca035e7719a023aaea31444bba4cadf19b7dad76ade5447864a34c319130", + "sha256_in_prefix": "3b91ca035e7719a023aaea31444bba4cadf19b7dad76ade5447864a34c319130", + "size_in_bytes": 2011 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso2022_kr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "78a067660ef35e1a3bab93e97d410f5a48c8526094326b348c738ac8500ce1a9", + "sha256_in_prefix": "78a067660ef35e1a3bab93e97d410f5a48c8526094326b348c738ac8500ce1a9", + "size_in_bytes": 2002 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_1.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fae1718f7554162a069673fe496c35bbacb17652908d235f662458083f2f8e8d", + "sha256_in_prefix": "fae1718f7554162a069673fe496c35bbacb17652908d235f662458083f2f8e8d", + "size_in_bytes": 3101 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_10.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8dea818a459b4cba7fdac06b09f0389b62d9704608d1a6dd51871eb35d68db5c", + "sha256_in_prefix": "8dea818a459b4cba7fdac06b09f0389b62d9704608d1a6dd51871eb35d68db5c", + "size_in_bytes": 3106 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_11.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2037bf5bad84ab18042cadeea0c4a1783aaec77ca12efc458ef3a479802025b4", + "sha256_in_prefix": "2037bf5bad84ab18042cadeea0c4a1783aaec77ca12efc458ef3a479802025b4", + "size_in_bytes": 3200 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_13.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "69e3591cc96b525be0a00b971d0b77180838b1648ebab7c73b80cd5a4f261c9d", + "sha256_in_prefix": "69e3591cc96b525be0a00b971d0b77180838b1648ebab7c73b80cd5a4f261c9d", + "size_in_bytes": 3109 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_14.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a2413a41b21dfc9e7b6ddca0264b9a7fd4e0101f2d216d2e535da299c9f6087e", + "sha256_in_prefix": "a2413a41b21dfc9e7b6ddca0264b9a7fd4e0101f2d216d2e535da299c9f6087e", + "size_in_bytes": 3127 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_15.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "21932ea2f80feb9f0c00e81589869e2fcec3ec76a935ac40f6a1a334b4e2e987", + "sha256_in_prefix": "21932ea2f80feb9f0c00e81589869e2fcec3ec76a935ac40f6a1a334b4e2e987", + "size_in_bytes": 3106 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_16.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fc97ab617e83327cc220bd6eecb482bbb8de74e73522c4ba8a819bb991230a69", + "sha256_in_prefix": "fc97ab617e83327cc220bd6eecb482bbb8de74e73522c4ba8a819bb991230a69", + "size_in_bytes": 3108 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9b07c6824b3518f33354e0a2da60c303b36595cac1e85c3611bf21739a336e80", + "sha256_in_prefix": "9b07c6824b3518f33354e0a2da60c303b36595cac1e85c3611bf21739a336e80", + "size_in_bytes": 3101 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_3.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "21106d22cff25e8cf81aab1dff90eead0370af38cf0c1a213f0eafc2d1b12efa", + "sha256_in_prefix": "21106d22cff25e8cf81aab1dff90eead0370af38cf0c1a213f0eafc2d1b12efa", + "size_in_bytes": 3108 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_4.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "483803187bb6698f739587963ed51445e6777ab42bb5896592a7e8985194d30e", + "sha256_in_prefix": "483803187bb6698f739587963ed51445e6777ab42bb5896592a7e8985194d30e", + "size_in_bytes": 3101 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_5.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f4ee32736543590d792399ef00bc6f0e0dbffd959bae4db6bf647a82d4369be7", + "sha256_in_prefix": "f4ee32736543590d792399ef00bc6f0e0dbffd959bae4db6bf647a82d4369be7", + "size_in_bytes": 3102 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_6.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "988832c8f021f6438942e5d365777629cf3f21939205a8624e8d44e4c68ed972", + "sha256_in_prefix": "988832c8f021f6438942e5d365777629cf3f21939205a8624e8d44e4c68ed972", + "size_in_bytes": 3146 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_7.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a650cf8e47b177440cc4c1ec50f6d3e16fd09614f387ba46ad118f06ed14e205", + "sha256_in_prefix": "a650cf8e47b177440cc4c1ec50f6d3e16fd09614f387ba46ad118f06ed14e205", + "size_in_bytes": 3109 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_8.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3647e194d3750e13ba48ca3fcd932542fb2c2abbed1bf1f9cb762a9c2a8ccd7a", + "sha256_in_prefix": "3647e194d3750e13ba48ca3fcd932542fb2c2abbed1bf1f9cb762a9c2a8ccd7a", + "size_in_bytes": 3140 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/iso8859_9.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "98d00f8b6a1919776954dd30d723b6615106cd164b5ecd3df4977410555613be", + "sha256_in_prefix": "98d00f8b6a1919776954dd30d723b6615106cd164b5ecd3df4977410555613be", + "size_in_bytes": 3101 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/johab.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cddb34c1519d4316896eb987d97582fe26ca0c4a92b7d083b8a1060f93ef8e67", + "sha256_in_prefix": "cddb34c1519d4316896eb987d97582fe26ca0c4a92b7d083b8a1060f93ef8e67", + "size_in_bytes": 1987 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/koi8_r.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "54fa48996e260baa27b2c1dea9219da01b3fd5643cc2361826ee0be9b85f3631", + "sha256_in_prefix": "54fa48996e260baa27b2c1dea9219da01b3fd5643cc2361826ee0be9b85f3631", + "size_in_bytes": 3153 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/koi8_t.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c4cbacc633081a7b7931dca46d71c0f490a63c9320474259ec121c0acad9e3f0", + "sha256_in_prefix": "c4cbacc633081a7b7931dca46d71c0f490a63c9320474259ec121c0acad9e3f0", + "size_in_bytes": 3064 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/koi8_u.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "18403c1dd98c6187e6910a935fb703d41b0baed687bd9101635e06f7a45516cc", + "sha256_in_prefix": "18403c1dd98c6187e6910a935fb703d41b0baed687bd9101635e06f7a45516cc", + "size_in_bytes": 3139 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/kz1048.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cb028cbf2b33cefbd5092b430b1f6b1971e6e3df41bb34f7d3fa4cdc6ad79184", + "sha256_in_prefix": "cb028cbf2b33cefbd5092b430b1f6b1971e6e3df41bb34f7d3fa4cdc6ad79184", + "size_in_bytes": 3116 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/latin_1.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0e582987438cacecb23980ff4a7751c0b4f3e4af86a380409ac1101ae90ffa78", + "sha256_in_prefix": "0e582987438cacecb23980ff4a7751c0b4f3e4af86a380409ac1101ae90ffa78", + "size_in_bytes": 2522 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_arabic.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7cdfd672deea1c1bdd5e096988873a11c58313ce2d29ada949b14bdf829be871", + "sha256_in_prefix": "7cdfd672deea1c1bdd5e096988873a11c58313ce2d29ada949b14bdf829be871", + "size_in_bytes": 13165 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_croatian.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3c2276ff76005a576cc11954871176eaf11260f8736b72ffd12f26986d2ca65e", + "sha256_in_prefix": "3c2276ff76005a576cc11954871176eaf11260f8736b72ffd12f26986d2ca65e", + "size_in_bytes": 3148 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_cyrillic.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "83b403df27249ced526d02356a53eb9cb30779587a7bd300b32ce7742b42d849", + "sha256_in_prefix": "83b403df27249ced526d02356a53eb9cb30779587a7bd300b32ce7742b42d849", + "size_in_bytes": 3138 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_farsi.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a8102bb60c9b1dfd740b834add234e016d9350a1ea909a4d4aa69cc8bd44048c", + "sha256_in_prefix": "a8102bb60c9b1dfd740b834add234e016d9350a1ea909a4d4aa69cc8bd44048c", + "size_in_bytes": 3082 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_greek.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "51f5c7646c85295b718edf1f7218ffa049c7a8e4c90ea1b012a714fd21926566", + "sha256_in_prefix": "51f5c7646c85295b718edf1f7218ffa049c7a8e4c90ea1b012a714fd21926566", + "size_in_bytes": 3122 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_iceland.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4cf9ae5069757c66343b4c090d02e550c5bcb3af7b1a00fc804edbaeedf092a0", + "sha256_in_prefix": "4cf9ae5069757c66343b4c090d02e550c5bcb3af7b1a00fc804edbaeedf092a0", + "size_in_bytes": 3141 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_latin2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aba562d6cdd6240151cb359e42e70d1e1c3727227fc5cc61ac21b975574bcf29", + "sha256_in_prefix": "aba562d6cdd6240151cb359e42e70d1e1c3727227fc5cc61ac21b975574bcf29", + "size_in_bytes": 3282 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_roman.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0d3e22fa961b889aa0d786f3240254955f57df440c537a4fc19ef5d98b16935b", + "sha256_in_prefix": "0d3e22fa961b889aa0d786f3240254955f57df440c537a4fc19ef5d98b16935b", + "size_in_bytes": 3139 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_romanian.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d27e5e48c253467ef57c8c945d683b03e95048c862cae4c86381390353f6049e", + "sha256_in_prefix": "d27e5e48c253467ef57c8c945d683b03e95048c862cae4c86381390353f6049e", + "size_in_bytes": 3149 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mac_turkish.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "61465a130eea5ced988e9b5f329c6d8beff77fdce0c4cd52d8e1f53e3ec89b35", + "sha256_in_prefix": "61465a130eea5ced988e9b5f329c6d8beff77fdce0c4cd52d8e1f53e3ec89b35", + "size_in_bytes": 3142 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/mbcs.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2d873c02f27f955aff5e6c6d31df72bfa8ded4800cbab8e8a80b51e60872e325", + "sha256_in_prefix": "2d873c02f27f955aff5e6c6d31df72bfa8ded4800cbab8e8a80b51e60872e325", + "size_in_bytes": 2086 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/oem.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6fb63d6ff7e9d4b6dfaba84b49c5976d1d5c391809d04781919d76f71e85b455", + "sha256_in_prefix": "6fb63d6ff7e9d4b6dfaba84b49c5976d1d5c391809d04781919d76f71e85b455", + "size_in_bytes": 1899 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/palmos.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fd84da5e53bb9bff4fb0bb25130e70d2c02180d6ed30e7dd775fa28665c33f82", + "sha256_in_prefix": "fd84da5e53bb9bff4fb0bb25130e70d2c02180d6ed30e7dd775fa28665c33f82", + "size_in_bytes": 3129 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/ptcp154.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da5cfa4eca171cecab404a3c64504a67152b2d475bd914c05a23f509eb229efa", + "sha256_in_prefix": "da5cfa4eca171cecab404a3c64504a67152b2d475bd914c05a23f509eb229efa", + "size_in_bytes": 3223 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/punycode.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e6cabfb245b93d440ebd2363b6c8340060b9cbcb5eac58aff59fa6298d9d6184", + "sha256_in_prefix": "e6cabfb245b93d440ebd2363b6c8340060b9cbcb5eac58aff59fa6298d9d6184", + "size_in_bytes": 9420 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/quopri_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2c56e97b8ef27f2091a7e1fb48dbf32ed25ef9c257a878bc298af35e78287736", + "sha256_in_prefix": "2c56e97b8ef27f2091a7e1fb48dbf32ed25ef9c257a878bc298af35e78287736", + "size_in_bytes": 3150 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/raw_unicode_escape.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5125a7fc39ac6a2dd1d2af235fa762f5093d5eb3deed8be7c31d9e82055b9e3b", + "sha256_in_prefix": "5125a7fc39ac6a2dd1d2af235fa762f5093d5eb3deed8be7c31d9e82055b9e3b", + "size_in_bytes": 2577 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/rot_13.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ca9fac3db9fb1c0618fd4491f168187238a8e057c5bbda847e61d1f9ae08732a", + "sha256_in_prefix": "ca9fac3db9fb1c0618fd4491f168187238a8e057c5bbda847e61d1f9ae08732a", + "size_in_bytes": 4397 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/shift_jis.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5efc307c0fa05026a604e4285571f77a9d63f34a39d8c6f337689b587e4bac4d", + "sha256_in_prefix": "5efc307c0fa05026a604e4285571f77a9d63f34a39d8c6f337689b587e4bac4d", + "size_in_bytes": 1995 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/shift_jis_2004.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "10fa0a171dbef1763ad37b7220e731ccc359327a3600e08d4e9f965ad3bfea3c", + "sha256_in_prefix": "10fa0a171dbef1763ad37b7220e731ccc359327a3600e08d4e9f965ad3bfea3c", + "size_in_bytes": 2006 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/shift_jisx0213.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c8b9f00ecb39f4cc9db596902debed3a7529cff9eff1d794040e0fab75de2dfd", + "sha256_in_prefix": "c8b9f00ecb39f4cc9db596902debed3a7529cff9eff1d794040e0fab75de2dfd", + "size_in_bytes": 2006 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/tis_620.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "174a0e42717e29867ff571a3551c926e7332dfad0afea265fb762d7317072550", + "sha256_in_prefix": "174a0e42717e29867ff571a3551c926e7332dfad0afea265fb762d7317072550", + "size_in_bytes": 3191 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/undefined.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6064d0269d8e9b9608828b897ccc33eff789532d33950fdf7069f6c2372c7476", + "sha256_in_prefix": "6064d0269d8e9b9608828b897ccc33eff789532d33950fdf7069f6c2372c7476", + "size_in_bytes": 2517 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/unicode_escape.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3d1bdfe815c14c4dc21b652348b693c8867319d9191e19155d3225dbb287c65a", + "sha256_in_prefix": "3d1bdfe815c14c4dc21b652348b693c8867319d9191e19155d3225dbb287c65a", + "size_in_bytes": 2557 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_16.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5927b01188c286b474bce6da7c2ead9349607d00fa75415d462efa0cf466f432", + "sha256_in_prefix": "5927b01188c286b474bce6da7c2ead9349607d00fa75415d462efa0cf466f432", + "size_in_bytes": 7777 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_16_be.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5393cba0987cfcf42eccd552d0aad1c19d2d4df13043a6a598dec4cd974095b5", + "sha256_in_prefix": "5393cba0987cfcf42eccd552d0aad1c19d2d4df13043a6a598dec4cd974095b5", + "size_in_bytes": 2162 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_16_le.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bdaf6982b633a1e96eda2e2327a84fa365d3f587bd7e1d18d24e7e7742e8277e", + "sha256_in_prefix": "bdaf6982b633a1e96eda2e2327a84fa365d3f587bd7e1d18d24e7e7742e8277e", + "size_in_bytes": 2162 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_32.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cc0f9cb1f5c18bdf85ca746725c6113e6e55bfaa95df3ca773dec3bebb61caf3", + "sha256_in_prefix": "cc0f9cb1f5c18bdf85ca746725c6113e6e55bfaa95df3ca773dec3bebb61caf3", + "size_in_bytes": 7670 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_32_be.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5767c50bdb0ce03acdaf5a36477bb2fea7df81c57e3c348e5489294122acbf22", + "sha256_in_prefix": "5767c50bdb0ce03acdaf5a36477bb2fea7df81c57e3c348e5489294122acbf22", + "size_in_bytes": 2055 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_32_le.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ea4e0df115bbc514023f7956356e54f266e23c14e9533e595ac31146b27c90cd", + "sha256_in_prefix": "ea4e0df115bbc514023f7956356e54f266e23c14e9533e595ac31146b27c90cd", + "size_in_bytes": 2055 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_7.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "30223a44077cc13a7b880a406e0f5314d0e97ff481d7d53a6995e913a1f2141a", + "sha256_in_prefix": "30223a44077cc13a7b880a406e0f5314d0e97ff481d7d53a6995e913a1f2141a", + "size_in_bytes": 2083 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_8.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0ad396f6de152ebbe461377b6821b29a5f3e0edfbff73d1c7b8e2514b688122e", + "sha256_in_prefix": "0ad396f6de152ebbe461377b6821b29a5f3e0edfbff73d1c7b8e2514b688122e", + "size_in_bytes": 2142 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/utf_8_sig.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3f1fcaddfb158c385a056902c0d14b8e9396e8db0b2cf3f64805b177125e4e7a", + "sha256_in_prefix": "3f1fcaddfb158c385a056902c0d14b8e9396e8db0b2cf3f64805b177125e4e7a", + "size_in_bytes": 6740 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/uu_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "014185e820360f1973fd14e1adb66aae8f328e4b4932b20da3f90b31215d15ba", + "sha256_in_prefix": "014185e820360f1973fd14e1adb66aae8f328e4b4932b20da3f90b31215d15ba", + "size_in_bytes": 4616 + }, + { + "_path": "lib/python3.12/encodings/__pycache__/zlib_codec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c8ac1017746d781c3509f5758b06f702e9345ec262055b4a28dab6eaf5b13f33", + "sha256_in_prefix": "c8ac1017746d781c3509f5758b06f702e9345ec262055b4a28dab6eaf5b13f33", + "size_in_bytes": 4248 + }, + { + "_path": "lib/python3.12/encodings/aliases.py", + "path_type": "hardlink", + "sha256": "6fdcc49ba23a0203ae6cf28e608f8e6297d7c4d77d52e651db3cb49b9564c6d2", + "sha256_in_prefix": "6fdcc49ba23a0203ae6cf28e608f8e6297d7c4d77d52e651db3cb49b9564c6d2", + "size_in_bytes": 15677 + }, + { + "_path": "lib/python3.12/encodings/ascii.py", + "path_type": "hardlink", + "sha256": "578aa1173f7cc60dad2895071287fe6182bd14787b3fbf47a6c7983dfe3675e3", + "sha256_in_prefix": "578aa1173f7cc60dad2895071287fe6182bd14787b3fbf47a6c7983dfe3675e3", + "size_in_bytes": 1248 + }, + { + "_path": "lib/python3.12/encodings/base64_codec.py", + "path_type": "hardlink", + "sha256": "cf9ac7a464f541492486241d1b4bf33e37b45c6499275cc4d69c5a8e564e5976", + "sha256_in_prefix": "cf9ac7a464f541492486241d1b4bf33e37b45c6499275cc4d69c5a8e564e5976", + "size_in_bytes": 1533 + }, + { + "_path": "lib/python3.12/encodings/big5.py", + "path_type": "hardlink", + "sha256": "98fac6f86a20dd05da197e2058176ebfd47edee7074c3248f5f48fe0fb672d7c", + "sha256_in_prefix": "98fac6f86a20dd05da197e2058176ebfd47edee7074c3248f5f48fe0fb672d7c", + "size_in_bytes": 1019 + }, + { + "_path": "lib/python3.12/encodings/big5hkscs.py", + "path_type": "hardlink", + "sha256": "21d051a00fb5c6a86ba187e0c50e811d659ce00991fd5f5b408f71ebb2ef0f16", + "sha256_in_prefix": "21d051a00fb5c6a86ba187e0c50e811d659ce00991fd5f5b408f71ebb2ef0f16", + "size_in_bytes": 1039 + }, + { + "_path": "lib/python3.12/encodings/bz2_codec.py", + "path_type": "hardlink", + "sha256": "1181a2a89102a2b1d2b2f1f4473236d5d1ececdd0be8fdaa498a3dbe21a185ab", + "sha256_in_prefix": "1181a2a89102a2b1d2b2f1f4473236d5d1ececdd0be8fdaa498a3dbe21a185ab", + "size_in_bytes": 2249 + }, + { + "_path": "lib/python3.12/encodings/charmap.py", + "path_type": "hardlink", + "sha256": "1b8b5fdb36ce3becc62a6115ed904a17083949ec8aaef5a80f7078cec232f43b", + "sha256_in_prefix": "1b8b5fdb36ce3becc62a6115ed904a17083949ec8aaef5a80f7078cec232f43b", + "size_in_bytes": 2084 + }, + { + "_path": "lib/python3.12/encodings/cp037.py", + "path_type": "hardlink", + "sha256": "fda6ca994d710e4e0c760e0204c29a4273fc0f14ebe3169306d2eb54c9953f58", + "sha256_in_prefix": "fda6ca994d710e4e0c760e0204c29a4273fc0f14ebe3169306d2eb54c9953f58", + "size_in_bytes": 13121 + }, + { + "_path": "lib/python3.12/encodings/cp1006.py", + "path_type": "hardlink", + "sha256": "eaded38b427841bdf280e878f1e26da506e743eaa9429075332af60cce429473", + "sha256_in_prefix": "eaded38b427841bdf280e878f1e26da506e743eaa9429075332af60cce429473", + "size_in_bytes": 13568 + }, + { + "_path": "lib/python3.12/encodings/cp1026.py", + "path_type": "hardlink", + "sha256": "f5227237dd7ce5005b16a8e4d8342f0d193193c878e3cf35b9305d22b3b1aaf9", + "sha256_in_prefix": "f5227237dd7ce5005b16a8e4d8342f0d193193c878e3cf35b9305d22b3b1aaf9", + "size_in_bytes": 13113 + }, + { + "_path": "lib/python3.12/encodings/cp1125.py", + "path_type": "hardlink", + "sha256": "f84c7d30ce222e6a50cff1a4c9737173411da108cbd2c9bb57c854480103c470", + "sha256_in_prefix": "f84c7d30ce222e6a50cff1a4c9737173411da108cbd2c9bb57c854480103c470", + "size_in_bytes": 34597 + }, + { + "_path": "lib/python3.12/encodings/cp1140.py", + "path_type": "hardlink", + "sha256": "3379d78b244aa905ffe1171a968caaf41b9a0154d1ddc76c05a2abaca2b289fd", + "sha256_in_prefix": "3379d78b244aa905ffe1171a968caaf41b9a0154d1ddc76c05a2abaca2b289fd", + "size_in_bytes": 13105 + }, + { + "_path": "lib/python3.12/encodings/cp1250.py", + "path_type": "hardlink", + "sha256": "ebcec1adf9167863fb0bab29708c546300c80a77ef07838c9e0437a59e265970", + "sha256_in_prefix": "ebcec1adf9167863fb0bab29708c546300c80a77ef07838c9e0437a59e265970", + "size_in_bytes": 13686 + }, + { + "_path": "lib/python3.12/encodings/cp1251.py", + "path_type": "hardlink", + "sha256": "d57f8cfa34494c5acb6692ddb31f616ae2dd89a075d2af6d36b0b7ec2ffe7af1", + "sha256_in_prefix": "d57f8cfa34494c5acb6692ddb31f616ae2dd89a075d2af6d36b0b7ec2ffe7af1", + "size_in_bytes": 13361 + }, + { + "_path": "lib/python3.12/encodings/cp1252.py", + "path_type": "hardlink", + "sha256": "19aa5bee667f5fb387924a813aec9fa1dda47769d09e8483a748bdb202be6a84", + "sha256_in_prefix": "19aa5bee667f5fb387924a813aec9fa1dda47769d09e8483a748bdb202be6a84", + "size_in_bytes": 13511 + }, + { + "_path": "lib/python3.12/encodings/cp1253.py", + "path_type": "hardlink", + "sha256": "8c27696dcfb6894b378869bc89f113703fbd1e9b13a83934463d5999b055d1e8", + "sha256_in_prefix": "8c27696dcfb6894b378869bc89f113703fbd1e9b13a83934463d5999b055d1e8", + "size_in_bytes": 13094 + }, + { + "_path": "lib/python3.12/encodings/cp1254.py", + "path_type": "hardlink", + "sha256": "06517ec2f74f1c6562d0a1a500c48ba43f2e6e9d0c3d28356d747f274f1a4c8d", + "sha256_in_prefix": "06517ec2f74f1c6562d0a1a500c48ba43f2e6e9d0c3d28356d747f274f1a4c8d", + "size_in_bytes": 13502 + }, + { + "_path": "lib/python3.12/encodings/cp1255.py", + "path_type": "hardlink", + "sha256": "54a1b5087578fa78e5bdd0afa6a9e80e8c5467c1e4226cf6e586cfe7a674a653", + "sha256_in_prefix": "54a1b5087578fa78e5bdd0afa6a9e80e8c5467c1e4226cf6e586cfe7a674a653", + "size_in_bytes": 12466 + }, + { + "_path": "lib/python3.12/encodings/cp1256.py", + "path_type": "hardlink", + "sha256": "ad3768ac2fef2a646b3301c20af705f4d4a1544f22fa8a84241bada27ab84133", + "sha256_in_prefix": "ad3768ac2fef2a646b3301c20af705f4d4a1544f22fa8a84241bada27ab84133", + "size_in_bytes": 12814 + }, + { + "_path": "lib/python3.12/encodings/cp1257.py", + "path_type": "hardlink", + "sha256": "d9149d2925b3f719809ef2297e541461079f15c658af207a3e498be314ab2c6b", + "sha256_in_prefix": "d9149d2925b3f719809ef2297e541461079f15c658af207a3e498be314ab2c6b", + "size_in_bytes": 13374 + }, + { + "_path": "lib/python3.12/encodings/cp1258.py", + "path_type": "hardlink", + "sha256": "672e05b51952a82c8dbd5603769195fcedf565e457bb86c0d5bae04955d04630", + "sha256_in_prefix": "672e05b51952a82c8dbd5603769195fcedf565e457bb86c0d5bae04955d04630", + "size_in_bytes": 13364 + }, + { + "_path": "lib/python3.12/encodings/cp273.py", + "path_type": "hardlink", + "sha256": "6c6aec3b213ea3aebc2c526dd4d121c95d4a25a2fc928a87cd80f8448988185f", + "sha256_in_prefix": "6c6aec3b213ea3aebc2c526dd4d121c95d4a25a2fc928a87cd80f8448988185f", + "size_in_bytes": 14132 + }, + { + "_path": "lib/python3.12/encodings/cp424.py", + "path_type": "hardlink", + "sha256": "30414c2186ea0802bbf3db034122ddec1f8a10061b97c50871e14b74ee36d0ca", + "sha256_in_prefix": "30414c2186ea0802bbf3db034122ddec1f8a10061b97c50871e14b74ee36d0ca", + "size_in_bytes": 12055 + }, + { + "_path": "lib/python3.12/encodings/cp437.py", + "path_type": "hardlink", + "sha256": "5c2a5015cd36cf7f561269f33dec4c323093d3d88b0673969accdabdcb9ce2cb", + "sha256_in_prefix": "5c2a5015cd36cf7f561269f33dec4c323093d3d88b0673969accdabdcb9ce2cb", + "size_in_bytes": 34564 + }, + { + "_path": "lib/python3.12/encodings/cp500.py", + "path_type": "hardlink", + "sha256": "630f503f9110d98ea3e1529f2f965ebc275a2f78d3de47f8e9b69d35589d764b", + "sha256_in_prefix": "630f503f9110d98ea3e1529f2f965ebc275a2f78d3de47f8e9b69d35589d764b", + "size_in_bytes": 13121 + }, + { + "_path": "lib/python3.12/encodings/cp720.py", + "path_type": "hardlink", + "sha256": "395496001271b92efe5df07fc0ae7c3410d1dd2bdfebbd3e4d8e806c8166beb0", + "sha256_in_prefix": "395496001271b92efe5df07fc0ae7c3410d1dd2bdfebbd3e4d8e806c8166beb0", + "size_in_bytes": 13686 + }, + { + "_path": "lib/python3.12/encodings/cp737.py", + "path_type": "hardlink", + "sha256": "be3ca1785a3970ec62310710eaf7de82932181b04d06fe4528f8adaba9fb8c4b", + "sha256_in_prefix": "be3ca1785a3970ec62310710eaf7de82932181b04d06fe4528f8adaba9fb8c4b", + "size_in_bytes": 34681 + }, + { + "_path": "lib/python3.12/encodings/cp775.py", + "path_type": "hardlink", + "sha256": "e0dba85b99329d7f16907e620adada06be5216abcb964406c827b569b2cf1aeb", + "sha256_in_prefix": "e0dba85b99329d7f16907e620adada06be5216abcb964406c827b569b2cf1aeb", + "size_in_bytes": 34476 + }, + { + "_path": "lib/python3.12/encodings/cp850.py", + "path_type": "hardlink", + "sha256": "257e29f235e2a8790dd68cee45668776648bab809ce8584f893cdd8fd007993c", + "sha256_in_prefix": "257e29f235e2a8790dd68cee45668776648bab809ce8584f893cdd8fd007993c", + "size_in_bytes": 34105 + }, + { + "_path": "lib/python3.12/encodings/cp852.py", + "path_type": "hardlink", + "sha256": "cc6faaa9dc4a933127da0aaacd1dc7a44c09266051af56bfe3215ff228636b6b", + "sha256_in_prefix": "cc6faaa9dc4a933127da0aaacd1dc7a44c09266051af56bfe3215ff228636b6b", + "size_in_bytes": 35002 + }, + { + "_path": "lib/python3.12/encodings/cp855.py", + "path_type": "hardlink", + "sha256": "7b25c61c9e8c47b218d3fbb801541a2861926ac712843d2113fff90e2074f5ba", + "sha256_in_prefix": "7b25c61c9e8c47b218d3fbb801541a2861926ac712843d2113fff90e2074f5ba", + "size_in_bytes": 33850 + }, + { + "_path": "lib/python3.12/encodings/cp856.py", + "path_type": "hardlink", + "sha256": "2e52ec5cb1eafa6739b5569b0b98ee89df5f7358b84ccdc8da64e86f017d359f", + "sha256_in_prefix": "2e52ec5cb1eafa6739b5569b0b98ee89df5f7358b84ccdc8da64e86f017d359f", + "size_in_bytes": 12423 + }, + { + "_path": "lib/python3.12/encodings/cp857.py", + "path_type": "hardlink", + "sha256": "8d1b769058bfccdb3c6c70c49a104f5081a2fcc9fad68f7b5eb3e4f67f0b33da", + "sha256_in_prefix": "8d1b769058bfccdb3c6c70c49a104f5081a2fcc9fad68f7b5eb3e4f67f0b33da", + "size_in_bytes": 33908 + }, + { + "_path": "lib/python3.12/encodings/cp858.py", + "path_type": "hardlink", + "sha256": "a24930c4a6ad0ff66dde9a69f2027e4b92c2c9c61dcda2992e940654c606577b", + "sha256_in_prefix": "a24930c4a6ad0ff66dde9a69f2027e4b92c2c9c61dcda2992e940654c606577b", + "size_in_bytes": 34015 + }, + { + "_path": "lib/python3.12/encodings/cp860.py", + "path_type": "hardlink", + "sha256": "2dfae7e31d3d9aa3013cff44a4d7ad842f257ac63765a9998436701b629cd86a", + "sha256_in_prefix": "2dfae7e31d3d9aa3013cff44a4d7ad842f257ac63765a9998436701b629cd86a", + "size_in_bytes": 34681 + }, + { + "_path": "lib/python3.12/encodings/cp861.py", + "path_type": "hardlink", + "sha256": "701930d77a2177497586e99bc3fe60f2d4beffb645608f167c76874a72ff405e", + "sha256_in_prefix": "701930d77a2177497586e99bc3fe60f2d4beffb645608f167c76874a72ff405e", + "size_in_bytes": 34633 + }, + { + "_path": "lib/python3.12/encodings/cp862.py", + "path_type": "hardlink", + "sha256": "15a2844b6ed9544c6400cf7299b42d0c2bef93c9bee70a9e89f66b8610ad6d6d", + "sha256_in_prefix": "15a2844b6ed9544c6400cf7299b42d0c2bef93c9bee70a9e89f66b8610ad6d6d", + "size_in_bytes": 33370 + }, + { + "_path": "lib/python3.12/encodings/cp863.py", + "path_type": "hardlink", + "sha256": "a3d57f61fce1b98fc81ea8e4ebebaf402fae40bbcdd35d4b8297b9bb49a79aa2", + "sha256_in_prefix": "a3d57f61fce1b98fc81ea8e4ebebaf402fae40bbcdd35d4b8297b9bb49a79aa2", + "size_in_bytes": 34252 + }, + { + "_path": "lib/python3.12/encodings/cp864.py", + "path_type": "hardlink", + "sha256": "15ad8f1fdfdd842c7522241372e7eddda7df687e815692a89157c5f256f21a08", + "sha256_in_prefix": "15ad8f1fdfdd842c7522241372e7eddda7df687e815692a89157c5f256f21a08", + "size_in_bytes": 33663 + }, + { + "_path": "lib/python3.12/encodings/cp865.py", + "path_type": "hardlink", + "sha256": "bdbaded987242ed2a8de7133ec2f61ddcc1c2e9de27816ab7cd0a4c678a3a907", + "sha256_in_prefix": "bdbaded987242ed2a8de7133ec2f61ddcc1c2e9de27816ab7cd0a4c678a3a907", + "size_in_bytes": 34618 + }, + { + "_path": "lib/python3.12/encodings/cp866.py", + "path_type": "hardlink", + "sha256": "9efcc8e85bbd1687272a0991f6d0429a4c06679db2d114b2ac95db27a70f9d13", + "sha256_in_prefix": "9efcc8e85bbd1687272a0991f6d0429a4c06679db2d114b2ac95db27a70f9d13", + "size_in_bytes": 34396 + }, + { + "_path": "lib/python3.12/encodings/cp869.py", + "path_type": "hardlink", + "sha256": "52582d9fb769b24eac7154f18d7dae856588297d6da98f37fb5efd8da883826d", + "sha256_in_prefix": "52582d9fb769b24eac7154f18d7dae856588297d6da98f37fb5efd8da883826d", + "size_in_bytes": 32965 + }, + { + "_path": "lib/python3.12/encodings/cp874.py", + "path_type": "hardlink", + "sha256": "fe4752fa2e65741e08a563a31ff914fe71068942ce9c6f4070b1dfd7b25e5e7f", + "sha256_in_prefix": "fe4752fa2e65741e08a563a31ff914fe71068942ce9c6f4070b1dfd7b25e5e7f", + "size_in_bytes": 12595 + }, + { + "_path": "lib/python3.12/encodings/cp875.py", + "path_type": "hardlink", + "sha256": "2fe72632015db2cba2bb4367055551da6fe22051b96d170c7b96fa271c46b257", + "sha256_in_prefix": "2fe72632015db2cba2bb4367055551da6fe22051b96d170c7b96fa271c46b257", + "size_in_bytes": 12854 + }, + { + "_path": "lib/python3.12/encodings/cp932.py", + "path_type": "hardlink", + "sha256": "99748e28113d2d49f5d666b49b78accd2c6e10a7852f7dd6dece9b5b71aa83c4", + "sha256_in_prefix": "99748e28113d2d49f5d666b49b78accd2c6e10a7852f7dd6dece9b5b71aa83c4", + "size_in_bytes": 1023 + }, + { + "_path": "lib/python3.12/encodings/cp949.py", + "path_type": "hardlink", + "sha256": "950a7d29467ce0590b4a1137830d43d88d8f20e4035dcaaa8b2a5c3c3f1de962", + "sha256_in_prefix": "950a7d29467ce0590b4a1137830d43d88d8f20e4035dcaaa8b2a5c3c3f1de962", + "size_in_bytes": 1023 + }, + { + "_path": "lib/python3.12/encodings/cp950.py", + "path_type": "hardlink", + "sha256": "27811178b450731fc955b1247656a605d04e5ee98e0d585e4596b94b703a27f6", + "sha256_in_prefix": "27811178b450731fc955b1247656a605d04e5ee98e0d585e4596b94b703a27f6", + "size_in_bytes": 1023 + }, + { + "_path": "lib/python3.12/encodings/euc_jis_2004.py", + "path_type": "hardlink", + "sha256": "9fa426cd9f17629f6320700ed18baa94839304cf1bcabbee7edb501747dc055d", + "sha256_in_prefix": "9fa426cd9f17629f6320700ed18baa94839304cf1bcabbee7edb501747dc055d", + "size_in_bytes": 1051 + }, + { + "_path": "lib/python3.12/encodings/euc_jisx0213.py", + "path_type": "hardlink", + "sha256": "e28315910da20218dae8b7d5becd81de1e283dfd8b0415a4980d67065de73a0b", + "sha256_in_prefix": "e28315910da20218dae8b7d5becd81de1e283dfd8b0415a4980d67065de73a0b", + "size_in_bytes": 1051 + }, + { + "_path": "lib/python3.12/encodings/euc_jp.py", + "path_type": "hardlink", + "sha256": "b453a439787b0efa031e43416a7d852a6be705c985e1200693eb96d87ea79cdc", + "sha256_in_prefix": "b453a439787b0efa031e43416a7d852a6be705c985e1200693eb96d87ea79cdc", + "size_in_bytes": 1027 + }, + { + "_path": "lib/python3.12/encodings/euc_kr.py", + "path_type": "hardlink", + "sha256": "633a1a5504bfad04b1ec9c96d44d4ebb3bb99066a218318e7d67d866e20887a6", + "sha256_in_prefix": "633a1a5504bfad04b1ec9c96d44d4ebb3bb99066a218318e7d67d866e20887a6", + "size_in_bytes": 1027 + }, + { + "_path": "lib/python3.12/encodings/gb18030.py", + "path_type": "hardlink", + "sha256": "6c10b4dc49bc63724e539137ede6936304fcca1c97c28d16d89f381e10849521", + "sha256_in_prefix": "6c10b4dc49bc63724e539137ede6936304fcca1c97c28d16d89f381e10849521", + "size_in_bytes": 1031 + }, + { + "_path": "lib/python3.12/encodings/gb2312.py", + "path_type": "hardlink", + "sha256": "3d2d567d8d079b78f3f3b566ed52ad2f38af61bf832b7dc28858b0039a032d6b", + "sha256_in_prefix": "3d2d567d8d079b78f3f3b566ed52ad2f38af61bf832b7dc28858b0039a032d6b", + "size_in_bytes": 1027 + }, + { + "_path": "lib/python3.12/encodings/gbk.py", + "path_type": "hardlink", + "sha256": "eff9b8cbc9ad2ef2e10e96afa83d3db1f775ea044aed275b7a35574ae0d8645b", + "sha256_in_prefix": "eff9b8cbc9ad2ef2e10e96afa83d3db1f775ea044aed275b7a35574ae0d8645b", + "size_in_bytes": 1015 + }, + { + "_path": "lib/python3.12/encodings/hex_codec.py", + "path_type": "hardlink", + "sha256": "fc5f0a31b59efe990b86efb98936769f33dd91d912ce55b49a5a4cfc516cd047", + "sha256_in_prefix": "fc5f0a31b59efe990b86efb98936769f33dd91d912ce55b49a5a4cfc516cd047", + "size_in_bytes": 1508 + }, + { + "_path": "lib/python3.12/encodings/hp_roman8.py", + "path_type": "hardlink", + "sha256": "c43cce763d12e8f71a63dbc16641bd87147eaf5f9d9054ea856864b216b2735b", + "sha256_in_prefix": "c43cce763d12e8f71a63dbc16641bd87147eaf5f9d9054ea856864b216b2735b", + "size_in_bytes": 13475 + }, + { + "_path": "lib/python3.12/encodings/hz.py", + "path_type": "hardlink", + "sha256": "025a9531e3046e52d3e039c0be04f9a5a74651d7683a13c7c7ebd4c7dfb5996a", + "sha256_in_prefix": "025a9531e3046e52d3e039c0be04f9a5a74651d7683a13c7c7ebd4c7dfb5996a", + "size_in_bytes": 1011 + }, + { + "_path": "lib/python3.12/encodings/idna.py", + "path_type": "hardlink", + "sha256": "9ca58e82d12b171f25d57239ad237dae5c44214a70f2f4f39358c2759b8b9013", + "sha256_in_prefix": "9ca58e82d12b171f25d57239ad237dae5c44214a70f2f4f39358c2759b8b9013", + "size_in_bytes": 9710 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp.py", + "path_type": "hardlink", + "sha256": "461a0e7f72eccb8b29f351c4e7926cfbda58e0edd6d0770bd82e0b36c5febe77", + "sha256_in_prefix": "461a0e7f72eccb8b29f351c4e7926cfbda58e0edd6d0770bd82e0b36c5febe77", + "size_in_bytes": 1053 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp_1.py", + "path_type": "hardlink", + "sha256": "63bacad13a979a5519fcaa4f1e1e07b2c7415005167fac3a689408c7d886fabd", + "sha256_in_prefix": "63bacad13a979a5519fcaa4f1e1e07b2c7415005167fac3a689408c7d886fabd", + "size_in_bytes": 1061 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp_2.py", + "path_type": "hardlink", + "sha256": "5d4248181548b0fc89a9f5ee9cf52ebecb235708ba87d47896ad14130884ef9f", + "sha256_in_prefix": "5d4248181548b0fc89a9f5ee9cf52ebecb235708ba87d47896ad14130884ef9f", + "size_in_bytes": 1061 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp_2004.py", + "path_type": "hardlink", + "sha256": "b4d1468bcd608b46f38cb0c6ef115510dcf9aa0f71e590792f407efc6e165164", + "sha256_in_prefix": "b4d1468bcd608b46f38cb0c6ef115510dcf9aa0f71e590792f407efc6e165164", + "size_in_bytes": 1073 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp_3.py", + "path_type": "hardlink", + "sha256": "3aceaa5661909de14e2861d864443b8472460ce39b99cce5c6965346d47aa5ac", + "sha256_in_prefix": "3aceaa5661909de14e2861d864443b8472460ce39b99cce5c6965346d47aa5ac", + "size_in_bytes": 1061 + }, + { + "_path": "lib/python3.12/encodings/iso2022_jp_ext.py", + "path_type": "hardlink", + "sha256": "f4c9ed8f3031995faa224bcb10153d2b6144944477d1f27d1a6cc4a879fac34c", + "sha256_in_prefix": "f4c9ed8f3031995faa224bcb10153d2b6144944477d1f27d1a6cc4a879fac34c", + "size_in_bytes": 1069 + }, + { + "_path": "lib/python3.12/encodings/iso2022_kr.py", + "path_type": "hardlink", + "sha256": "1c86362e17944f0bcf68db02f4995bdeea605867795fff7ab4079073f96705e4", + "sha256_in_prefix": "1c86362e17944f0bcf68db02f4995bdeea605867795fff7ab4079073f96705e4", + "size_in_bytes": 1053 + }, + { + "_path": "lib/python3.12/encodings/iso8859_1.py", + "path_type": "hardlink", + "sha256": "b5cebd515e057d670bf54e10b8a6f162ef3daa7f21b146aee3249160caf3c32d", + "sha256_in_prefix": "b5cebd515e057d670bf54e10b8a6f162ef3daa7f21b146aee3249160caf3c32d", + "size_in_bytes": 13176 + }, + { + "_path": "lib/python3.12/encodings/iso8859_10.py", + "path_type": "hardlink", + "sha256": "54c886b41819ebb7f4fb34b8dbae1c45f4fc0864f019ecd772676ccfac5fae7b", + "sha256_in_prefix": "54c886b41819ebb7f4fb34b8dbae1c45f4fc0864f019ecd772676ccfac5fae7b", + "size_in_bytes": 13589 + }, + { + "_path": "lib/python3.12/encodings/iso8859_11.py", + "path_type": "hardlink", + "sha256": "ed5a964470a241b4da7a6cfb718e4149d09644933af38f0497602baab6e563ef", + "sha256_in_prefix": "ed5a964470a241b4da7a6cfb718e4149d09644933af38f0497602baab6e563ef", + "size_in_bytes": 12335 + }, + { + "_path": "lib/python3.12/encodings/iso8859_13.py", + "path_type": "hardlink", + "sha256": "7312237e8e5d201d920b4130f057cfdf1b0be9baafaa246826e6d93204fcc206", + "sha256_in_prefix": "7312237e8e5d201d920b4130f057cfdf1b0be9baafaa246826e6d93204fcc206", + "size_in_bytes": 13271 + }, + { + "_path": "lib/python3.12/encodings/iso8859_14.py", + "path_type": "hardlink", + "sha256": "82778b995a0ee87c5f1180fcc52900359eee15bd9a6e3a0e25f0d963e0b2a343", + "sha256_in_prefix": "82778b995a0ee87c5f1180fcc52900359eee15bd9a6e3a0e25f0d963e0b2a343", + "size_in_bytes": 13652 + }, + { + "_path": "lib/python3.12/encodings/iso8859_15.py", + "path_type": "hardlink", + "sha256": "01976a81811873dc9a0c79db9fc00d1c30103487f3c6bc3a6d81b4043cd48e02", + "sha256_in_prefix": "01976a81811873dc9a0c79db9fc00d1c30103487f3c6bc3a6d81b4043cd48e02", + "size_in_bytes": 13212 + }, + { + "_path": "lib/python3.12/encodings/iso8859_16.py", + "path_type": "hardlink", + "sha256": "b5ac8f5a5d8f84c0f903b2b7c342184758d590d8bcf810d561f942fe5b372d66", + "sha256_in_prefix": "b5ac8f5a5d8f84c0f903b2b7c342184758d590d8bcf810d561f942fe5b372d66", + "size_in_bytes": 13557 + }, + { + "_path": "lib/python3.12/encodings/iso8859_2.py", + "path_type": "hardlink", + "sha256": "2b57cab6111cae9021505e3ae1b2adbbfc344ec48165fda322f6b069fbb18adc", + "sha256_in_prefix": "2b57cab6111cae9021505e3ae1b2adbbfc344ec48165fda322f6b069fbb18adc", + "size_in_bytes": 13404 + }, + { + "_path": "lib/python3.12/encodings/iso8859_3.py", + "path_type": "hardlink", + "sha256": "4ffdf89004bf0c5230caa7079f7ca3142fc112f8b923ddb2c7358369d2d3c242", + "sha256_in_prefix": "4ffdf89004bf0c5230caa7079f7ca3142fc112f8b923ddb2c7358369d2d3c242", + "size_in_bytes": 13089 + }, + { + "_path": "lib/python3.12/encodings/iso8859_4.py", + "path_type": "hardlink", + "sha256": "87bd130daa0eaef3e4cb465e10cffb2bcd194ff74097e0c186b4b8eb7be41ac5", + "sha256_in_prefix": "87bd130daa0eaef3e4cb465e10cffb2bcd194ff74097e0c186b4b8eb7be41ac5", + "size_in_bytes": 13376 + }, + { + "_path": "lib/python3.12/encodings/iso8859_5.py", + "path_type": "hardlink", + "sha256": "9961d96cc7b9fdf011ebcaaeaeca7b50b8670fadbd7b75fde66192f8c1f68f30", + "sha256_in_prefix": "9961d96cc7b9fdf011ebcaaeaeca7b50b8670fadbd7b75fde66192f8c1f68f30", + "size_in_bytes": 13015 + }, + { + "_path": "lib/python3.12/encodings/iso8859_6.py", + "path_type": "hardlink", + "sha256": "4840e68014346517680f593ca22f67133c39ba7e46f34b9be62c980a728448c6", + "sha256_in_prefix": "4840e68014346517680f593ca22f67133c39ba7e46f34b9be62c980a728448c6", + "size_in_bytes": 10833 + }, + { + "_path": "lib/python3.12/encodings/iso8859_7.py", + "path_type": "hardlink", + "sha256": "b352eca3b819488f64fb3338fd93f39c1e30f32bb13f2f9c577925e58f2960e4", + "sha256_in_prefix": "b352eca3b819488f64fb3338fd93f39c1e30f32bb13f2f9c577925e58f2960e4", + "size_in_bytes": 12844 + }, + { + "_path": "lib/python3.12/encodings/iso8859_8.py", + "path_type": "hardlink", + "sha256": "4cf9e8a8bbe04accb1c1a80853efb19ae0772d18f81e270adefc1b2386cb368e", + "sha256_in_prefix": "4cf9e8a8bbe04accb1c1a80853efb19ae0772d18f81e270adefc1b2386cb368e", + "size_in_bytes": 11036 + }, + { + "_path": "lib/python3.12/encodings/iso8859_9.py", + "path_type": "hardlink", + "sha256": "84d9b15263e81685f7513c5ab45caf80b2f73c301c68e659f7162c1b1882d359", + "sha256_in_prefix": "84d9b15263e81685f7513c5ab45caf80b2f73c301c68e659f7162c1b1882d359", + "size_in_bytes": 13156 + }, + { + "_path": "lib/python3.12/encodings/johab.py", + "path_type": "hardlink", + "sha256": "9586615917afd3d848c1c4328656603b2834af6115f2aec932fccc935e1a60fb", + "sha256_in_prefix": "9586615917afd3d848c1c4328656603b2834af6115f2aec932fccc935e1a60fb", + "size_in_bytes": 1023 + }, + { + "_path": "lib/python3.12/encodings/koi8_r.py", + "path_type": "hardlink", + "sha256": "4d4e353aee8039bb71e2145a6e68fe1e6833a1b4250b70ee0ac5ec70bbb8c51d", + "sha256_in_prefix": "4d4e353aee8039bb71e2145a6e68fe1e6833a1b4250b70ee0ac5ec70bbb8c51d", + "size_in_bytes": 13779 + }, + { + "_path": "lib/python3.12/encodings/koi8_t.py", + "path_type": "hardlink", + "sha256": "9c9043814abdbe7dc39ff98f3857d5d110a84c978ad2304158d810a4e9eacef1", + "sha256_in_prefix": "9c9043814abdbe7dc39ff98f3857d5d110a84c978ad2304158d810a4e9eacef1", + "size_in_bytes": 13193 + }, + { + "_path": "lib/python3.12/encodings/koi8_u.py", + "path_type": "hardlink", + "sha256": "d449f9858e357fa8c2edbd4b9fe739337e9f201cac3ded20f99bfcecd4970ff7", + "sha256_in_prefix": "d449f9858e357fa8c2edbd4b9fe739337e9f201cac3ded20f99bfcecd4970ff7", + "size_in_bytes": 13762 + }, + { + "_path": "lib/python3.12/encodings/kz1048.py", + "path_type": "hardlink", + "sha256": "76beb30e98a911f72f97609a2373782573c17c88a5fb3537db338aa382979ffc", + "sha256_in_prefix": "76beb30e98a911f72f97609a2373782573c17c88a5fb3537db338aa382979ffc", + "size_in_bytes": 13723 + }, + { + "_path": "lib/python3.12/encodings/latin_1.py", + "path_type": "hardlink", + "sha256": "b75503e532a27c636477396c855209ff5f3036536d2a4bede0a576c89382b60c", + "sha256_in_prefix": "b75503e532a27c636477396c855209ff5f3036536d2a4bede0a576c89382b60c", + "size_in_bytes": 1264 + }, + { + "_path": "lib/python3.12/encodings/mac_arabic.py", + "path_type": "hardlink", + "sha256": "5eafd9a3136abfbd8ed52df9c90203c7a283e7429ed60502a87a02511e0fb777", + "sha256_in_prefix": "5eafd9a3136abfbd8ed52df9c90203c7a283e7429ed60502a87a02511e0fb777", + "size_in_bytes": 36467 + }, + { + "_path": "lib/python3.12/encodings/mac_croatian.py", + "path_type": "hardlink", + "sha256": "a880cd05c82a8d11a29c65ee86a396def3344465dd71441b0bb4a73826024953", + "sha256_in_prefix": "a880cd05c82a8d11a29c65ee86a396def3344465dd71441b0bb4a73826024953", + "size_in_bytes": 13633 + }, + { + "_path": "lib/python3.12/encodings/mac_cyrillic.py", + "path_type": "hardlink", + "sha256": "83616786a1c6308b03a0dc82536908d24d0974b2248d67393d613fe558cea4bd", + "sha256_in_prefix": "83616786a1c6308b03a0dc82536908d24d0974b2248d67393d613fe558cea4bd", + "size_in_bytes": 13454 + }, + { + "_path": "lib/python3.12/encodings/mac_farsi.py", + "path_type": "hardlink", + "sha256": "f5763c38fb4ab0423fafe2fdca34d6f9932ac7f1a74c0cd8109d60234c7dc624", + "sha256_in_prefix": "f5763c38fb4ab0423fafe2fdca34d6f9932ac7f1a74c0cd8109d60234c7dc624", + "size_in_bytes": 15170 + }, + { + "_path": "lib/python3.12/encodings/mac_greek.py", + "path_type": "hardlink", + "sha256": "63016a323ddf98cb3aa9cfa78f3bab4768bedbfe9a5262a36a5aecb13d291f6e", + "sha256_in_prefix": "63016a323ddf98cb3aa9cfa78f3bab4768bedbfe9a5262a36a5aecb13d291f6e", + "size_in_bytes": 13721 + }, + { + "_path": "lib/python3.12/encodings/mac_iceland.py", + "path_type": "hardlink", + "sha256": "753cc1ac635caa7e1b4630fbcebef8db8db332c098154a5b11f652912bf64f37", + "sha256_in_prefix": "753cc1ac635caa7e1b4630fbcebef8db8db332c098154a5b11f652912bf64f37", + "size_in_bytes": 13498 + }, + { + "_path": "lib/python3.12/encodings/mac_latin2.py", + "path_type": "hardlink", + "sha256": "31670da18ce8b5394cd53fe6bf216268e7e8eae4c0247532e420e2e103727d50", + "sha256_in_prefix": "31670da18ce8b5394cd53fe6bf216268e7e8eae4c0247532e420e2e103727d50", + "size_in_bytes": 14118 + }, + { + "_path": "lib/python3.12/encodings/mac_roman.py", + "path_type": "hardlink", + "sha256": "230367d96aef8e8d7f185b4acfb84923714f39ddbcbf9cf38a06bf6f5d621c22", + "sha256_in_prefix": "230367d96aef8e8d7f185b4acfb84923714f39ddbcbf9cf38a06bf6f5d621c22", + "size_in_bytes": 13480 + }, + { + "_path": "lib/python3.12/encodings/mac_romanian.py", + "path_type": "hardlink", + "sha256": "49630cf035c19e896a123ed6e5fee18b5e485123daf2f15da38bf727ff387bee", + "sha256_in_prefix": "49630cf035c19e896a123ed6e5fee18b5e485123daf2f15da38bf727ff387bee", + "size_in_bytes": 13661 + }, + { + "_path": "lib/python3.12/encodings/mac_turkish.py", + "path_type": "hardlink", + "sha256": "99758a5cad2825cb3be3fa5d031e0821e4eba910a46f417fd890207b9b6be77b", + "sha256_in_prefix": "99758a5cad2825cb3be3fa5d031e0821e4eba910a46f417fd890207b9b6be77b", + "size_in_bytes": 13513 + }, + { + "_path": "lib/python3.12/encodings/mbcs.py", + "path_type": "hardlink", + "sha256": "f6ed445ed537c9f856d8defe8b56505727737d0dc9348d0a877abedab4bdd864", + "sha256_in_prefix": "f6ed445ed537c9f856d8defe8b56505727737d0dc9348d0a877abedab4bdd864", + "size_in_bytes": 1211 + }, + { + "_path": "lib/python3.12/encodings/oem.py", + "path_type": "hardlink", + "sha256": "481656d3a35f792d0e5109e3f821e6dbfcf097163a19b0cdfcbff3b3db99292f", + "sha256_in_prefix": "481656d3a35f792d0e5109e3f821e6dbfcf097163a19b0cdfcbff3b3db99292f", + "size_in_bytes": 1019 + }, + { + "_path": "lib/python3.12/encodings/palmos.py", + "path_type": "hardlink", + "sha256": "eccf7418adefcc2a59e9a07fc4e34363bd62f7e878d48c8a02730a8ed1c584c8", + "sha256_in_prefix": "eccf7418adefcc2a59e9a07fc4e34363bd62f7e878d48c8a02730a8ed1c584c8", + "size_in_bytes": 13519 + }, + { + "_path": "lib/python3.12/encodings/ptcp154.py", + "path_type": "hardlink", + "sha256": "0eabcb2c287d335e86b71b0abe5718bd6ddc9aaee234f0f0f2363845d2926d8d", + "sha256_in_prefix": "0eabcb2c287d335e86b71b0abe5718bd6ddc9aaee234f0f0f2363845d2926d8d", + "size_in_bytes": 14015 + }, + { + "_path": "lib/python3.12/encodings/punycode.py", + "path_type": "hardlink", + "sha256": "34edc8fb1c50e4d1cbaa1e008bb491cd7c12116c316e51974f333fe7b628eb7c", + "sha256_in_prefix": "34edc8fb1c50e4d1cbaa1e008bb491cd7c12116c316e51974f333fe7b628eb7c", + "size_in_bytes": 6883 + }, + { + "_path": "lib/python3.12/encodings/quopri_codec.py", + "path_type": "hardlink", + "sha256": "502a213c34c05a94ed063ee03f47680bd6efbb35036e06fb4dc809bf398cfa64", + "sha256_in_prefix": "502a213c34c05a94ed063ee03f47680bd6efbb35036e06fb4dc809bf398cfa64", + "size_in_bytes": 1525 + }, + { + "_path": "lib/python3.12/encodings/raw_unicode_escape.py", + "path_type": "hardlink", + "sha256": "fa6328486b8f5a5cbd10e377e80adb8cf94acbbe19c38b4e1bf708d831a80a3a", + "sha256_in_prefix": "fa6328486b8f5a5cbd10e377e80adb8cf94acbbe19c38b4e1bf708d831a80a3a", + "size_in_bytes": 1332 + }, + { + "_path": "lib/python3.12/encodings/rot_13.py", + "path_type": "hardlink", + "sha256": "14767f475acdc0bf48e6272280dd15b80efaecafb93c06be21136f83dd1ee7e4", + "sha256_in_prefix": "14767f475acdc0bf48e6272280dd15b80efaecafb93c06be21136f83dd1ee7e4", + "size_in_bytes": 2448 + }, + { + "_path": "lib/python3.12/encodings/shift_jis.py", + "path_type": "hardlink", + "sha256": "ad4ac50ebf58294304e412cc0f1b12980988dd6edc414e4110029c0a1abbe966", + "sha256_in_prefix": "ad4ac50ebf58294304e412cc0f1b12980988dd6edc414e4110029c0a1abbe966", + "size_in_bytes": 1039 + }, + { + "_path": "lib/python3.12/encodings/shift_jis_2004.py", + "path_type": "hardlink", + "sha256": "d21c5930f21063ea78fea3b0f76dfb8fd92858d2a4a200064a52126a43dd1a99", + "sha256_in_prefix": "d21c5930f21063ea78fea3b0f76dfb8fd92858d2a4a200064a52126a43dd1a99", + "size_in_bytes": 1059 + }, + { + "_path": "lib/python3.12/encodings/shift_jisx0213.py", + "path_type": "hardlink", + "sha256": "2c8d0b93bb36edf31c1236b1b4d1c0008553868bd2fc9137570115b96b834f2e", + "sha256_in_prefix": "2c8d0b93bb36edf31c1236b1b4d1c0008553868bd2fc9137570115b96b834f2e", + "size_in_bytes": 1059 + }, + { + "_path": "lib/python3.12/encodings/tis_620.py", + "path_type": "hardlink", + "sha256": "647c4719e2c1a7375105e15a89b377c66f6b699977dcabbb71d923a4607b7902", + "sha256_in_prefix": "647c4719e2c1a7375105e15a89b377c66f6b699977dcabbb71d923a4607b7902", + "size_in_bytes": 12300 + }, + { + "_path": "lib/python3.12/encodings/undefined.py", + "path_type": "hardlink", + "sha256": "85bba5c5e1007cd8c1ade5c0214bcc825396d2bbd02054e62a9f162104748b64", + "sha256_in_prefix": "85bba5c5e1007cd8c1ade5c0214bcc825396d2bbd02054e62a9f162104748b64", + "size_in_bytes": 1299 + }, + { + "_path": "lib/python3.12/encodings/unicode_escape.py", + "path_type": "hardlink", + "sha256": "507e7ca8f18df639fd823d7cc23ce4028a3550ceefdfa40b3c76f81d1a94531d", + "sha256_in_prefix": "507e7ca8f18df639fd823d7cc23ce4028a3550ceefdfa40b3c76f81d1a94531d", + "size_in_bytes": 1304 + }, + { + "_path": "lib/python3.12/encodings/utf_16.py", + "path_type": "hardlink", + "sha256": "6c36257f7b8d214473560d195e71bccef0c69a53e1e52d2800b7a7890aad7e58", + "sha256_in_prefix": "6c36257f7b8d214473560d195e71bccef0c69a53e1e52d2800b7a7890aad7e58", + "size_in_bytes": 5236 + }, + { + "_path": "lib/python3.12/encodings/utf_16_be.py", + "path_type": "hardlink", + "sha256": "3357196f3fa52433326a6626880e34964e00c5570aee50e9a0a0a7c6d86f6e4f", + "sha256_in_prefix": "3357196f3fa52433326a6626880e34964e00c5570aee50e9a0a0a7c6d86f6e4f", + "size_in_bytes": 1037 + }, + { + "_path": "lib/python3.12/encodings/utf_16_le.py", + "path_type": "hardlink", + "sha256": "3aedaf3eb49769282daef1eaedfd4fa1c31fe5eebeff67fe2307c89dc2e2fd80", + "sha256_in_prefix": "3aedaf3eb49769282daef1eaedfd4fa1c31fe5eebeff67fe2307c89dc2e2fd80", + "size_in_bytes": 1037 + }, + { + "_path": "lib/python3.12/encodings/utf_32.py", + "path_type": "hardlink", + "sha256": "2072eece5f6026ad2d3549ab193a9e38894ea15ca9d5b3cd408fd6b116acc0c2", + "sha256_in_prefix": "2072eece5f6026ad2d3549ab193a9e38894ea15ca9d5b3cd408fd6b116acc0c2", + "size_in_bytes": 5129 + }, + { + "_path": "lib/python3.12/encodings/utf_32_be.py", + "path_type": "hardlink", + "sha256": "cbba20e1f6d0879c7c4293446c371a9f79e7c90bf3c78a77a9b8fc72b18915dd", + "sha256_in_prefix": "cbba20e1f6d0879c7c4293446c371a9f79e7c90bf3c78a77a9b8fc72b18915dd", + "size_in_bytes": 930 + }, + { + "_path": "lib/python3.12/encodings/utf_32_le.py", + "path_type": "hardlink", + "sha256": "9134b91047d85b442898d59effe23e7e0cf4167ca341ae31119a731dbf880a7b", + "sha256_in_prefix": "9134b91047d85b442898d59effe23e7e0cf4167ca341ae31119a731dbf880a7b", + "size_in_bytes": 930 + }, + { + "_path": "lib/python3.12/encodings/utf_7.py", + "path_type": "hardlink", + "sha256": "9ff32314f4f1fa074f206bbf7fdb851504e5313128636d73b4bf75b886e4a87d", + "sha256_in_prefix": "9ff32314f4f1fa074f206bbf7fdb851504e5313128636d73b4bf75b886e4a87d", + "size_in_bytes": 946 + }, + { + "_path": "lib/python3.12/encodings/utf_8.py", + "path_type": "hardlink", + "sha256": "ba0cac060269583523ca9506473a755203037c57d466a11aa89a30a5f6756f3d", + "sha256_in_prefix": "ba0cac060269583523ca9506473a755203037c57d466a11aa89a30a5f6756f3d", + "size_in_bytes": 1005 + }, + { + "_path": "lib/python3.12/encodings/utf_8_sig.py", + "path_type": "hardlink", + "sha256": "1ef3da8d8aa08149e7f274dc64dbfce2155da812e5258ca8e8f832428d3b5c2d", + "sha256_in_prefix": "1ef3da8d8aa08149e7f274dc64dbfce2155da812e5258ca8e8f832428d3b5c2d", + "size_in_bytes": 4133 + }, + { + "_path": "lib/python3.12/encodings/uu_codec.py", + "path_type": "hardlink", + "sha256": "45ba92000718abf85f158563c755205e100356ce1b4ab9444b4d0a3d21f061a3", + "sha256_in_prefix": "45ba92000718abf85f158563c755205e100356ce1b4ab9444b4d0a3d21f061a3", + "size_in_bytes": 2851 + }, + { + "_path": "lib/python3.12/encodings/zlib_codec.py", + "path_type": "hardlink", + "sha256": "6ef01e8d3a5fe1cc52f7b5ae008df12f1dbce7304111bf8d4758f1bfc0115759", + "sha256_in_prefix": "6ef01e8d3a5fe1cc52f7b5ae008df12f1dbce7304111bf8d4758f1bfc0115759", + "size_in_bytes": 2204 + }, + { + "_path": "lib/python3.12/ensurepip/__init__.py", + "path_type": "hardlink", + "sha256": "02ee7ac7c72ea6f2f9124842f9fc242f4f836a547719ce12f8ac3018e0409f56", + "sha256_in_prefix": "02ee7ac7c72ea6f2f9124842f9fc242f4f836a547719ce12f8ac3018e0409f56", + "size_in_bytes": 9443 + }, + { + "_path": "lib/python3.12/ensurepip/__main__.py", + "path_type": "hardlink", + "sha256": "ee735f518d0fc4dfec81f7aa3da1e052372ed4202c0da4eddd2587840beaecd7", + "sha256_in_prefix": "ee735f518d0fc4dfec81f7aa3da1e052372ed4202c0da4eddd2587840beaecd7", + "size_in_bytes": 88 + }, + { + "_path": "lib/python3.12/ensurepip/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4992236a9bfd03fbc6cde5a808e3fc615d1d99556e567ba55780e2d26dd6be8d", + "sha256_in_prefix": "4992236a9bfd03fbc6cde5a808e3fc615d1d99556e567ba55780e2d26dd6be8d", + "size_in_bytes": 9515 + }, + { + "_path": "lib/python3.12/ensurepip/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a0b6fa5a72b052ece9b6818710966c8b6f7d14ed67f3654aa3275369de2d1ff9", + "sha256_in_prefix": "a0b6fa5a72b052ece9b6818710966c8b6f7d14ed67f3654aa3275369de2d1ff9", + "size_in_bytes": 320 + }, + { + "_path": "lib/python3.12/ensurepip/__pycache__/_uninstall.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8f69fb7381689e6bb02a9e0f166f07f0229ac378ba06bf1e191024bef2bc54fb", + "sha256_in_prefix": "8f69fb7381689e6bb02a9e0f166f07f0229ac378ba06bf1e191024bef2bc54fb", + "size_in_bytes": 1333 + }, + { + "_path": "lib/python3.12/ensurepip/_bundled/pip-24.0-py3-none-any.whl", + "path_type": "hardlink", + "sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", + "sha256_in_prefix": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc", + "size_in_bytes": 2110226 + }, + { + "_path": "lib/python3.12/ensurepip/_uninstall.py", + "path_type": "hardlink", + "sha256": "3a6e95d01c45e2e47c05df3c81073b895c97c1eb0e5b90ab175d6d9263fc81f2", + "sha256_in_prefix": "3a6e95d01c45e2e47c05df3c81073b895c97c1eb0e5b90ab175d6d9263fc81f2", + "size_in_bytes": 808 + }, + { + "_path": "lib/python3.12/enum.py", + "path_type": "hardlink", + "sha256": "c8ead615c159598370295649eb296819ad4b40d50b200c4fec2d4269bf7af9ae", + "sha256_in_prefix": "c8ead615c159598370295649eb296819ad4b40d50b200c4fec2d4269bf7af9ae", + "size_in_bytes": 81636 + }, + { + "_path": "lib/python3.12/filecmp.py", + "path_type": "hardlink", + "sha256": "7ecc32ce8f6f3c19a2dd21bbefe48e9054d01ca9d6ae6e30832a65f530b1223a", + "sha256_in_prefix": "7ecc32ce8f6f3c19a2dd21bbefe48e9054d01ca9d6ae6e30832a65f530b1223a", + "size_in_bytes": 10187 + }, + { + "_path": "lib/python3.12/fileinput.py", + "path_type": "hardlink", + "sha256": "b0cd2a3f01c96f594b6038e52bd83d489bfa081cc757103c70aab4e5b2c4fe1f", + "sha256_in_prefix": "b0cd2a3f01c96f594b6038e52bd83d489bfa081cc757103c70aab4e5b2c4fe1f", + "size_in_bytes": 15714 + }, + { + "_path": "lib/python3.12/fnmatch.py", + "path_type": "hardlink", + "sha256": "6683da36e47af523f3f41e18ad244d837783e19e98911cc0b7415dea81494ebc", + "sha256_in_prefix": "6683da36e47af523f3f41e18ad244d837783e19e98911cc0b7415dea81494ebc", + "size_in_bytes": 5999 + }, + { + "_path": "lib/python3.12/fractions.py", + "path_type": "hardlink", + "sha256": "cf33568f7b767f66896995a7a81cc662e8be226f2e58efb61d2028f64eb5d231", + "sha256_in_prefix": "cf33568f7b767f66896995a7a81cc662e8be226f2e58efb61d2028f64eb5d231", + "size_in_bytes": 38067 + }, + { + "_path": "lib/python3.12/ftplib.py", + "path_type": "hardlink", + "sha256": "d46af0c591299d304747c661da2fd4fe417cb7e057eee56a1789c54e2ce083bd", + "sha256_in_prefix": "d46af0c591299d304747c661da2fd4fe417cb7e057eee56a1789c54e2ce083bd", + "size_in_bytes": 34735 + }, + { + "_path": "lib/python3.12/functools.py", + "path_type": "hardlink", + "sha256": "cca971c456e1bec8b751aecdf41466f34dbf72321ee0840627280ba2ccf9d033", + "sha256_in_prefix": "cca971c456e1bec8b751aecdf41466f34dbf72321ee0840627280ba2ccf9d033", + "size_in_bytes": 38126 + }, + { + "_path": "lib/python3.12/genericpath.py", + "path_type": "hardlink", + "sha256": "6a271770c5e0c0a594075cc0063c807421fac3474df05d91a01c91d12c36eb5f", + "sha256_in_prefix": "6a271770c5e0c0a594075cc0063c807421fac3474df05d91a01c91d12c36eb5f", + "size_in_bytes": 5301 + }, + { + "_path": "lib/python3.12/getopt.py", + "path_type": "hardlink", + "sha256": "0ce875700c8798193b8e2748f7a27fc542cc4d525a1e6fc403767450ec92be99", + "sha256_in_prefix": "0ce875700c8798193b8e2748f7a27fc542cc4d525a1e6fc403767450ec92be99", + "size_in_bytes": 7488 + }, + { + "_path": "lib/python3.12/getpass.py", + "path_type": "hardlink", + "sha256": "e74fd445337ff503223dd8aa4bdd7d04917067d00c796a10bedb7a1381a4960a", + "sha256_in_prefix": "e74fd445337ff503223dd8aa4bdd7d04917067d00c796a10bedb7a1381a4960a", + "size_in_bytes": 5990 + }, + { + "_path": "lib/python3.12/gettext.py", + "path_type": "hardlink", + "sha256": "a5c249a522b6b8e3aa6f1b12a8bcc09508b99ad612b58d2fc973db27ea3b7cc3", + "sha256_in_prefix": "a5c249a522b6b8e3aa6f1b12a8bcc09508b99ad612b58d2fc973db27ea3b7cc3", + "size_in_bytes": 21320 + }, + { + "_path": "lib/python3.12/glob.py", + "path_type": "hardlink", + "sha256": "c9e5f9ae0752660ede63328a456f58f87c29500b31f58c1b813458b00fceb6d5", + "sha256_in_prefix": "c9e5f9ae0752660ede63328a456f58f87c29500b31f58c1b813458b00fceb6d5", + "size_in_bytes": 8732 + }, + { + "_path": "lib/python3.12/graphlib.py", + "path_type": "hardlink", + "sha256": "7bd338c5a475d1101064603d3baa5507446d3c5e73f741f6d6e77c6204c1eb65", + "sha256_in_prefix": "7bd338c5a475d1101064603d3baa5507446d3c5e73f741f6d6e77c6204c1eb65", + "size_in_bytes": 9656 + }, + { + "_path": "lib/python3.12/gzip.py", + "path_type": "hardlink", + "sha256": "31e7275c5c20d1b414063c28088b68e7a3e657af60c9c23435bf92e77a1fd1e5", + "sha256_in_prefix": "31e7275c5c20d1b414063c28088b68e7a3e657af60c9c23435bf92e77a1fd1e5", + "size_in_bytes": 24859 + }, + { + "_path": "lib/python3.12/hashlib.py", + "path_type": "hardlink", + "sha256": "6dbdebf270868b391080e21dc9687eddfaf321c965ad979f68d3f5c423c613ab", + "sha256_in_prefix": "6dbdebf270868b391080e21dc9687eddfaf321c965ad979f68d3f5c423c613ab", + "size_in_bytes": 9349 + }, + { + "_path": "lib/python3.12/heapq.py", + "path_type": "hardlink", + "sha256": "6d43277e5c76fc0f073cd388fcff852d14d068f6bb6d4886c340f8b75a1229a9", + "sha256_in_prefix": "6d43277e5c76fc0f073cd388fcff852d14d068f6bb6d4886c340f8b75a1229a9", + "size_in_bytes": 23024 + }, + { + "_path": "lib/python3.12/hmac.py", + "path_type": "hardlink", + "sha256": "7facd1330e5487ed995eda5c8619df0d3e32f69cb619f97662372fb76325746e", + "sha256_in_prefix": "7facd1330e5487ed995eda5c8619df0d3e32f69cb619f97662372fb76325746e", + "size_in_bytes": 7716 + }, + { + "_path": "lib/python3.12/html/__init__.py", + "path_type": "hardlink", + "sha256": "923d82d821e75e8d235392c10c145ab8587927b3faf9c952bbd48081eebd8522", + "sha256_in_prefix": "923d82d821e75e8d235392c10c145ab8587927b3faf9c952bbd48081eebd8522", + "size_in_bytes": 4775 + }, + { + "_path": "lib/python3.12/html/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c14f93a3913b24facdf81fd81d12d611df0e568684373c52f796539e0abb249e", + "sha256_in_prefix": "c14f93a3913b24facdf81fd81d12d611df0e568684373c52f796539e0abb249e", + "size_in_bytes": 4381 + }, + { + "_path": "lib/python3.12/html/__pycache__/entities.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a34cf6ee964e5cb0eaece561bacd71f9d933d1e1709ddb96952eb6b7255b344a", + "sha256_in_prefix": "a34cf6ee964e5cb0eaece561bacd71f9d933d1e1709ddb96952eb6b7255b344a", + "size_in_bytes": 97665 + }, + { + "_path": "lib/python3.12/html/__pycache__/parser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "35db4e65e3db64258bc873f09b54b978dee66305ddfd558fcf01ff5b3953d851", + "sha256_in_prefix": "35db4e65e3db64258bc873f09b54b978dee66305ddfd558fcf01ff5b3953d851", + "size_in_bytes": 17169 + }, + { + "_path": "lib/python3.12/html/entities.py", + "path_type": "hardlink", + "sha256": "d9c65fb2828dbc1f3e399058a341d51e9375ec5bca95a8e92599c41bd5b78bde", + "sha256_in_prefix": "d9c65fb2828dbc1f3e399058a341d51e9375ec5bca95a8e92599c41bd5b78bde", + "size_in_bytes": 75512 + }, + { + "_path": "lib/python3.12/html/parser.py", + "path_type": "hardlink", + "sha256": "ab5a0a2fce2bec75d969dbe057b490ef574f9ac57cce9e0eaaf7a220b301e838", + "sha256_in_prefix": "ab5a0a2fce2bec75d969dbe057b490ef574f9ac57cce9e0eaaf7a220b301e838", + "size_in_bytes": 17054 + }, + { + "_path": "lib/python3.12/http/__init__.py", + "path_type": "hardlink", + "sha256": "17f4f6832cfc84b5b9600414bab80b77e67ccb611bdfed10a3f2beca9d0d568b", + "sha256_in_prefix": "17f4f6832cfc84b5b9600414bab80b77e67ccb611bdfed10a3f2beca9d0d568b", + "size_in_bytes": 8308 + }, + { + "_path": "lib/python3.12/http/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3568021e5902099befbbd53c92dda4ffc0666378477f113e20d3d4d31db855eb", + "sha256_in_prefix": "3568021e5902099befbbd53c92dda4ffc0666378477f113e20d3d4d31db855eb", + "size_in_bytes": 9482 + }, + { + "_path": "lib/python3.12/http/__pycache__/client.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b2a7549e383bd58be0d9aee55897f822607f6b7e8a5c2656d3b9b7bf8e913990", + "sha256_in_prefix": "b2a7549e383bd58be0d9aee55897f822607f6b7e8a5c2656d3b9b7bf8e913990", + "size_in_bytes": 57161 + }, + { + "_path": "lib/python3.12/http/__pycache__/cookiejar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b48e630fcf336f2c2fb9e400c3aef7a653fd75c753b07119b6c326d6a9622e1e", + "sha256_in_prefix": "b48e630fcf336f2c2fb9e400c3aef7a653fd75c753b07119b6c326d6a9622e1e", + "size_in_bytes": 81622 + }, + { + "_path": "lib/python3.12/http/__pycache__/cookies.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ae2097faa4a2620cda491b0d547ee14a2ff36ef1fb375a93aa6735168079347e", + "sha256_in_prefix": "ae2097faa4a2620cda491b0d547ee14a2ff36ef1fb375a93aa6735168079347e", + "size_in_bytes": 21532 + }, + { + "_path": "lib/python3.12/http/__pycache__/server.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e5dd37586988b8c5fab289a09c46f20932249f09c22a5089a6184999acb46dba", + "sha256_in_prefix": "e5dd37586988b8c5fab289a09c46f20932249f09c22a5089a6184999acb46dba", + "size_in_bytes": 55596 + }, + { + "_path": "lib/python3.12/http/client.py", + "path_type": "hardlink", + "sha256": "d78f92c3b6e5aa778d2ec8ef7faa14d6005a2ba7784d9e69fd872ecc81287774", + "sha256_in_prefix": "d78f92c3b6e5aa778d2ec8ef7faa14d6005a2ba7784d9e69fd872ecc81287774", + "size_in_bytes": 57228 + }, + { + "_path": "lib/python3.12/http/cookiejar.py", + "path_type": "hardlink", + "sha256": "2a64dbc46edd0173600f32d195531741de562522da28bc76c2f97dccceb37ddb", + "sha256_in_prefix": "2a64dbc46edd0173600f32d195531741de562522da28bc76c2f97dccceb37ddb", + "size_in_bytes": 77438 + }, + { + "_path": "lib/python3.12/http/cookies.py", + "path_type": "hardlink", + "sha256": "a4712e985f8d892e290e8317d0d4d692313a39d5b0bd22fc640b885a79043ff7", + "sha256_in_prefix": "a4712e985f8d892e290e8317d0d4d692313a39d5b0bd22fc640b885a79043ff7", + "size_in_bytes": 20482 + }, + { + "_path": "lib/python3.12/http/server.py", + "path_type": "hardlink", + "sha256": "6ef28116c245a8e5e7f2d57f17607b7df706fd86110cf1c5a2b8416151b41248", + "sha256_in_prefix": "6ef28116c245a8e5e7f2d57f17607b7df706fd86110cf1c5a2b8416151b41248", + "size_in_bytes": 48516 + }, + { + "_path": "lib/python3.12/idlelib/CREDITS.txt", + "path_type": "hardlink", + "sha256": "33e6a36056667d40e26f195c14371567470f53324c3fec43aec29e09d7d2a60b", + "sha256_in_prefix": "33e6a36056667d40e26f195c14371567470f53324c3fec43aec29e09d7d2a60b", + "size_in_bytes": 2152 + }, + { + "_path": "lib/python3.12/idlelib/ChangeLog", + "path_type": "hardlink", + "sha256": "b7f42699e5e5a7c82ebdf2a2962946b7228c933ece0ea7c0d7789f21a7dd7e64", + "sha256_in_prefix": "b7f42699e5e5a7c82ebdf2a2962946b7228c933ece0ea7c0d7789f21a7dd7e64", + "size_in_bytes": 56360 + }, + { + "_path": "lib/python3.12/idlelib/HISTORY.txt", + "path_type": "hardlink", + "sha256": "531067a78ad392f25631aba1d885f40786cf5f47854577162c9f90ff1f33164c", + "sha256_in_prefix": "531067a78ad392f25631aba1d885f40786cf5f47854577162c9f90ff1f33164c", + "size_in_bytes": 10312 + }, + { + "_path": "lib/python3.12/idlelib/Icons/README.txt", + "path_type": "hardlink", + "sha256": "60399d6129e3e486ce6b437bbf614ff4838bd4e7f42d461c3e5467cf3b4fa272", + "sha256_in_prefix": "60399d6129e3e486ce6b437bbf614ff4838bd4e7f42d461c3e5467cf3b4fa272", + "size_in_bytes": 443 + }, + { + "_path": "lib/python3.12/idlelib/Icons/folder.gif", + "path_type": "hardlink", + "sha256": "7c98d566a13fd599d1c11a375f387fef69b6c595c4f18c5d88c188a860be0e55", + "sha256_in_prefix": "7c98d566a13fd599d1c11a375f387fef69b6c595c4f18c5d88c188a860be0e55", + "size_in_bytes": 120 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle.ico", + "path_type": "hardlink", + "sha256": "7f13eeb5dca39d05e24b9eb069c6dcb2748633822d67288a8bf8b7e21cdddf55", + "sha256_in_prefix": "7f13eeb5dca39d05e24b9eb069c6dcb2748633822d67288a8bf8b7e21cdddf55", + "size_in_bytes": 57746 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_16.gif", + "path_type": "hardlink", + "sha256": "fe3af292b38660a8a58b1a8b4fa4240aa190602e7e9a700ea0536b3181fc968e", + "sha256_in_prefix": "fe3af292b38660a8a58b1a8b4fa4240aa190602e7e9a700ea0536b3181fc968e", + "size_in_bytes": 634 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_16.png", + "path_type": "hardlink", + "sha256": "78fb3fb0ec11f61bc6cf0947f3c3923aa18e1c6513684058ed0fa01ac858143e", + "sha256_in_prefix": "78fb3fb0ec11f61bc6cf0947f3c3923aa18e1c6513684058ed0fa01ac858143e", + "size_in_bytes": 1031 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_256.png", + "path_type": "hardlink", + "sha256": "3f517467d12e0e3ecf20f9bd68ce4bd18a2b8088f32308fd978fd80e87d3628b", + "sha256_in_prefix": "3f517467d12e0e3ecf20f9bd68ce4bd18a2b8088f32308fd978fd80e87d3628b", + "size_in_bytes": 39205 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_32.gif", + "path_type": "hardlink", + "sha256": "fe70991cfccd1267922e94d91e02e9a58d2d29fd3382a2f4975280b9023cb7b9", + "sha256_in_prefix": "fe70991cfccd1267922e94d91e02e9a58d2d29fd3382a2f4975280b9023cb7b9", + "size_in_bytes": 1019 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_32.png", + "path_type": "hardlink", + "sha256": "797cd05f1964d57c4c6c248ac7f7ea6a38019ada32a9ab7e6c28d060f87b03de", + "sha256_in_prefix": "797cd05f1964d57c4c6c248ac7f7ea6a38019ada32a9ab7e6c28d060f87b03de", + "size_in_bytes": 2036 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_48.gif", + "path_type": "hardlink", + "sha256": "37484901eb40eefa846308e1da3ff6f240ea98f769a2afc3cf4fdba00327ecbe", + "sha256_in_prefix": "37484901eb40eefa846308e1da3ff6f240ea98f769a2afc3cf4fdba00327ecbe", + "size_in_bytes": 1388 + }, + { + "_path": "lib/python3.12/idlelib/Icons/idle_48.png", + "path_type": "hardlink", + "sha256": "a09f433197c8870b12bb7859cc4c3fe2068908cb1ddbd4880ab0f6fee91b6c23", + "sha256_in_prefix": "a09f433197c8870b12bb7859cc4c3fe2068908cb1ddbd4880ab0f6fee91b6c23", + "size_in_bytes": 3977 + }, + { + "_path": "lib/python3.12/idlelib/Icons/minusnode.gif", + "path_type": "hardlink", + "sha256": "efa5aa1d1e3439ab85425bd2aa3a25b9e6c21309e672690cfb32219e1eb7a7f3", + "sha256_in_prefix": "efa5aa1d1e3439ab85425bd2aa3a25b9e6c21309e672690cfb32219e1eb7a7f3", + "size_in_bytes": 75 + }, + { + "_path": "lib/python3.12/idlelib/Icons/openfolder.gif", + "path_type": "hardlink", + "sha256": "9a59e2abf1840156e9db8f85a38822fd56ab79a139eb95ec86f1fba1bb87326b", + "sha256_in_prefix": "9a59e2abf1840156e9db8f85a38822fd56ab79a139eb95ec86f1fba1bb87326b", + "size_in_bytes": 125 + }, + { + "_path": "lib/python3.12/idlelib/Icons/plusnode.gif", + "path_type": "hardlink", + "sha256": "6ace9e90a2bcb16d06c4d78837137f2c14bc26b3bd9f24b7b6afeadb689bdafb", + "sha256_in_prefix": "6ace9e90a2bcb16d06c4d78837137f2c14bc26b3bd9f24b7b6afeadb689bdafb", + "size_in_bytes": 78 + }, + { + "_path": "lib/python3.12/idlelib/Icons/python.gif", + "path_type": "hardlink", + "sha256": "158c31382f8e5b41fded0c2aa9cc66a382928b003cdd8b5b0518836ad9c89377", + "sha256_in_prefix": "158c31382f8e5b41fded0c2aa9cc66a382928b003cdd8b5b0518836ad9c89377", + "size_in_bytes": 380 + }, + { + "_path": "lib/python3.12/idlelib/Icons/tk.gif", + "path_type": "hardlink", + "sha256": "7f16cb2e322891dbd9101302c09ffda0c2a3a72d053bb8c0927d507414c59cad", + "sha256_in_prefix": "7f16cb2e322891dbd9101302c09ffda0c2a3a72d053bb8c0927d507414c59cad", + "size_in_bytes": 72 + }, + { + "_path": "lib/python3.12/idlelib/NEWS2x.txt", + "path_type": "hardlink", + "sha256": "c89a3b513501ebace8e428aea68dce39d0af9f29196e08fc9ea49c99605e79e7", + "sha256_in_prefix": "c89a3b513501ebace8e428aea68dce39d0af9f29196e08fc9ea49c99605e79e7", + "size_in_bytes": 27172 + }, + { + "_path": "lib/python3.12/idlelib/News3.txt", + "path_type": "hardlink", + "sha256": "5b20beec21d162146baefd500b56821250472923c3fa75ee15e794b88c505ba3", + "sha256_in_prefix": "5b20beec21d162146baefd500b56821250472923c3fa75ee15e794b88c505ba3", + "size_in_bytes": 55514 + }, + { + "_path": "lib/python3.12/idlelib/README.txt", + "path_type": "hardlink", + "sha256": "4f2dc8ffdbfc7837b60edc32ac2f593a220f4abf0ea00cc477382ad8ecf8eb3d", + "sha256_in_prefix": "4f2dc8ffdbfc7837b60edc32ac2f593a220f4abf0ea00cc477382ad8ecf8eb3d", + "size_in_bytes": 11653 + }, + { + "_path": "lib/python3.12/idlelib/TODO.txt", + "path_type": "hardlink", + "sha256": "f88e0fb30fa0ab5d0dc3030442ed92713f34170336c4dd2623723dc34829df89", + "sha256_in_prefix": "f88e0fb30fa0ab5d0dc3030442ed92713f34170336c4dd2623723dc34829df89", + "size_in_bytes": 8478 + }, + { + "_path": "lib/python3.12/idlelib/__init__.py", + "path_type": "hardlink", + "sha256": "3f8058df4fec56eb20ff67ff84c86fd3d9697e2384c5a290ed696f6d3187aa45", + "sha256_in_prefix": "3f8058df4fec56eb20ff67ff84c86fd3d9697e2384c5a290ed696f6d3187aa45", + "size_in_bytes": 396 + }, + { + "_path": "lib/python3.12/idlelib/__main__.py", + "path_type": "hardlink", + "sha256": "f8f55514d26791588de02fe685af0ab129174b32ab93efa39faf6140b6795d9d", + "sha256_in_prefix": "f8f55514d26791588de02fe685af0ab129174b32ab93efa39faf6140b6795d9d", + "size_in_bytes": 159 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ba59c931221e1cb006648bfef26f2346d2cd1f5308a08b4bc0215f49b4ae1d74", + "sha256_in_prefix": "ba59c931221e1cb006648bfef26f2346d2cd1f5308a08b4bc0215f49b4ae1d74", + "size_in_bytes": 514 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0b0e6dc7a750f64db244afa64fb5c534d49bfbe6589e04eb147104d26852aa7e", + "sha256_in_prefix": "0b0e6dc7a750f64db244afa64fb5c534d49bfbe6589e04eb147104d26852aa7e", + "size_in_bytes": 329 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/autocomplete.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "714fcbebbc68607042bd55ba68f22423460f5568921e6b3828fe7a22b689e393", + "sha256_in_prefix": "714fcbebbc68607042bd55ba68f22423460f5568921e6b3828fe7a22b689e393", + "size_in_bytes": 10913 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/autocomplete_w.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c86b6f21b8370d846f6b29493724b4a0067a0ae215a7dc9575f5b8474f2bb1bc", + "sha256_in_prefix": "c86b6f21b8370d846f6b29493724b4a0067a0ae215a7dc9575f5b8474f2bb1bc", + "size_in_bytes": 23717 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/autoexpand.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da89c5713c1bd5165449729bacbb97cdbcddeef014a4db6428dbd8e3b6d14b2c", + "sha256_in_prefix": "da89c5713c1bd5165449729bacbb97cdbcddeef014a4db6428dbd8e3b6d14b2c", + "size_in_bytes": 4549 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/browser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7183113eb23c0570030df6a4b3ecab86a5782bca9dcfbed9fcd1a46511fadd9d", + "sha256_in_prefix": "7183113eb23c0570030df6a4b3ecab86a5782bca9dcfbed9fcd1a46511fadd9d", + "size_in_bytes": 13327 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/calltip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b1e1731c15b141da5de84986a7a63ba0138b3bc23b04e10be16ab203f5db63a3", + "sha256_in_prefix": "b1e1731c15b141da5de84986a7a63ba0138b3bc23b04e10be16ab203f5db63a3", + "size_in_bytes": 8359 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/calltip_w.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aaddb82044866cd25fb4fb0236e7cce75c9f1bda5a8a1de50785500a1586ad17", + "sha256_in_prefix": "aaddb82044866cd25fb4fb0236e7cce75c9f1bda5a8a1de50785500a1586ad17", + "size_in_bytes": 10277 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/codecontext.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3e5294ebdd27d2dc34a89fae2ad26c2492db3de6c1fd9cb4ef90d3a9bf52672c", + "sha256_in_prefix": "3e5294ebdd27d2dc34a89fae2ad26c2492db3de6c1fd9cb4ef90d3a9bf52672c", + "size_in_bytes": 13562 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/colorizer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "757fc5097a5f873883c2f468826447852e259991572a322bf3e538afcd3a6d4a", + "sha256_in_prefix": "757fc5097a5f873883c2f468826447852e259991572a322bf3e538afcd3a6d4a", + "size_in_bytes": 17698 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/config.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c76fe92ee69f12bc4c649b588db9e9ca0cf837f4573df9b125970804842732e7", + "sha256_in_prefix": "c76fe92ee69f12bc4c649b588db9e9ca0cf837f4573df9b125970804842732e7", + "size_in_bytes": 41478 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/config_key.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cc6f77988fe2bd0b9b9bc86e461436ba9a07443e6d98f7731a57787f71308b26", + "sha256_in_prefix": "cc6f77988fe2bd0b9b9bc86e461436ba9a07443e6d98f7731a57787f71308b26", + "size_in_bytes": 19884 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/configdialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3dd9c3014a8e499bb5e1a61f87f812eb34a4f01eeece37873c44dadc25056e4a", + "sha256_in_prefix": "3dd9c3014a8e499bb5e1a61f87f812eb34a4f01eeece37873c44dadc25056e4a", + "size_in_bytes": 125360 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/debugger.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "348e541d7567827ac9f79d63eb3a3065fe9c0386de2e38212f07872d362dadbd", + "sha256_in_prefix": "348e541d7567827ac9f79d63eb3a3065fe9c0386de2e38212f07872d362dadbd", + "size_in_bytes": 28182 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/debugger_r.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "23a962d319471cfe9aeaead1418a12e953b2a25b8e12ab0c00a4a84fae3795c2", + "sha256_in_prefix": "23a962d319471cfe9aeaead1418a12e953b2a25b8e12ab0c00a4a84fae3795c2", + "size_in_bytes": 18773 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/debugobj.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5885e8a233ac6e31ff0ab5a88a167e9b1dd5287206f8b690f931eed5d3ce1bf4", + "sha256_in_prefix": "5885e8a233ac6e31ff0ab5a88a167e9b1dd5287206f8b690f931eed5d3ce1bf4", + "size_in_bytes": 7586 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/debugobj_r.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6496a53167e99053a5fd27f91bbcdb1c4b8086c4f637d47651aebaeecccde388", + "sha256_in_prefix": "6496a53167e99053a5fd27f91bbcdb1c4b8086c4f637d47651aebaeecccde388", + "size_in_bytes": 2518 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/delegator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bdec346cd6574b2d5d76b7e2bab87914206091ad54758a2841790299be4baed4", + "sha256_in_prefix": "bdec346cd6574b2d5d76b7e2bab87914206091ad54758a2841790299be4baed4", + "size_in_bytes": 1724 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/dynoption.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b90379212e38cd99f6c105503b320812c769170b041994c9573526bbe3466bd6", + "sha256_in_prefix": "b90379212e38cd99f6c105503b320812c769170b041994c9573526bbe3466bd6", + "size_in_bytes": 3253 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/editor.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "306cd3768ab587380772a7b99cfb3eb30ec40e780e0b6d556e2fe0730d7b84a0", + "sha256_in_prefix": "306cd3768ab587380772a7b99cfb3eb30ec40e780e0b6d556e2fe0730d7b84a0", + "size_in_bytes": 86698 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/filelist.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "360aaf13cfbccbb58c0f7685d5be8a1a5b1a069d72fc1357e7e813272c8e3504", + "sha256_in_prefix": "360aaf13cfbccbb58c0f7685d5be8a1a5b1a069d72fc1357e7e813272c8e3504", + "size_in_bytes": 5643 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/format.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f0b5cfa6382efc10ad3338cd03d62bd049ff2a574f664bb37fbe88d29cefc993", + "sha256_in_prefix": "f0b5cfa6382efc10ad3338cd03d62bd049ff2a574f664bb37fbe88d29cefc993", + "size_in_bytes": 20726 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/grep.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2163e26d4ed1015e7756dd434b663d86d308b3e2f7f85e3658528550a876e107", + "sha256_in_prefix": "2163e26d4ed1015e7756dd434b663d86d308b3e2f7f85e3658528550a876e107", + "size_in_bytes": 11182 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/help.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "81238c6a2e1c6c9c7f42b028c0cb5fd934ba6261ce37024509cbabd06f195c8e", + "sha256_in_prefix": "81238c6a2e1c6c9c7f42b028c0cb5fd934ba6261ce37024509cbabd06f195c8e", + "size_in_bytes": 16235 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/help_about.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3a043a8b17e3bf0189a6e8a62d7110b91a8647683bf9e888acb3d4c8b190e246", + "sha256_in_prefix": "3a043a8b17e3bf0189a6e8a62d7110b91a8647683bf9e888acb3d4c8b190e246", + "size_in_bytes": 12663 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/history.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f79a5ce6bfe35964053d70064fae97f1e25774746351726a100d5dbd9a1932fe", + "sha256_in_prefix": "f79a5ce6bfe35964053d70064fae97f1e25774746351726a100d5dbd9a1932fe", + "size_in_bytes": 5177 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/hyperparser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ad0af374ef73fd469b819d16970c2b915d56e73520d5a3cebf852399079af387", + "sha256_in_prefix": "ad0af374ef73fd469b819d16970c2b915d56e73520d5a3cebf852399079af387", + "size_in_bytes": 12232 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/idle.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f0a51abeb18250bdeb30a96b82bf0c888d222998474531c32891ba523f2ed99c", + "sha256_in_prefix": "f0a51abeb18250bdeb30a96b82bf0c888d222998474531c32891ba523f2ed99c", + "size_in_bytes": 602 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/iomenu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f35891ce5e739478d6fc0553687c00a0605a75469831e1e8c0a9de39dc911c70", + "sha256_in_prefix": "f35891ce5e739478d6fc0553687c00a0605a75469831e1e8c0a9de39dc911c70", + "size_in_bytes": 21338 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/macosx.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a60b5e2cef6b9978e46ad71159cd5e360e83827d44a96c3cbb043ce649f878eb", + "sha256_in_prefix": "a60b5e2cef6b9978e46ad71159cd5e360e83827d44a96c3cbb043ce649f878eb", + "size_in_bytes": 9760 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/mainmenu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a88144ded3e7d43274f16ea4f220eb5beefadad974ca462314144485d6ae31ac", + "sha256_in_prefix": "a88144ded3e7d43274f16ea4f220eb5beefadad974ca462314144485d6ae31ac", + "size_in_bytes": 3529 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/multicall.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c93c33ade4dbef7876a4d508c73fba22747bfac8a6dc658cc3d7292361571e96", + "sha256_in_prefix": "c93c33ade4dbef7876a4d508c73fba22747bfac8a6dc658cc3d7292361571e96", + "size_in_bytes": 21777 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/outwin.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ce368c0a46bfe25a871ebb6804d6a6329d196b2c1aa1888ff24f5d12d83fda91", + "sha256_in_prefix": "ce368c0a46bfe25a871ebb6804d6a6329d196b2c1aa1888ff24f5d12d83fda91", + "size_in_bytes": 7694 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/parenmatch.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0ecc185f0192233d17f57496fa30ec03f43ef2f500ffd1d8a847d638f5f1c24b", + "sha256_in_prefix": "0ecc185f0192233d17f57496fa30ec03f43ef2f500ffd1d8a847d638f5f1c24b", + "size_in_bytes": 9533 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/pathbrowser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "633b10faf185772b9edc9e61d820f817684f0aca370b82c18b62f54ebdf0a11a", + "sha256_in_prefix": "633b10faf185772b9edc9e61d820f817684f0aca370b82c18b62f54ebdf0a11a", + "size_in_bytes": 5650 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/percolator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e9699705f9a7c222d46baed2113a74ef6e230f5e6169e8403abd619c3cdcf6fe", + "sha256_in_prefix": "e9699705f9a7c222d46baed2113a74ef6e230f5e6169e8403abd619c3cdcf6fe", + "size_in_bytes": 6888 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/pyparse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4e45aad1e0c2b4d32be8088ad6a0208303e20b8ea93513f47474d25f4345bd76", + "sha256_in_prefix": "4e45aad1e0c2b4d32be8088ad6a0208303e20b8ea93513f47474d25f4345bd76", + "size_in_bytes": 18101 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/pyshell.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aa66cf14cd79c55d1565254eeff52e08f9f9be7cf2c5428fb65d79ea37cdf386", + "sha256_in_prefix": "aa66cf14cd79c55d1565254eeff52e08f9f9be7cf2c5428fb65d79ea37cdf386", + "size_in_bytes": 81280 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/query.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7c2fc8d146d50ac1c49a3e2d7cc01ec5c3fd7f31a2650275b3f1dcd0ce13064d", + "sha256_in_prefix": "7c2fc8d146d50ac1c49a3e2d7cc01ec5c3fd7f31a2650275b3f1dcd0ce13064d", + "size_in_bytes": 19515 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/redirector.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "06d9939a8d8bb080738754c3a8858a097b4ef54a1e988340fcdcf638b2a27e45", + "sha256_in_prefix": "06d9939a8d8bb080738754c3a8858a097b4ef54a1e988340fcdcf638b2a27e45", + "size_in_bytes": 8906 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/replace.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f28e6bb32e0ca74a611df160c7b61286688611bac92c3bad5ee8284b3274840d", + "sha256_in_prefix": "f28e6bb32e0ca74a611df160c7b61286688611bac92c3bad5ee8284b3274840d", + "size_in_bytes": 14242 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/rpc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "df1602500cbc009cffe7c42a9a80d0f87dc6566bcf98a42f6414e3fd7fabfae9", + "sha256_in_prefix": "df1602500cbc009cffe7c42a9a80d0f87dc6566bcf98a42f6414e3fd7fabfae9", + "size_in_bytes": 30017 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/run.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "531307039d43b86180fd86a78f5f1548f88485871b2d1feb9a97f5d1ee473d39", + "sha256_in_prefix": "531307039d43b86180fd86a78f5f1548f88485871b2d1feb9a97f5d1ee473d39", + "size_in_bytes": 29495 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/runscript.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a938283e9ae20c73a84a2c67e129d7b08bd16cce8c1deae09ed618681d46e8bb", + "sha256_in_prefix": "a938283e9ae20c73a84a2c67e129d7b08bd16cce8c1deae09ed618681d46e8bb", + "size_in_bytes": 10911 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/scrolledlist.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6aef9ec7486e9ae9f1b028d22e145e229e893e2282fe3b5d59bebeee30ddab23", + "sha256_in_prefix": "6aef9ec7486e9ae9f1b028d22e145e229e893e2282fe3b5d59bebeee30ddab23", + "size_in_bytes": 9012 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/search.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bcfb375bf72ec7aa023c56cdeff0cebba9e310f46fe5a33c7a39d72b8d91c7d2", + "sha256_in_prefix": "bcfb375bf72ec7aa023c56cdeff0cebba9e310f46fe5a33c7a39d72b8d91c7d2", + "size_in_bytes": 8034 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/searchbase.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "451dfe900d0244413e1956aa3b4da6560d83995f131b5ce242e8102d4b68578b", + "sha256_in_prefix": "451dfe900d0244413e1956aa3b4da6560d83995f131b5ce242e8102d4b68578b", + "size_in_bytes": 12192 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/searchengine.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b548a66b53ad5d33fe147d5b27b98594b3a4573928c177f7d33c3d8a838010af", + "sha256_in_prefix": "b548a66b53ad5d33fe147d5b27b98594b3a4573928c177f7d33c3d8a838010af", + "size_in_bytes": 9957 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/sidebar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b1dca94a7d1405954330041632fece42029e6a64a9305d30c48a1f94c7badbef", + "sha256_in_prefix": "b1dca94a7d1405954330041632fece42029e6a64a9305d30c48a1f94c7badbef", + "size_in_bytes": 28788 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/squeezer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "19e23d11cf78054255043a0b1c40a61d719287d992992a20dbdbb0c60aa538d4", + "sha256_in_prefix": "19e23d11cf78054255043a0b1c40a61d719287d992992a20dbdbb0c60aa538d4", + "size_in_bytes": 14490 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/stackviewer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "946884ae622d3e1bea07c6e6a7a711347d8edd11a6dc4ec2ca8e50364c3151c8", + "sha256_in_prefix": "946884ae622d3e1bea07c6e6a7a711347d8edd11a6dc4ec2ca8e50364c3151c8", + "size_in_bytes": 7239 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/statusbar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ed1828dbf40f7f22d7087d3d0f9b4706d31be64e05c4db965ba11df22f833790", + "sha256_in_prefix": "ed1828dbf40f7f22d7087d3d0f9b4706d31be64e05c4db965ba11df22f833790", + "size_in_bytes": 2942 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/textview.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bd7c3196a4082df43972764a40802c063bcff54f1b6a822da09a99364cec0449", + "sha256_in_prefix": "bd7c3196a4082df43972764a40802c063bcff54f1b6a822da09a99364cec0449", + "size_in_bytes": 9878 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/tooltip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2f60a453bf873ab9805f9f6e0005035478986c854cbb84e6f37be08db8777fee", + "sha256_in_prefix": "2f60a453bf873ab9805f9f6e0005035478986c854cbb84e6f37be08db8777fee", + "size_in_bytes": 9412 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/tree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "47685ec757d0b60b94f2d84359c5fffe2e4d9d84a81621d626270e69da79ec81", + "sha256_in_prefix": "47685ec757d0b60b94f2d84359c5fffe2e4d9d84a81621d626270e69da79ec81", + "size_in_bytes": 28095 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/undo.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9962fec08b7406c037a87dc90c2e886e44c7b4bf0d76a1ae1f841f3ce40c0a4d", + "sha256_in_prefix": "9962fec08b7406c037a87dc90c2e886e44c7b4bf0d76a1ae1f841f3ce40c0a4d", + "size_in_bytes": 18466 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "302162daa88e752d8f1feaa3204c2865914779b46d5a38caf9a252b44936eb9c", + "sha256_in_prefix": "302162daa88e752d8f1feaa3204c2865914779b46d5a38caf9a252b44936eb9c", + "size_in_bytes": 814 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/window.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3e60b6a7b34c76f55f4f20f6d637b3b58768df6cd2f09e409e86abbf0b2b51b3", + "sha256_in_prefix": "3e60b6a7b34c76f55f4f20f6d637b3b58768df6cd2f09e409e86abbf0b2b51b3", + "size_in_bytes": 4859 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/zoomheight.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "701fef5c221508f1a46ee8f8993f7a2904088db818ca6616121517896c36f246", + "sha256_in_prefix": "701fef5c221508f1a46ee8f8993f7a2904088db818ca6616121517896c36f246", + "size_in_bytes": 4461 + }, + { + "_path": "lib/python3.12/idlelib/__pycache__/zzdummy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f8c18e0dce2805d3b8cc25b81dfa237b0d2ecd1083ca4d5ed19f208925785235", + "sha256_in_prefix": "f8c18e0dce2805d3b8cc25b81dfa237b0d2ecd1083ca4d5ed19f208925785235", + "size_in_bytes": 3265 + }, + { + "_path": "lib/python3.12/idlelib/autocomplete.py", + "path_type": "hardlink", + "sha256": "0d36f7694a50cbaa22d9bf03b91fa0658a147bd90dd867714a9b411febb36427", + "sha256_in_prefix": "0d36f7694a50cbaa22d9bf03b91fa0658a147bd90dd867714a9b411febb36427", + "size_in_bytes": 9354 + }, + { + "_path": "lib/python3.12/idlelib/autocomplete_w.py", + "path_type": "hardlink", + "sha256": "91170b060749d0b3c8f2ab31499104028bedf971e5575155d43392d5c8dae5d6", + "sha256_in_prefix": "91170b060749d0b3c8f2ab31499104028bedf971e5575155d43392d5c8dae5d6", + "size_in_bytes": 20863 + }, + { + "_path": "lib/python3.12/idlelib/autoexpand.py", + "path_type": "hardlink", + "sha256": "c8eb28ef7addf5a664a7e3addfbfebe29040a8695e1db515828305aacba2ee4e", + "sha256_in_prefix": "c8eb28ef7addf5a664a7e3addfbfebe29040a8695e1db515828305aacba2ee4e", + "size_in_bytes": 3216 + }, + { + "_path": "lib/python3.12/idlelib/browser.py", + "path_type": "hardlink", + "sha256": "b607102a6e2ff7de241744008144a5480e2925098694be2a46003d8f60da0f52", + "sha256_in_prefix": "b607102a6e2ff7de241744008144a5480e2925098694be2a46003d8f60da0f52", + "size_in_bytes": 8588 + }, + { + "_path": "lib/python3.12/idlelib/calltip.py", + "path_type": "hardlink", + "sha256": "3a723fdf88c0018dfadd19757142a643b01b785c6df17a50bbe21463663ab590", + "sha256_in_prefix": "3a723fdf88c0018dfadd19757142a643b01b785c6df17a50bbe21463663ab590", + "size_in_bytes": 7267 + }, + { + "_path": "lib/python3.12/idlelib/calltip_w.py", + "path_type": "hardlink", + "sha256": "077e9d0d95946296077d5c95f343e242a7d250a6efece4afc58759b5e984e6c3", + "sha256_in_prefix": "077e9d0d95946296077d5c95f343e242a7d250a6efece4afc58759b5e984e6c3", + "size_in_bytes": 7083 + }, + { + "_path": "lib/python3.12/idlelib/codecontext.py", + "path_type": "hardlink", + "sha256": "628a13325b3bf2f76dea9254b20178b3232261f83c660f0e33785e6215dd6492", + "sha256_in_prefix": "628a13325b3bf2f76dea9254b20178b3232261f83c660f0e33785e6215dd6492", + "size_in_bytes": 11420 + }, + { + "_path": "lib/python3.12/idlelib/colorizer.py", + "path_type": "hardlink", + "sha256": "4de77a632286cf7cb616a2cf50dcd16a99d452fe7b16bf94c34950be97f293c2", + "sha256_in_prefix": "4de77a632286cf7cb616a2cf50dcd16a99d452fe7b16bf94c34950be97f293c2", + "size_in_bytes": 14783 + }, + { + "_path": "lib/python3.12/idlelib/config-extensions.def", + "path_type": "hardlink", + "sha256": "e75df0b77ff61253be457af636d5eb7c55a3ff2b6a733beea844d2b294972ebf", + "sha256_in_prefix": "e75df0b77ff61253be457af636d5eb7c55a3ff2b6a733beea844d2b294972ebf", + "size_in_bytes": 2266 + }, + { + "_path": "lib/python3.12/idlelib/config-highlight.def", + "path_type": "hardlink", + "sha256": "609eada44ff4aa9d5cd10ad8b4c29bb76db8ebc74912a0ae86f5ea3cd19b7547", + "sha256_in_prefix": "609eada44ff4aa9d5cd10ad8b4c29bb76db8ebc74912a0ae86f5ea3cd19b7547", + "size_in_bytes": 2864 + }, + { + "_path": "lib/python3.12/idlelib/config-keys.def", + "path_type": "hardlink", + "sha256": "bee81ba5c5abec1e35e313268f8d8fe72d305d0ad73abfba3d2ea1e2b2308710", + "sha256_in_prefix": "bee81ba5c5abec1e35e313268f8d8fe72d305d0ad73abfba3d2ea1e2b2308710", + "size_in_bytes": 10910 + }, + { + "_path": "lib/python3.12/idlelib/config-main.def", + "path_type": "hardlink", + "sha256": "e783704ad5cd9b3f44c026f55c98be2c52190bf9b7832251283f3e953ba80f87", + "sha256_in_prefix": "e783704ad5cd9b3f44c026f55c98be2c52190bf9b7832251283f3e953ba80f87", + "size_in_bytes": 3168 + }, + { + "_path": "lib/python3.12/idlelib/config.py", + "path_type": "hardlink", + "sha256": "226d4259cf50e32bb1c2b76b90e6914a9d1790171363d82d1c4c47ed9673aa9b", + "sha256_in_prefix": "226d4259cf50e32bb1c2b76b90e6914a9d1790171363d82d1c4c47ed9673aa9b", + "size_in_bytes": 38387 + }, + { + "_path": "lib/python3.12/idlelib/config_key.py", + "path_type": "hardlink", + "sha256": "856bd4b2c1fd7275856d3869cad8975f7770edbf021a93c64816a41c2322c2fa", + "sha256_in_prefix": "856bd4b2c1fd7275856d3869cad8975f7770edbf021a93c64816a41c2322c2fa", + "size_in_bytes": 15230 + }, + { + "_path": "lib/python3.12/idlelib/configdialog.py", + "path_type": "hardlink", + "sha256": "68a6a9470476408acdce5e3a8816196e025f8cccd0845bf1da579db19a5bba8c", + "sha256_in_prefix": "68a6a9470476408acdce5e3a8816196e025f8cccd0845bf1da579db19a5bba8c", + "size_in_bytes": 105314 + }, + { + "_path": "lib/python3.12/idlelib/debugger.py", + "path_type": "hardlink", + "sha256": "6e595d5a388e46b6b6e24490e970a3d355ec116a16a064bfca6ed86d4b17dcb4", + "sha256_in_prefix": "6e595d5a388e46b6b6e24490e970a3d355ec116a16a064bfca6ed86d4b17dcb4", + "size_in_bytes": 20991 + }, + { + "_path": "lib/python3.12/idlelib/debugger_r.py", + "path_type": "hardlink", + "sha256": "ddc797740231f068ca7c7c8610e799d72ad11af670d9bc0b6f9e04fe2ba222d1", + "sha256_in_prefix": "ddc797740231f068ca7c7c8610e799d72ad11af670d9bc0b6f9e04fe2ba222d1", + "size_in_bytes": 12115 + }, + { + "_path": "lib/python3.12/idlelib/debugobj.py", + "path_type": "hardlink", + "sha256": "aae9e2468a3d05366480864dc56689c65896757faf3b0364b8eef9feb4876a43", + "sha256_in_prefix": "aae9e2468a3d05366480864dc56689c65896757faf3b0364b8eef9feb4876a43", + "size_in_bytes": 4177 + }, + { + "_path": "lib/python3.12/idlelib/debugobj_r.py", + "path_type": "hardlink", + "sha256": "4e583b43fdf9bd4a731d70e074ee597aba03f3c8c36302bdc7e74650fb1fcc11", + "sha256_in_prefix": "4e583b43fdf9bd4a731d70e074ee597aba03f3c8c36302bdc7e74650fb1fcc11", + "size_in_bytes": 1082 + }, + { + "_path": "lib/python3.12/idlelib/delegator.py", + "path_type": "hardlink", + "sha256": "c2b31919d27056fc3aaa8f4ef798fbdf162665175fa9216d665f58ba2e4a464d", + "sha256_in_prefix": "c2b31919d27056fc3aaa8f4ef798fbdf162665175fa9216d665f58ba2e4a464d", + "size_in_bytes": 1044 + }, + { + "_path": "lib/python3.12/idlelib/dynoption.py", + "path_type": "hardlink", + "sha256": "29933f56722b2efb5cf451825a7fe50f357983e68f6a261afdf89b52f778e488", + "sha256_in_prefix": "29933f56722b2efb5cf451825a7fe50f357983e68f6a261afdf89b52f778e488", + "size_in_bytes": 1993 + }, + { + "_path": "lib/python3.12/idlelib/editor.py", + "path_type": "hardlink", + "sha256": "e277fc183eefdf1fc20acfbd18a6bdde4988d0193edd27cb8e865e74f798c897", + "sha256_in_prefix": "e277fc183eefdf1fc20acfbd18a6bdde4988d0193edd27cb8e865e74f798c897", + "size_in_bytes": 69561 + }, + { + "_path": "lib/python3.12/idlelib/extend.txt", + "path_type": "hardlink", + "sha256": "5bceaf660c46faf8f9fbf2be5e23389d6e6477d1e458fee680e606bcc95d2853", + "sha256_in_prefix": "5bceaf660c46faf8f9fbf2be5e23389d6e6477d1e458fee680e606bcc95d2853", + "size_in_bytes": 3631 + }, + { + "_path": "lib/python3.12/idlelib/filelist.py", + "path_type": "hardlink", + "sha256": "64e194e4514141414ecb231ac165ed861749bb0d31d0758c7c3a823ce154abe1", + "sha256_in_prefix": "64e194e4514141414ecb231ac165ed861749bb0d31d0758c7c3a823ce154abe1", + "size_in_bytes": 3871 + }, + { + "_path": "lib/python3.12/idlelib/format.py", + "path_type": "hardlink", + "sha256": "dc2b00fb239f38543bf973d94daef2c52457b905d4d89c640993823127b7923c", + "sha256_in_prefix": "dc2b00fb239f38543bf973d94daef2c52457b905d4d89c640993823127b7923c", + "size_in_bytes": 15777 + }, + { + "_path": "lib/python3.12/idlelib/grep.py", + "path_type": "hardlink", + "sha256": "f5a9327c83e7aecec64efb81bf9f4542a4f3e0a13d0b6443e8eca5dfbb509835", + "sha256_in_prefix": "f5a9327c83e7aecec64efb81bf9f4542a4f3e0a13d0b6443e8eca5dfbb509835", + "size_in_bytes": 7526 + }, + { + "_path": "lib/python3.12/idlelib/help.html", + "path_type": "hardlink", + "sha256": "ac81ab586d33514ce0f303cf02d04bc9a2184569c82f4c85fed7c16b209e6dbb", + "sha256_in_prefix": "ac81ab586d33514ce0f303cf02d04bc9a2184569c82f4c85fed7c16b209e6dbb", + "size_in_bytes": 78525 + }, + { + "_path": "lib/python3.12/idlelib/help.py", + "path_type": "hardlink", + "sha256": "35f26243be00070246751349d864ffc576242b38aa559ed536e7b635819ea847", + "sha256_in_prefix": "35f26243be00070246751349d864ffc576242b38aa559ed536e7b635819ea847", + "size_in_bytes": 11902 + }, + { + "_path": "lib/python3.12/idlelib/help_about.py", + "path_type": "hardlink", + "sha256": "93aec712aa0f1899597c52697d859cf26c63163ee355e456f0e20b984dcfdfdf", + "sha256_in_prefix": "93aec712aa0f1899597c52697d859cf26c63163ee355e456f0e20b984dcfdfdf", + "size_in_bytes": 8910 + }, + { + "_path": "lib/python3.12/idlelib/history.py", + "path_type": "hardlink", + "sha256": "f91f1568d083bdbc856d38ef48493bcb138c6a492d523385b300a5bac30133e6", + "sha256_in_prefix": "f91f1568d083bdbc856d38ef48493bcb138c6a492d523385b300a5bac30133e6", + "size_in_bytes": 4065 + }, + { + "_path": "lib/python3.12/idlelib/hyperparser.py", + "path_type": "hardlink", + "sha256": "18563d2b4c248aed70b7f29fd903fd51d1b5aceb3dc93c23f9a54141eed7a9b0", + "sha256_in_prefix": "18563d2b4c248aed70b7f29fd903fd51d1b5aceb3dc93c23f9a54141eed7a9b0", + "size_in_bytes": 12889 + }, + { + "_path": "lib/python3.12/idlelib/idle.bat", + "path_type": "hardlink", + "sha256": "15a3977f0d2c6a8e87db2ef7050ea10afb3a88b064bf5ef95439924e42464114", + "sha256_in_prefix": "15a3977f0d2c6a8e87db2ef7050ea10afb3a88b064bf5ef95439924e42464114", + "size_in_bytes": 177 + }, + { + "_path": "lib/python3.12/idlelib/idle.py", + "path_type": "hardlink", + "sha256": "33ffa2f718e123fd1c4e536bb4a471978515787ee9fbf7806a92073a787a733a", + "sha256_in_prefix": "33ffa2f718e123fd1c4e536bb4a471978515787ee9fbf7806a92073a787a733a", + "size_in_bytes": 454 + }, + { + "_path": "lib/python3.12/idlelib/idle.pyw", + "path_type": "hardlink", + "sha256": "26101d297127132c5e9634499f41ad00e125ea308343a20b278bee9e9225eb5c", + "sha256_in_prefix": "26101d297127132c5e9634499f41ad00e125ea308343a20b278bee9e9225eb5c", + "size_in_bytes": 570 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/README.txt", + "path_type": "hardlink", + "sha256": "94cca8aab706b6ceb5d9ed44cad93127988c9370cdde250a53bec9b132261f05", + "sha256_in_prefix": "94cca8aab706b6ceb5d9ed44cad93127988c9370cdde250a53bec9b132261f05", + "size_in_bytes": 8880 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__init__.py", + "path_type": "hardlink", + "sha256": "0a7370f8ab516e0944f381fcecee02ac660926551b3eb543f88ace3ef024ca70", + "sha256_in_prefix": "0a7370f8ab516e0944f381fcecee02ac660926551b3eb543f88ace3ef024ca70", + "size_in_bytes": 1250 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c338b0ebaffa9b7b9c128a9f46e4ddaca1bb1378398eb33f204a6e932379b07b", + "sha256_in_prefix": "c338b0ebaffa9b7b9c128a9f46e4ddaca1bb1378398eb33f204a6e932379b07b", + "size_in_bytes": 950 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/htest.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b94778ce3bf50020457c25fa996723ff7f252ac01ff2294618a1bbce2bfff750", + "sha256_in_prefix": "b94778ce3bf50020457c25fa996723ff7f252ac01ff2294618a1bbce2bfff750", + "size_in_bytes": 16368 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/mock_idle.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f93563da4eeaa1d7586b1202b1e7a9989c6caff506f85b89b2db20a203374b78", + "sha256_in_prefix": "f93563da4eeaa1d7586b1202b1e7a9989c6caff506f85b89b2db20a203374b78", + "size_in_bytes": 3172 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/mock_tk.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b19875ade728b064560a6e1c4a5d115d378ec0aa52fea8c4806d86f052427ca2", + "sha256_in_prefix": "b19875ade728b064560a6e1c4a5d115d378ec0aa52fea8c4806d86f052427ca2", + "size_in_bytes": 14073 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/template.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fe3f789b73f1ac8b2ff882acfab1b92191b9b9c8ca8a11cb6d73ac88f5ff2564", + "sha256_in_prefix": "fe3f789b73f1ac8b2ff882acfab1b92191b9b9c8ca8a11cb6d73ac88f5ff2564", + "size_in_bytes": 1456 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_autocomplete.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3e7bd67ddcdf030756554f8d72cb1b15f5511e9424d6b04053989ef4dff18124", + "sha256_in_prefix": "3e7bd67ddcdf030756554f8d72cb1b15f5511e9424d6b04053989ef4dff18124", + "size_in_bytes": 18673 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_autocomplete_w.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "35d0fcd634530d376e56305923b9e90fbb191a87e9a034cf1610aabf3e494cee", + "sha256_in_prefix": "35d0fcd634530d376e56305923b9e90fbb191a87e9a034cf1610aabf3e494cee", + "size_in_bytes": 1924 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_autoexpand.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4e3b25ee7b1348ff80f3525dcb77b5ad7d134af2f66f99e68469c3a5266d1721", + "sha256_in_prefix": "4e3b25ee7b1348ff80f3525dcb77b5ad7d134af2f66f99e68469c3a5266d1721", + "size_in_bytes": 6985 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_browser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8dfc2231f42001a28101239f15aca04dd7550f7e44b0257cb1be78a0746c85a1", + "sha256_in_prefix": "8dfc2231f42001a28101239f15aca04dd7550f7e44b0257cb1be78a0746c85a1", + "size_in_bytes": 17047 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_calltip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8a4416668f3ed4864ee64c5942feb1477be3620b3e195002c0b97ad7db4f1d29", + "sha256_in_prefix": "8a4416668f3ed4864ee64c5942feb1477be3620b3e195002c0b97ad7db4f1d29", + "size_in_bytes": 26593 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_calltip_w.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f4b5a45d45d2751d9849ac95d27daa931b2b0ca2adb5e486774416898448fbe6", + "sha256_in_prefix": "f4b5a45d45d2751d9849ac95d27daa931b2b0ca2adb5e486774416898448fbe6", + "size_in_bytes": 1864 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_codecontext.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9d2122fcd50fa0527ad04d6e7dc83c3d2bc991cc9c66b5400cc3e1cdbceacea4", + "sha256_in_prefix": "9d2122fcd50fa0527ad04d6e7dc83c3d2bc991cc9c66b5400cc3e1cdbceacea4", + "size_in_bytes": 21630 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_colorizer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f54e11a61eddf6e7e35beb42804edf800c2244abaad1c1223b6e56200068a34d", + "sha256_in_prefix": "f54e11a61eddf6e7e35beb42804edf800c2244abaad1c1223b6e56200068a34d", + "size_in_bytes": 31850 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_config.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "70b92a872b89be6c8bf9c0d4ac5fab140ef83f367e4e252a8c80cbef0529b5ff", + "sha256_in_prefix": "70b92a872b89be6c8bf9c0d4ac5fab140ef83f367e4e252a8c80cbef0529b5ff", + "size_in_bytes": 48220 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_config_key.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5f6516840026bc8dd438e501b4320a8b0753a3005c241006eeba588a12780122", + "sha256_in_prefix": "5f6516840026bc8dd438e501b4320a8b0753a3005c241006eeba588a12780122", + "size_in_bytes": 22068 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_configdialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ed6033e4b43623adc3a1a313bab3975b6ef232434ef6227428f2c40416c02327", + "sha256_in_prefix": "ed6033e4b43623adc3a1a313bab3975b6ef232434ef6227428f2c40416c02327", + "size_in_bytes": 91122 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_debugger.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a8c25f7aff09d9a5ba0c0b0e7834468828da0364dd45901b50a4fe25e8f938d2", + "sha256_in_prefix": "a8c25f7aff09d9a5ba0c0b0e7834468828da0364dd45901b50a4fe25e8f938d2", + "size_in_bytes": 18140 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_debugger_r.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "41f23b0a4b2341d60ded9161d477e8e10fad3582f86a83ce08121fa0bd8fbf59", + "sha256_in_prefix": "41f23b0a4b2341d60ded9161d477e8e10fad3582f86a83ce08121fa0bd8fbf59", + "size_in_bytes": 1512 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_debugobj.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "718f1584348ce72400b72d51ac52a4225d4e805de83d3f8898a927df6410ca94", + "sha256_in_prefix": "718f1584348ce72400b72d51ac52a4225d4e805de83d3f8898a927df6410ca94", + "size_in_bytes": 4117 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_debugobj_r.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6e2843d58abbc51e5d39b40c695facea8d26e00e1bf866fbbf13b887b625fb30", + "sha256_in_prefix": "6e2843d58abbc51e5d39b40c695facea8d26e00e1bf866fbbf13b887b625fb30", + "size_in_bytes": 1573 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_delegator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3f94638f0f895dac8045fe9f471da193ab138b4145c71f49615acf59b8625ea3", + "sha256_in_prefix": "3f94638f0f895dac8045fe9f471da193ab138b4145c71f49615acf59b8625ea3", + "size_in_bytes": 2088 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_editmenu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "60193910ad31a881a5acda899a78e64f3e95010148310d85771674f2ebe245f7", + "sha256_in_prefix": "60193910ad31a881a5acda899a78e64f3e95010148310d85771674f2ebe245f7", + "size_in_bytes": 4635 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_editor.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "82e7c0252e75ef68af4add06c446ee720ec5e0feeecfb157ff8e5c4ba5d5557f", + "sha256_in_prefix": "82e7c0252e75ef68af4add06c446ee720ec5e0feeecfb157ff8e5c4ba5d5557f", + "size_in_bytes": 11175 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_filelist.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a8221981dddc3448a85782dcea1fcb9d75cef4167dc8f3770256f86c5aa49761", + "sha256_in_prefix": "a8221981dddc3448a85782dcea1fcb9d75cef4167dc8f3770256f86c5aa49761", + "size_in_bytes": 2135 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_format.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5e61b45fdb75872c0164729ddb99d459351108f7b820f0994b6e9ffbdbe92849", + "sha256_in_prefix": "5e61b45fdb75872c0164729ddb99d459351108f7b820f0994b6e9ffbdbe92849", + "size_in_bytes": 32980 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_grep.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bb61501c34fadc9962d008ff8212a8cdab6245c8a2fea500f529ebd7afde60d2", + "sha256_in_prefix": "bb61501c34fadc9962d008ff8212a8cdab6245c8a2fea500f529ebd7afde60d2", + "size_in_bytes": 8472 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_help.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1b7b438668c3a7aaaf1add71d7c408a6bcf7324008f36449992c380a14e0a58f", + "sha256_in_prefix": "1b7b438668c3a7aaaf1add71d7c408a6bcf7324008f36449992c380a14e0a58f", + "size_in_bytes": 2170 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_help_about.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "555a6682b6c745e4ded443b4982655706615d8fcc11dbd4fe042d6e167416f30", + "sha256_in_prefix": "555a6682b6c745e4ded443b4982655706615d8fcc11dbd4fe042d6e167416f30", + "size_in_bytes": 11327 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_history.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b01018c33c4ea7d79c663720b3d4dca82408d3ce99abe3b108281a455d1ccfce", + "sha256_in_prefix": "b01018c33c4ea7d79c663720b3d4dca82408d3ce99abe3b108281a455d1ccfce", + "size_in_bytes": 10828 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_hyperparser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fdb21da162fbabbd967b3fd94c94d360a64bd70cfb58055905ae53dd6cb593ec", + "sha256_in_prefix": "fdb21da162fbabbd967b3fd94c94d360a64bd70cfb58055905ae53dd6cb593ec", + "size_in_bytes": 14641 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_iomenu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "324059eb371f39c20275cdfdb2326d4ab621b1c369358122ea6bebbec9fea3df", + "sha256_in_prefix": "324059eb371f39c20275cdfdb2326d4ab621b1c369358122ea6bebbec9fea3df", + "size_in_bytes": 4984 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_macosx.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4b5cce3e1ebeaa3144fca96a7f287fa37cb73bf3295a5fa2615c3b0e10617e79", + "sha256_in_prefix": "4b5cce3e1ebeaa3144fca96a7f287fa37cb73bf3295a5fa2615c3b0e10617e79", + "size_in_bytes": 6697 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_mainmenu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5a8fe5715f33d43944fda42c8a7c99ae4028a80129842f0d6f2c7df55211ed25", + "sha256_in_prefix": "5a8fe5715f33d43944fda42c8a7c99ae4028a80129842f0d6f2c7df55211ed25", + "size_in_bytes": 2439 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_multicall.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cfd9fe223f1e31a670a5836264ef76d8d18267b656e018baea515492276a4926", + "sha256_in_prefix": "cfd9fe223f1e31a670a5836264ef76d8d18267b656e018baea515492276a4926", + "size_in_bytes": 2881 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_outwin.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "53882205201b30a4f60243c564de350b6f56aef390b2089d0d70553e3ffdaadf", + "sha256_in_prefix": "53882205201b30a4f60243c564de350b6f56aef390b2089d0d70553e3ffdaadf", + "size_in_bytes": 9215 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_parenmatch.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a509cc3661891481cd4c872df3dad3e1dc48ff52e67ad9cd849717666d16e2b6", + "sha256_in_prefix": "a509cc3661891481cd4c872df3dad3e1dc48ff52e67ad9cd849717666d16e2b6", + "size_in_bytes": 6128 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_pathbrowser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bdbd478c49a631a7c1225ce8889aea482a5279d016cbc6a56b8baa5fbac672b7", + "sha256_in_prefix": "bdbd478c49a631a7c1225ce8889aea482a5279d016cbc6a56b8baa5fbac672b7", + "size_in_bytes": 5786 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_percolator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2165495a66e648f0b419a8bb7d75b3c0fb2be81ac7883040dc21f6dcae29e975", + "sha256_in_prefix": "2165495a66e648f0b419a8bb7d75b3c0fb2be81ac7883040dc21f6dcae29e975", + "size_in_bytes": 9121 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_pyparse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f8e1a1ede2d71c05a827e45c33d47a42399e1d5c0da24c8aeaf4e69eed3d1329", + "sha256_in_prefix": "f8e1a1ede2d71c05a827e45c33d47a42399e1d5c0da24c8aeaf4e69eed3d1329", + "size_in_bytes": 23072 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_pyshell.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c18834ce8312a82d92207aa023f4f5f8fede413a8285cbd6c3f8fa560cd1cbf4", + "sha256_in_prefix": "c18834ce8312a82d92207aa023f4f5f8fede413a8285cbd6c3f8fa560cd1cbf4", + "size_in_bytes": 9127 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_query.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4585e05fb7cb77aeb3956b7cea6cf27652a1ace03e5ce48469382c6b744aec1f", + "sha256_in_prefix": "4585e05fb7cb77aeb3956b7cea6cf27652a1ace03e5ce48469382c6b744aec1f", + "size_in_bytes": 31838 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_redirector.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "300383f11a00e742f7a14b2427206266d4555628c8a56da74851261a2c2e4fab", + "sha256_in_prefix": "300383f11a00e742f7a14b2427206266d4555628c8a56da74851261a2c2e4fab", + "size_in_bytes": 9502 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_replace.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9b5441d99a5eaf0b9e5e9a59bde8fad099cc33bb7e481d00fd1f02ede291ecb5", + "sha256_in_prefix": "9b5441d99a5eaf0b9e5e9a59bde8fad099cc33bb7e481d00fd1f02ede291ecb5", + "size_in_bytes": 15294 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_rpc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "839765ec560b3e643ea327e2d422ef9d77c05c44b3aa86d1087ac4dae00f463c", + "sha256_in_prefix": "839765ec560b3e643ea327e2d422ef9d77c05c44b3aa86d1087ac4dae00f463c", + "size_in_bytes": 2295 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_run.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ffb5701521431a303b501d8d9e96997e8b292cf175c620bb0ff9c151a2bbd2a3", + "sha256_in_prefix": "ffb5701521431a303b501d8d9e96997e8b292cf175c620bb0ff9c151a2bbd2a3", + "size_in_bytes": 30913 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_runscript.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "05da1ef8388da43285f44ad649762bb03673123178f8fadfbf9de4ebf2854768", + "sha256_in_prefix": "05da1ef8388da43285f44ad649762bb03673123178f8fadfbf9de4ebf2854768", + "size_in_bytes": 1968 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_scrolledlist.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2ce05a4423be05f0e6549e8380de4d416ee157c4e5796664e17ed45ee1f20ff0", + "sha256_in_prefix": "2ce05a4423be05f0e6549e8380de4d416ee157c4e5796664e17ed45ee1f20ff0", + "size_in_bytes": 1377 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_search.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da0995aec081a0dcd046a0ef03b165822c52e5bd3253f2b3ab85d6ab686f5039", + "sha256_in_prefix": "da0995aec081a0dcd046a0ef03b165822c52e5bd3253f2b3ab85d6ab686f5039", + "size_in_bytes": 4680 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_searchbase.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8d8ff57ff66f9c5c7971f38b2b4d6abe446c7dd59fde91201238d7970f3db882", + "sha256_in_prefix": "8d8ff57ff66f9c5c7971f38b2b4d6abe446c7dd59fde91201238d7970f3db882", + "size_in_bytes": 10236 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_searchengine.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a5ec6566944716e9023cead5351aac896635ca8973623b02b472b6e18c0ac36d", + "sha256_in_prefix": "a5ec6566944716e9023cead5351aac896635ca8973623b02b472b6e18c0ac36d", + "size_in_bytes": 17780 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_sidebar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "018e32dc18d47b74f0d7fe5c2addb31c8c6f5578eb2d2922a9118e2c6ad293e0", + "sha256_in_prefix": "018e32dc18d47b74f0d7fe5c2addb31c8c6f5578eb2d2922a9118e2c6ad293e0", + "size_in_bytes": 45614 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_squeezer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "51fa0b87c8158ef25ef94b7e947f5f3580f494dd3d2d79b202c8c335b6d334f8", + "sha256_in_prefix": "51fa0b87c8158ef25ef94b7e947f5f3580f494dd3d2d79b202c8c335b6d334f8", + "size_in_bytes": 27164 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_stackviewer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f799e5e599f729f0d58fc9df926e7c1de81ed00213a2f11389735b935aec293a", + "sha256_in_prefix": "f799e5e599f729f0d58fc9df926e7c1de81ed00213a2f11389735b935aec293a", + "size_in_bytes": 2127 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_statusbar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8139d10c868e2e8f3e4bd78f76663ccf0aa15d9b76a90e112e12aec36b7184cc", + "sha256_in_prefix": "8139d10c868e2e8f3e4bd78f76663ccf0aa15d9b76a90e112e12aec36b7184cc", + "size_in_bytes": 2549 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_text.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "55e23e75311d779acaa46d482a9e35037e2ba65262a42e642df486cb8da279d3", + "sha256_in_prefix": "55e23e75311d779acaa46d482a9e35037e2ba65262a42e642df486cb8da279d3", + "size_in_bytes": 11433 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_textview.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8f39ab0b71ed5fad0f2785d0b7ce2a4fb183f41ec0b9628a85601cb34354797d", + "sha256_in_prefix": "8f39ab0b71ed5fad0f2785d0b7ce2a4fb183f41ec0b9628a85601cb34354797d", + "size_in_bytes": 15596 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_tooltip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cf8a8aad1b3bccd4b66aa1ce7c55ceb83a6be7130973e9e26326bf75c4da7229", + "sha256_in_prefix": "cf8a8aad1b3bccd4b66aa1ce7c55ceb83a6be7130973e9e26326bf75c4da7229", + "size_in_bytes": 9814 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_tree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "16ed89681020ba58cb68ed90617ee3bd41b731a205fb37edeee0d8979aad815a", + "sha256_in_prefix": "16ed89681020ba58cb68ed90617ee3bd41b731a205fb37edeee0d8979aad815a", + "size_in_bytes": 3841 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_undo.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ecfcdbd050b836648a6431ddcd3b6263680037fc9913ca3dcf8f387e1ec4bb1d", + "sha256_in_prefix": "ecfcdbd050b836648a6431ddcd3b6263680037fc9913ca3dcf8f387e1ec4bb1d", + "size_in_bytes": 8042 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2948ba576ec2b6e765e8ebf5e6213ef49f92975f3d138b4c9201aee697b0a5a0", + "sha256_in_prefix": "2948ba576ec2b6e765e8ebf5e6213ef49f92975f3d138b4c9201aee697b0a5a0", + "size_in_bytes": 878 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_warning.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cd6c759c1e8f7354a2f27ebdfff4161aac839f25ea5f1e99b9a5a2577680e81d", + "sha256_in_prefix": "cd6c759c1e8f7354a2f27ebdfff4161aac839f25ea5f1e99b9a5a2577680e81d", + "size_in_bytes": 4340 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_window.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "503a09202e3d41706afc955ba06bcdccf2d230b9ea5043469c778e6ebe45d85f", + "sha256_in_prefix": "503a09202e3d41706afc955ba06bcdccf2d230b9ea5043469c778e6ebe45d85f", + "size_in_bytes": 2492 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_zoomheight.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "49b58d59295aec2c1d359904e4f6b5746246ce4a12f72f1b033f113396e6a1d7", + "sha256_in_prefix": "49b58d59295aec2c1d359904e4f6b5746246ce4a12f72f1b033f113396e6a1d7", + "size_in_bytes": 2399 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/test_zzdummy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "201a5e027456b35526f31c577832c4876457718b6332afc9b693902ed56cf5d8", + "sha256_in_prefix": "201a5e027456b35526f31c577832c4876457718b6332afc9b693902ed56cf5d8", + "size_in_bytes": 8259 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/__pycache__/tkinter_testing_utils.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "442a93be5bd2e2c816dd7890fac99ac4bb5c6cbda135067fba4609d6ad72611f", + "sha256_in_prefix": "442a93be5bd2e2c816dd7890fac99ac4bb5c6cbda135067fba4609d6ad72611f", + "size_in_bytes": 2656 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/example_noext", + "path_type": "hardlink", + "sha256": "526edff5d21fd1f1421f5ab6a706cb51732edcae235b9895f93a8f46e25505fe", + "sha256_in_prefix": "526edff5d21fd1f1421f5ab6a706cb51732edcae235b9895f93a8f46e25505fe", + "size_in_bytes": 68 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/example_stub.pyi", + "path_type": "hardlink", + "sha256": "e89a8196b490fe728f31af590b3bbca69bddc7aec8cbf09d2a5ae0953240ac56", + "sha256_in_prefix": "e89a8196b490fe728f31af590b3bbca69bddc7aec8cbf09d2a5ae0953240ac56", + "size_in_bytes": 154 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/htest.py", + "path_type": "hardlink", + "sha256": "8c0413ab3067d28fe93f40e2e1da410414095ab278f63fc578a9d8452f98eb5c", + "sha256_in_prefix": "8c0413ab3067d28fe93f40e2e1da410414095ab278f63fc578a9d8452f98eb5c", + "size_in_bytes": 15313 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/mock_idle.py", + "path_type": "hardlink", + "sha256": "637d74d26089c582fb784c2920f5bcb41e5b1fc8b9e0931ddc1cc8d92becbff4", + "sha256_in_prefix": "637d74d26089c582fb784c2920f5bcb41e5b1fc8b9e0931ddc1cc8d92becbff4", + "size_in_bytes": 1943 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/mock_tk.py", + "path_type": "hardlink", + "sha256": "7d60a26e82fd0469a95e02c2adda6607363a51ab67d5851cc323a58a595f74a7", + "sha256_in_prefix": "7d60a26e82fd0469a95e02c2adda6607363a51ab67d5851cc323a58a595f74a7", + "size_in_bytes": 11693 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/template.py", + "path_type": "hardlink", + "sha256": "43421286ad234a4240f8d4bc09f67bb58da0bf9d9b07bf93010989ef2c17f2f8", + "sha256_in_prefix": "43421286ad234a4240f8d4bc09f67bb58da0bf9d9b07bf93010989ef2c17f2f8", + "size_in_bytes": 642 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_autocomplete.py", + "path_type": "hardlink", + "sha256": "0ee1af80bb645bd57e6f6383f5e5473f901e9d40524992abf9c48a4163997eef", + "sha256_in_prefix": "0ee1af80bb645bd57e6f6383f5e5473f901e9d40524992abf9c48a4163997eef", + "size_in_bytes": 11093 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_autocomplete_w.py", + "path_type": "hardlink", + "sha256": "f8cd80196c2841f65f53ca5ae1c4fb99c7c215b29cf88774e0b189c99e4cee79", + "sha256_in_prefix": "f8cd80196c2841f65f53ca5ae1c4fb99c7c215b29cf88774e0b189c99e4cee79", + "size_in_bytes": 720 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_autoexpand.py", + "path_type": "hardlink", + "sha256": "85f913f8cbd5dfd5d52d3b7d00eedec231ec3e4ee7d117db4a2bb714eb1a7243", + "sha256_in_prefix": "85f913f8cbd5dfd5d52d3b7d00eedec231ec3e4ee7d117db4a2bb714eb1a7243", + "size_in_bytes": 4638 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_browser.py", + "path_type": "hardlink", + "sha256": "bdfd3bd9ab02ee535e77f3233920f80891eb84d7042f7db381afc7766b3702eb", + "sha256_in_prefix": "bdfd3bd9ab02ee535e77f3233920f80891eb84d7042f7db381afc7766b3702eb", + "size_in_bytes": 8420 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_calltip.py", + "path_type": "hardlink", + "sha256": "a67efd1c92e824321254f615d35a72508ee09d75e1058c3d01ad7d8bf3be1ebf", + "sha256_in_prefix": "a67efd1c92e824321254f615d35a72508ee09d75e1058c3d01ad7d8bf3be1ebf", + "size_in_bytes": 13658 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_calltip_w.py", + "path_type": "hardlink", + "sha256": "7462c048c689f82c3ae6b5782a18776762f88055b80ae77a92243b6c0606e004", + "sha256_in_prefix": "7462c048c689f82c3ae6b5782a18776762f88055b80ae77a92243b6c0606e004", + "size_in_bytes": 686 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_codecontext.py", + "path_type": "hardlink", + "sha256": "84e6b890b22b2abcc0865c691162b93c6ffb9b4e17f05011bdaffa770a52fcf0", + "sha256_in_prefix": "84e6b890b22b2abcc0865c691162b93c6ffb9b4e17f05011bdaffa770a52fcf0", + "size_in_bytes": 16082 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_colorizer.py", + "path_type": "hardlink", + "sha256": "6a3fbb630e0ecc7aafc9c8bc56ece3462911c733aa3bb4c52ee55c1d897301d4", + "sha256_in_prefix": "6a3fbb630e0ecc7aafc9c8bc56ece3462911c733aa3bb4c52ee55c1d897301d4", + "size_in_bytes": 22882 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_config.py", + "path_type": "hardlink", + "sha256": "02546eb557e57b1654da9016cf56f1826869f3e6c78bcafffb8a89013641c1a1", + "sha256_in_prefix": "02546eb557e57b1654da9016cf56f1826869f3e6c78bcafffb8a89013641c1a1", + "size_in_bytes": 32091 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_config_key.py", + "path_type": "hardlink", + "sha256": "54d0c65e1f66d37c415d3fe533c8db891974f08e8fca6374596280d64db86586", + "sha256_in_prefix": "54d0c65e1f66d37c415d3fe533c8db891974f08e8fca6374596280d64db86586", + "size_in_bytes": 11462 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_configdialog.py", + "path_type": "hardlink", + "sha256": "56685b99d406c974ffce84260b08b06476b1e98f701d0675c378d86c8f19f579", + "sha256_in_prefix": "56685b99d406c974ffce84260b08b06476b1e98f701d0675c378d86c8f19f579", + "size_in_bytes": 55389 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_debugger.py", + "path_type": "hardlink", + "sha256": "8117fa37bf2c4266809f3a41c7c37c603c6a390b235801504123ea533c55d7cc", + "sha256_in_prefix": "8117fa37bf2c4266809f3a41c7c37c603c6a390b235801504123ea533c55d7cc", + "size_in_bytes": 9727 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_debugger_r.py", + "path_type": "hardlink", + "sha256": "ccc0ba5e03ee1df449f78a164efdc6739f5a530315ab3971ac05c652bc779cea", + "sha256_in_prefix": "ccc0ba5e03ee1df449f78a164efdc6739f5a530315ab3971ac05c652bc779cea", + "size_in_bytes": 965 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_debugobj.py", + "path_type": "hardlink", + "sha256": "5427a574cfcfd36a48e365f6f8864b226ee8d7eb48702ff1496570302b1d9acc", + "sha256_in_prefix": "5427a574cfcfd36a48e365f6f8864b226ee8d7eb48702ff1496570302b1d9acc", + "size_in_bytes": 1611 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_debugobj_r.py", + "path_type": "hardlink", + "sha256": "22d74368ba175175b9c14315f9d82fd7ddde60ae93d2e5572e9a647de7e869eb", + "sha256_in_prefix": "22d74368ba175175b9c14315f9d82fd7ddde60ae93d2e5572e9a647de7e869eb", + "size_in_bytes": 545 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_delegator.py", + "path_type": "hardlink", + "sha256": "559d39df8c1ff38d177943f245b87f5379ee5ea93399fd6b5f7bfa882e6ed8ca", + "sha256_in_prefix": "559d39df8c1ff38d177943f245b87f5379ee5ea93399fd6b5f7bfa882e6ed8ca", + "size_in_bytes": 1567 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_editmenu.py", + "path_type": "hardlink", + "sha256": "ed3800137d48ffcf86ecb71afe5a24cd9ed381571f23036438ba8a97f502326a", + "sha256_in_prefix": "ed3800137d48ffcf86ecb71afe5a24cd9ed381571f23036438ba8a97f502326a", + "size_in_bytes": 2564 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_editor.py", + "path_type": "hardlink", + "sha256": "654ae5ca7f747a4a88d2868de48c7bff1f35b26098075f840722e955fe4cb83e", + "sha256_in_prefix": "654ae5ca7f747a4a88d2868de48c7bff1f35b26098075f840722e955fe4cb83e", + "size_in_bytes": 8151 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_filelist.py", + "path_type": "hardlink", + "sha256": "d4cea5fdba68fb9e361541820d44eed003c317f4ef14bb9df3406b8d2c53ef7c", + "sha256_in_prefix": "d4cea5fdba68fb9e361541820d44eed003c317f4ef14bb9df3406b8d2c53ef7c", + "size_in_bytes": 795 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_format.py", + "path_type": "hardlink", + "sha256": "b356a2a8f5fe14c39c6af73623484df4ed930cc16ef4605f3b04fd9b618867a6", + "sha256_in_prefix": "b356a2a8f5fe14c39c6af73623484df4ed930cc16ef4605f3b04fd9b618867a6", + "size_in_bytes": 23610 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_grep.py", + "path_type": "hardlink", + "sha256": "ca64de882b5608e016b7df8f739089c9f262643bce09979b76399cc4be1ea12c", + "sha256_in_prefix": "ca64de882b5608e016b7df8f739089c9f262643bce09979b76399cc4be1ea12c", + "size_in_bytes": 5072 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_help.py", + "path_type": "hardlink", + "sha256": "0513a2872307b45ea7869b7e07dc437d7e8c69524073513b96374397f371b32a", + "sha256_in_prefix": "0513a2872307b45ea7869b7e07dc437d7e8c69524073513b96374397f371b32a", + "size_in_bytes": 863 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_help_about.py", + "path_type": "hardlink", + "sha256": "47663dfbcddced35ad97631cebb690a30ab3aa724bde0a7174d11290ac79eb02", + "sha256_in_prefix": "47663dfbcddced35ad97631cebb690a30ab3aa724bde0a7174d11290ac79eb02", + "size_in_bytes": 5904 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_history.py", + "path_type": "hardlink", + "sha256": "6319fe7810ed91786b503de80701a291a4f9abe54c9e101c19c0917b709e62f3", + "sha256_in_prefix": "6319fe7810ed91786b503de80701a291a4f9abe54c9e101c19c0917b709e62f3", + "size_in_bytes": 5517 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_hyperparser.py", + "path_type": "hardlink", + "sha256": "cd2fbc788d4d75b514e53951dc90d00d41a8a87baad31bc1e380b7449bfcf183", + "sha256_in_prefix": "cd2fbc788d4d75b514e53951dc90d00d41a8a87baad31bc1e380b7449bfcf183", + "size_in_bytes": 9082 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_iomenu.py", + "path_type": "hardlink", + "sha256": "8250eb60ea1d7760589febf38c171c8c6e202e527a680030233539db59439d8d", + "sha256_in_prefix": "8250eb60ea1d7760589febf38c171c8c6e202e527a680030233539db59439d8d", + "size_in_bytes": 2457 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_macosx.py", + "path_type": "hardlink", + "sha256": "975e48ab453711c5072988e2e66a7fe51e716ac64e494f022a5ff82781ccd368", + "sha256_in_prefix": "975e48ab453711c5072988e2e66a7fe51e716ac64e494f022a5ff82781ccd368", + "size_in_bytes": 3444 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_mainmenu.py", + "path_type": "hardlink", + "sha256": "faa064ffd9c8e30b1205e46bb4ede816c74b7948cfa34c7795ed19c35eac10d5", + "sha256_in_prefix": "faa064ffd9c8e30b1205e46bb4ede816c74b7948cfa34c7795ed19c35eac10d5", + "size_in_bytes": 1638 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_multicall.py", + "path_type": "hardlink", + "sha256": "1bfb51912275d8e346dce0a40ab84316b15e3f142e66529a8c9cfd52210c1a1f", + "sha256_in_prefix": "1bfb51912275d8e346dce0a40ab84316b15e3f142e66529a8c9cfd52210c1a1f", + "size_in_bytes": 1317 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_outwin.py", + "path_type": "hardlink", + "sha256": "4f0590e1fe9af387fa627cb8a40cd7618da5d2a46ce4b33446d54f6fbcce2105", + "sha256_in_prefix": "4f0590e1fe9af387fa627cb8a40cd7618da5d2a46ce4b33446d54f6fbcce2105", + "size_in_bytes": 5417 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_parenmatch.py", + "path_type": "hardlink", + "sha256": "5e0ba86116e28d46e7db9ed33d85cf7caa837e1779e1b8feb5f6b6b4a837551e", + "sha256_in_prefix": "5e0ba86116e28d46e7db9ed33d85cf7caa837e1779e1b8feb5f6b6b4a837551e", + "size_in_bytes": 3544 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_pathbrowser.py", + "path_type": "hardlink", + "sha256": "a7d9c5085ff5c64232897f6ee0a09258a41a35f153f47ff0f3b8fa97ec67be9e", + "sha256_in_prefix": "a7d9c5085ff5c64232897f6ee0a09258a41a35f153f47ff0f3b8fa97ec67be9e", + "size_in_bytes": 2422 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_percolator.py", + "path_type": "hardlink", + "sha256": "133b134a46b23cf2c635be3116415fd388e3a1c1581bf1a77d7f7f0aff3a725b", + "sha256_in_prefix": "133b134a46b23cf2c635be3116415fd388e3a1c1581bf1a77d7f7f0aff3a725b", + "size_in_bytes": 4065 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_pyparse.py", + "path_type": "hardlink", + "sha256": "8f386a9f535369afb495322e104077c66c5a3abb91917ec69f868b405120cf35", + "sha256_in_prefix": "8f386a9f535369afb495322e104077c66c5a3abb91917ec69f868b405120cf35", + "size_in_bytes": 19365 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_pyshell.py", + "path_type": "hardlink", + "sha256": "ff47aecd0657edbd7bc920473fe2e55b0bb0db6f347dc52f5e81b767897d3bc5", + "sha256_in_prefix": "ff47aecd0657edbd7bc920473fe2e55b0bb0db6f347dc52f5e81b767897d3bc5", + "size_in_bytes": 4965 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_query.py", + "path_type": "hardlink", + "sha256": "632c2dc13a158a5902e5b758166151ffa377db7f5a0c368bc3b0741a237876c3", + "sha256_in_prefix": "632c2dc13a158a5902e5b758166151ffa377db7f5a0c368bc3b0741a237876c3", + "size_in_bytes": 15454 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_redirector.py", + "path_type": "hardlink", + "sha256": "517c1fe16da359e01f3cdfdf3f7aead4283e8b8e1107522b72f59d4c4f3ade4c", + "sha256_in_prefix": "517c1fe16da359e01f3cdfdf3f7aead4283e8b8e1107522b72f59d4c4f3ade4c", + "size_in_bytes": 4176 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_replace.py", + "path_type": "hardlink", + "sha256": "321333b3eaad9ecbf633186bc625d4a60c4c736def0fa00665add2ab899eecb1", + "sha256_in_prefix": "321333b3eaad9ecbf633186bc625d4a60c4c736def0fa00665add2ab899eecb1", + "size_in_bytes": 8299 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_rpc.py", + "path_type": "hardlink", + "sha256": "1e2d997f442002389b3dadb47ed8134947c664a32ef637f43afdcbd1b5c13823", + "sha256_in_prefix": "1e2d997f442002389b3dadb47ed8134947c664a32ef637f43afdcbd1b5c13823", + "size_in_bytes": 805 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_run.py", + "path_type": "hardlink", + "sha256": "3cbd9ab33ef7ad8e575f798cc205988d5f106d8be0df20e12b794394c3342b9e", + "sha256_in_prefix": "3cbd9ab33ef7ad8e575f798cc205988d5f106d8be0df20e12b794394c3342b9e", + "size_in_bytes": 15756 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_runscript.py", + "path_type": "hardlink", + "sha256": "4264a834dc230d397725f398d905d0746321d543c56644e5c89af59fe3fedb61", + "sha256_in_prefix": "4264a834dc230d397725f398d905d0746321d543c56644e5c89af59fe3fedb61", + "size_in_bytes": 777 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_scrolledlist.py", + "path_type": "hardlink", + "sha256": "a84ec601c8786daf0564e978c97c0e14095c23f9a08bb64950f9cb541b074b3a", + "sha256_in_prefix": "a84ec601c8786daf0564e978c97c0e14095c23f9a08bb64950f9cb541b074b3a", + "size_in_bytes": 496 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_search.py", + "path_type": "hardlink", + "sha256": "c0550b241c99a566f61929515ca97aedf99f73568df3dfe93078ed22cb54892b", + "sha256_in_prefix": "c0550b241c99a566f61929515ca97aedf99f73568df3dfe93078ed22cb54892b", + "size_in_bytes": 2459 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_searchbase.py", + "path_type": "hardlink", + "sha256": "2b8550dd411b75c6152c4da90843e1221094400080f9a1752e383d0b776f775b", + "sha256_in_prefix": "2b8550dd411b75c6152c4da90843e1221094400080f9a1752e383d0b776f775b", + "size_in_bytes": 5691 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_searchengine.py", + "path_type": "hardlink", + "sha256": "519ddd5633eb8732539594f79ed21a6544f65e599a0d5c8c84db3a488ccdad97", + "sha256_in_prefix": "519ddd5633eb8732539594f79ed21a6544f65e599a0d5c8c84db3a488ccdad97", + "size_in_bytes": 11588 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_sidebar.py", + "path_type": "hardlink", + "sha256": "262977182301b015c9d5051d8ac9861eb286f03b4126d3b01e4d6fe36d866f09", + "sha256_in_prefix": "262977182301b015c9d5051d8ac9861eb286f03b4126d3b01e4d6fe36d866f09", + "size_in_bytes": 26854 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_squeezer.py", + "path_type": "hardlink", + "sha256": "fd5f695e2b1c296719e0a5b494a93184cc7e28cca22e9265def8171b23276b6c", + "sha256_in_prefix": "fd5f695e2b1c296719e0a5b494a93184cc7e28cca22e9265def8171b23276b6c", + "size_in_bytes": 19656 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_stackviewer.py", + "path_type": "hardlink", + "sha256": "15eaeabf43bbaf7d7bc795fb3dfd59c92f3691c73a20548513dcadef8d45b8bf", + "sha256_in_prefix": "15eaeabf43bbaf7d7bc795fb3dfd59c92f3691c73a20548513dcadef8d45b8bf", + "size_in_bytes": 991 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_statusbar.py", + "path_type": "hardlink", + "sha256": "0e9b262b9ad0046cbb0af1101a651fcb88cd1cba38e474b863abbb074b260a02", + "sha256_in_prefix": "0e9b262b9ad0046cbb0af1101a651fcb88cd1cba38e474b863abbb074b260a02", + "size_in_bytes": 1133 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_text.py", + "path_type": "hardlink", + "sha256": "55abe8a9d0bdb45efecb879207f1259702cdcf47dbc636d7cca8dd458f0dc70f", + "sha256_in_prefix": "55abe8a9d0bdb45efecb879207f1259702cdcf47dbc636d7cca8dd458f0dc70f", + "size_in_bytes": 6970 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_textview.py", + "path_type": "hardlink", + "sha256": "e45b199106608c7c981c149d3b4ccf092e7a2e7e9430cc76887cd769b9aaf533", + "sha256_in_prefix": "e45b199106608c7c981c149d3b4ccf092e7a2e7e9430cc76887cd769b9aaf533", + "size_in_bytes": 7364 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_tooltip.py", + "path_type": "hardlink", + "sha256": "b9a82e57761bbca3d4e07193652e8294895765092ef8a651f4dcf63acec7f153", + "sha256_in_prefix": "b9a82e57761bbca3d4e07193652e8294895765092ef8a651f4dcf63acec7f153", + "size_in_bytes": 5385 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_tree.py", + "path_type": "hardlink", + "sha256": "62ae68d64105485107e8173f94ce09739f276004bc8fa65efa5add2c6188e166", + "sha256_in_prefix": "62ae68d64105485107e8173f94ce09739f276004bc8fa65efa5add2c6188e166", + "size_in_bytes": 1752 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_undo.py", + "path_type": "hardlink", + "sha256": "c5178b2dd77d794938fa52adce719d4948a92ba1a689068cec1fb6888d033e0e", + "sha256_in_prefix": "c5178b2dd77d794938fa52adce719d4948a92ba1a689068cec1fb6888d033e0e", + "size_in_bytes": 4228 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_util.py", + "path_type": "hardlink", + "sha256": "300f627fc2199deb246ec793ef47b032de742d763a4170c8bb15e19ccbf602a5", + "sha256_in_prefix": "300f627fc2199deb246ec793ef47b032de742d763a4170c8bb15e19ccbf602a5", + "size_in_bytes": 308 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_warning.py", + "path_type": "hardlink", + "sha256": "d1efc442b3fb93de89fb0988c73f8536fc5099afb761d2b69ec101c239c8c193", + "sha256_in_prefix": "d1efc442b3fb93de89fb0988c73f8536fc5099afb761d2b69ec101c239c8c193", + "size_in_bytes": 2740 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_window.py", + "path_type": "hardlink", + "sha256": "336f2b6994f5aacca9689f32249db20a8dac36934314b7d5ba391d94169d63c6", + "sha256_in_prefix": "336f2b6994f5aacca9689f32249db20a8dac36934314b7d5ba391d94169d63c6", + "size_in_bytes": 1075 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_zoomheight.py", + "path_type": "hardlink", + "sha256": "6300aa47014a5c2dfc9bc0d6c3fb234dff4e4b60a6527d4cdfbb8c416f99df44", + "sha256_in_prefix": "6300aa47014a5c2dfc9bc0d6c3fb234dff4e4b60a6527d4cdfbb8c416f99df44", + "size_in_bytes": 999 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/test_zzdummy.py", + "path_type": "hardlink", + "sha256": "4502524aaa1923393725c04e6b2f27077399190e42bc8903415e95718c5f3c6f", + "sha256_in_prefix": "4502524aaa1923393725c04e6b2f27077399190e42bc8903415e95718c5f3c6f", + "size_in_bytes": 4455 + }, + { + "_path": "lib/python3.12/idlelib/idle_test/tkinter_testing_utils.py", + "path_type": "hardlink", + "sha256": "ece147cef65152a54b0a3d4319bdf8ed82d9a6310273b0056cc17a2de4d744cd", + "sha256_in_prefix": "ece147cef65152a54b0a3d4319bdf8ed82d9a6310273b0056cc17a2de4d744cd", + "size_in_bytes": 2333 + }, + { + "_path": "lib/python3.12/idlelib/iomenu.py", + "path_type": "hardlink", + "sha256": "7004f1ab2cfa5994e453f426507170ec37c1c4a5b9837ba319e5eaebf1a29c34", + "sha256_in_prefix": "7004f1ab2cfa5994e453f426507170ec37c1c4a5b9837ba319e5eaebf1a29c34", + "size_in_bytes": 16159 + }, + { + "_path": "lib/python3.12/idlelib/macosx.py", + "path_type": "hardlink", + "sha256": "e6c687754bb60cd1015a413073b4d85b5e5bc7993c1acbfbc92d70600a83132e", + "sha256_in_prefix": "e6c687754bb60cd1015a413073b4d85b5e5bc7993c1acbfbc92d70600a83132e", + "size_in_bytes": 9290 + }, + { + "_path": "lib/python3.12/idlelib/mainmenu.py", + "path_type": "hardlink", + "sha256": "092fad4454f593d7bf2e5e1e746acade92bb346d06476ba527f162f843ae3208", + "sha256_in_prefix": "092fad4454f593d7bf2e5e1e746acade92bb346d06476ba527f162f843ae3208", + "size_in_bytes": 3938 + }, + { + "_path": "lib/python3.12/idlelib/multicall.py", + "path_type": "hardlink", + "sha256": "efb7d9bddcae17fab2108cb714c240c82d1368087b6d2b91e02ec224ddebce12", + "sha256_in_prefix": "efb7d9bddcae17fab2108cb714c240c82d1368087b6d2b91e02ec224ddebce12", + "size_in_bytes": 18652 + }, + { + "_path": "lib/python3.12/idlelib/outwin.py", + "path_type": "hardlink", + "sha256": "e1946c1a25a020a48843b2ed528bcdd6df29b2af117472b7e2627997b1339b84", + "sha256_in_prefix": "e1946c1a25a020a48843b2ed528bcdd6df29b2af117472b7e2627997b1339b84", + "size_in_bytes": 5715 + }, + { + "_path": "lib/python3.12/idlelib/parenmatch.py", + "path_type": "hardlink", + "sha256": "f122e13c385a135cbbbe8b1d87efeed43ddd3e0be9ddd8aa24b267b61fac4287", + "sha256_in_prefix": "f122e13c385a135cbbbe8b1d87efeed43ddd3e0be9ddd8aa24b267b61fac4287", + "size_in_bytes": 7204 + }, + { + "_path": "lib/python3.12/idlelib/pathbrowser.py", + "path_type": "hardlink", + "sha256": "42a4e008922c991049f1b42ca18700b65f2f8d0ab6dd12cc22671771e90c2065", + "sha256_in_prefix": "42a4e008922c991049f1b42ca18700b65f2f8d0ab6dd12cc22671771e90c2065", + "size_in_bytes": 3093 + }, + { + "_path": "lib/python3.12/idlelib/percolator.py", + "path_type": "hardlink", + "sha256": "42fe72c167eb3a2795cbe64c498d7cbe1de05132be29a99a58226ae83efb31d4", + "sha256_in_prefix": "42fe72c167eb3a2795cbe64c498d7cbe1de05132be29a99a58226ae83efb31d4", + "size_in_bytes": 3568 + }, + { + "_path": "lib/python3.12/idlelib/pyparse.py", + "path_type": "hardlink", + "sha256": "21c6bf43370998d5a5a6670f7b13409335e9a2c1a350ed586bbe63be5f226648", + "sha256_in_prefix": "21c6bf43370998d5a5a6670f7b13409335e9a2c1a350ed586bbe63be5f226648", + "size_in_bytes": 19864 + }, + { + "_path": "lib/python3.12/idlelib/pyshell.py", + "path_type": "hardlink", + "sha256": "1c1a2257ac73dda641843ff8abb8c26f250a5d6ea121cd42b8bc8c4784fcab77", + "sha256_in_prefix": "1c1a2257ac73dda641843ff8abb8c26f250a5d6ea121cd42b8bc8c4784fcab77", + "size_in_bytes": 62533 + }, + { + "_path": "lib/python3.12/idlelib/query.py", + "path_type": "hardlink", + "sha256": "faea5edd6b8693e6a32107054ad0de3be4d28e6aacb7792f86cbbe146131373b", + "sha256_in_prefix": "faea5edd6b8693e6a32107054ad0de3be4d28e6aacb7792f86cbbe146131373b", + "size_in_bytes": 15067 + }, + { + "_path": "lib/python3.12/idlelib/redirector.py", + "path_type": "hardlink", + "sha256": "7911a7534eb0c73ee3e2464c5f8498109653f73ebed8fa903780c5fd7ca00754", + "sha256_in_prefix": "7911a7534eb0c73ee3e2464c5f8498109653f73ebed8fa903780c5fd7ca00754", + "size_in_bytes": 6777 + }, + { + "_path": "lib/python3.12/idlelib/replace.py", + "path_type": "hardlink", + "sha256": "ea13db39aa89df369b36200c7301874a5636403e8270b1862f946e2fff081b84", + "sha256_in_prefix": "ea13db39aa89df369b36200c7301874a5636403e8270b1862f946e2fff081b84", + "size_in_bytes": 9841 + }, + { + "_path": "lib/python3.12/idlelib/rpc.py", + "path_type": "hardlink", + "sha256": "8d0cb6e11c8dcc5dbda89b9a582bfaa74fe2b661dde442b02eb61b8fc47d9eb3", + "sha256_in_prefix": "8d0cb6e11c8dcc5dbda89b9a582bfaa74fe2b661dde442b02eb61b8fc47d9eb3", + "size_in_bytes": 21078 + }, + { + "_path": "lib/python3.12/idlelib/run.py", + "path_type": "hardlink", + "sha256": "f892ec4391871cfec444e719a198fa020673e6513a397be3465ff95fd8d165d1", + "sha256_in_prefix": "f892ec4391871cfec444e719a198fa020673e6513a397be3465ff95fd8d165d1", + "size_in_bytes": 21462 + }, + { + "_path": "lib/python3.12/idlelib/runscript.py", + "path_type": "hardlink", + "sha256": "b92740fddc7b1d603b1736a135bd15518081f20c0db1e1a779cab715ee9120fe", + "sha256_in_prefix": "b92740fddc7b1d603b1736a135bd15518081f20c0db1e1a779cab715ee9120fe", + "size_in_bytes": 8273 + }, + { + "_path": "lib/python3.12/idlelib/scrolledlist.py", + "path_type": "hardlink", + "sha256": "25b0ad247977f6079226052e2b76dd4c127bf50f2f5e8ffbd1fe10bc631bfca9", + "sha256_in_prefix": "25b0ad247977f6079226052e2b76dd4c127bf50f2f5e8ffbd1fe10bc631bfca9", + "size_in_bytes": 4478 + }, + { + "_path": "lib/python3.12/idlelib/search.py", + "path_type": "hardlink", + "sha256": "c53ff4d4814d97d0d95b7e15030d3ae8c732366ed84c2b300183e933270df724", + "sha256_in_prefix": "c53ff4d4814d97d0d95b7e15030d3ae8c732366ed84c2b300183e933270df724", + "size_in_bytes": 5567 + }, + { + "_path": "lib/python3.12/idlelib/searchbase.py", + "path_type": "hardlink", + "sha256": "5e13c99d9f264166d9204eeff0492d43d03f2afd8f66494b3e110d7665ab29cc", + "sha256_in_prefix": "5e13c99d9f264166d9204eeff0492d43d03f2afd8f66494b3e110d7665ab29cc", + "size_in_bytes": 7856 + }, + { + "_path": "lib/python3.12/idlelib/searchengine.py", + "path_type": "hardlink", + "sha256": "11b0c8df926e4f6bd2e26d0264b2d902c41bcc70d68a4a830df1ea2da2c2a6cc", + "sha256_in_prefix": "11b0c8df926e4f6bd2e26d0264b2d902c41bcc70d68a4a830df1ea2da2c2a6cc", + "size_in_bytes": 7415 + }, + { + "_path": "lib/python3.12/idlelib/sidebar.py", + "path_type": "hardlink", + "sha256": "760f14ebb0312adb289cda0562c9eff70982a0acde5d9d9d0b591390cd4a581e", + "sha256_in_prefix": "760f14ebb0312adb289cda0562c9eff70982a0acde5d9d9d0b591390cd4a581e", + "size_in_bytes": 20338 + }, + { + "_path": "lib/python3.12/idlelib/squeezer.py", + "path_type": "hardlink", + "sha256": "112221334fee94a88cba2ca7ac455e1bd6ab796397cbe036b1e8a98bc0787e30", + "sha256_in_prefix": "112221334fee94a88cba2ca7ac455e1bd6ab796397cbe036b1e8a98bc0787e30", + "size_in_bytes": 12834 + }, + { + "_path": "lib/python3.12/idlelib/stackviewer.py", + "path_type": "hardlink", + "sha256": "ee053a65298e2ec2f4628d8269a33362816271fd81fab4e550a621493c26a76f", + "sha256_in_prefix": "ee053a65298e2ec2f4628d8269a33362816271fd81fab4e550a621493c26a76f", + "size_in_bytes": 4016 + }, + { + "_path": "lib/python3.12/idlelib/statusbar.py", + "path_type": "hardlink", + "sha256": "3f4dc0f27b0c23e488d022abe8461529ce8a1b4eaf9dbfd97123ef2c502f684e", + "sha256_in_prefix": "3f4dc0f27b0c23e488d022abe8461529ce8a1b4eaf9dbfd97123ef2c502f684e", + "size_in_bytes": 1474 + }, + { + "_path": "lib/python3.12/idlelib/textview.py", + "path_type": "hardlink", + "sha256": "eace58159e9636bb1456885c21f5ed474e203090139e5dd3457ac72ad5552006", + "sha256_in_prefix": "eace58159e9636bb1456885c21f5ed474e203090139e5dd3457ac72ad5552006", + "size_in_bytes": 6808 + }, + { + "_path": "lib/python3.12/idlelib/tooltip.py", + "path_type": "hardlink", + "sha256": "73dfad0e6652bcd67f7fccdface2e4cd8d5f3c6ffe2ef1c2e86ca0cb12d5d034", + "sha256_in_prefix": "73dfad0e6652bcd67f7fccdface2e4cd8d5f3c6ffe2ef1c2e86ca0cb12d5d034", + "size_in_bytes": 6471 + }, + { + "_path": "lib/python3.12/idlelib/tree.py", + "path_type": "hardlink", + "sha256": "dd594fd0f47ed3cb956d6bc77f72f200144aca13a3c3b9ecd7f472fcefc9256a", + "sha256_in_prefix": "dd594fd0f47ed3cb956d6bc77f72f200144aca13a3c3b9ecd7f472fcefc9256a", + "size_in_bytes": 16483 + }, + { + "_path": "lib/python3.12/idlelib/undo.py", + "path_type": "hardlink", + "sha256": "291fda98995bb4688fbe05fd3fa689e21aade3627c4c16e8971ed353f6cc3107", + "sha256_in_prefix": "291fda98995bb4688fbe05fd3fa689e21aade3627c4c16e8971ed353f6cc3107", + "size_in_bytes": 11016 + }, + { + "_path": "lib/python3.12/idlelib/util.py", + "path_type": "hardlink", + "sha256": "a80958a9f028ed987daf18cd55d78f6db3aff12e9c5629323d992829c0737413", + "sha256_in_prefix": "a80958a9f028ed987daf18cd55d78f6db3aff12e9c5629323d992829c0737413", + "size_in_bytes": 731 + }, + { + "_path": "lib/python3.12/idlelib/window.py", + "path_type": "hardlink", + "sha256": "ca31d8c01c9b468fcad0a4e529c8e205c1e4ecf30520545db654d466bd7158bd", + "sha256_in_prefix": "ca31d8c01c9b468fcad0a4e529c8e205c1e4ecf30520545db654d466bd7158bd", + "size_in_bytes": 2616 + }, + { + "_path": "lib/python3.12/idlelib/zoomheight.py", + "path_type": "hardlink", + "sha256": "5f6ff83cb0df3ee5e7d997ffe23efb341b994bfbaf00b79a4832d54231a095dd", + "sha256_in_prefix": "5f6ff83cb0df3ee5e7d997ffe23efb341b994bfbaf00b79a4832d54231a095dd", + "size_in_bytes": 4203 + }, + { + "_path": "lib/python3.12/idlelib/zzdummy.py", + "path_type": "hardlink", + "sha256": "5e248f0ea4f35052d23bb2c43564aa567b8cebaf91fd63ba0be8fef2f4167945", + "sha256_in_prefix": "5e248f0ea4f35052d23bb2c43564aa567b8cebaf91fd63ba0be8fef2f4167945", + "size_in_bytes": 2005 + }, + { + "_path": "lib/python3.12/imaplib.py", + "path_type": "hardlink", + "sha256": "81a8a1705087119d7ba1eba17bac27fdb49ed9127a28c6f7678f6013257ce0dd", + "sha256_in_prefix": "81a8a1705087119d7ba1eba17bac27fdb49ed9127a28c6f7678f6013257ce0dd", + "size_in_bytes": 53688 + }, + { + "_path": "lib/python3.12/imghdr.py", + "path_type": "hardlink", + "sha256": "c1bb52ea0816db4c5f3420655ab4a476fb3829709141e91f1a56b9c6fe286d56", + "sha256_in_prefix": "c1bb52ea0816db4c5f3420655ab4a476fb3829709141e91f1a56b9c6fe286d56", + "size_in_bytes": 4398 + }, + { + "_path": "lib/python3.12/importlib/__init__.py", + "path_type": "hardlink", + "sha256": "c9e1b3dbc619ac31e7017ac43668a20200872c1c0e79ae379c0dab6ed399b730", + "sha256_in_prefix": "c9e1b3dbc619ac31e7017ac43668a20200872c1c0e79ae379c0dab6ed399b730", + "size_in_bytes": 4774 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "209891b744538a85fe7d0d27d5dfd528acaf1a7bb001c40b1b93f47b893beb10", + "sha256_in_prefix": "209891b744538a85fe7d0d27d5dfd528acaf1a7bb001c40b1b93f47b893beb10", + "size_in_bytes": 4560 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/_abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "726dba7b00850618e2f654a383529b87ef30e5e6f143cea53879cfb31aba324f", + "sha256_in_prefix": "726dba7b00850618e2f654a383529b87ef30e5e6f143cea53879cfb31aba324f", + "size_in_bytes": 1638 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/_bootstrap.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8a14e2d080afb1ed9d6d6cfc93588a24e0b7782b12b5e55cbda949c0c1d0ad68", + "sha256_in_prefix": "8a14e2d080afb1ed9d6d6cfc93588a24e0b7782b12b5e55cbda949c0c1d0ad68", + "size_in_bytes": 55836 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/_bootstrap_external.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4a6670a35a430120f396c03449695b776fdeefc3f58b2006ecdb79dab5bab4d7", + "sha256_in_prefix": "4a6670a35a430120f396c03449695b776fdeefc3f58b2006ecdb79dab5bab4d7", + "size_in_bytes": 61587 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "af75dd52cee6dcd1586429ac194d8e211376d13f56d63f257aa366d0b60c4940", + "sha256_in_prefix": "af75dd52cee6dcd1586429ac194d8e211376d13f56d63f257aa366d0b60c4940", + "size_in_bytes": 10411 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/machinery.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b83a5a5904d098bad7a4c7d5494cb26902511655a0e70abefa86d8320e36f9c7", + "sha256_in_prefix": "b83a5a5904d098bad7a4c7d5494cb26902511655a0e70abefa86d8320e36f9c7", + "size_in_bytes": 1050 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/readers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ec92151affaf8f9756892a6e2bf1e79a172516092c9855af47491ae134dd2865", + "sha256_in_prefix": "ec92151affaf8f9756892a6e2bf1e79a172516092c9855af47491ae134dd2865", + "size_in_bytes": 457 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/simple.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7e853de498a2be309ac811ae5716724c7502cda3e33ff3ca218f9c7d960ce124", + "sha256_in_prefix": "7e853de498a2be309ac811ae5716724c7502cda3e33ff3ca218f9c7d960ce124", + "size_in_bytes": 464 + }, + { + "_path": "lib/python3.12/importlib/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "03487750fb6f695ef8861be334fd2094c68bb751ac55555696f6c02c68d36731", + "sha256_in_prefix": "03487750fb6f695ef8861be334fd2094c68bb751ac55555696f6c02c68d36731", + "size_in_bytes": 11767 + }, + { + "_path": "lib/python3.12/importlib/_abc.py", + "path_type": "hardlink", + "sha256": "80aab7931dc999dee581c8b8b56fcd973fe156335a96ceeaf6acfc03cebf10e8", + "sha256_in_prefix": "80aab7931dc999dee581c8b8b56fcd973fe156335a96ceeaf6acfc03cebf10e8", + "size_in_bytes": 1354 + }, + { + "_path": "lib/python3.12/importlib/_bootstrap.py", + "path_type": "hardlink", + "sha256": "9653944363a4773cc32bbb34426024597a9d2ee4cd42e7912b4daf8cadfb53ed", + "sha256_in_prefix": "9653944363a4773cc32bbb34426024597a9d2ee4cd42e7912b4daf8cadfb53ed", + "size_in_bytes": 57056 + }, + { + "_path": "lib/python3.12/importlib/_bootstrap_external.py", + "path_type": "hardlink", + "sha256": "949e115a77dd6b25280195c30b6f5146a303212816b3221430ad82467d4f3133", + "sha256_in_prefix": "949e115a77dd6b25280195c30b6f5146a303212816b3221430ad82467d4f3133", + "size_in_bytes": 69175 + }, + { + "_path": "lib/python3.12/importlib/abc.py", + "path_type": "hardlink", + "sha256": "5f9cb36ca1bce9d5df00bc8d4d7f46b7ea2353dfa99292ad7f099affddfb5d03", + "sha256_in_prefix": "5f9cb36ca1bce9d5df00bc8d4d7f46b7ea2353dfa99292ad7f099affddfb5d03", + "size_in_bytes": 7612 + }, + { + "_path": "lib/python3.12/importlib/machinery.py", + "path_type": "hardlink", + "sha256": "d045cd7ecf2a12b6ecbfbef79eb114e87ef2ebd756f5b705f73e6f3266e3dede", + "sha256_in_prefix": "d045cd7ecf2a12b6ecbfbef79eb114e87ef2ebd756f5b705f73e6f3266e3dede", + "size_in_bytes": 880 + }, + { + "_path": "lib/python3.12/importlib/metadata/__init__.py", + "path_type": "hardlink", + "sha256": "873ff461b8e216bc55ad9956d13dabfe35ff2ba13701ede97837884994dbc9fa", + "sha256_in_prefix": "873ff461b8e216bc55ad9956d13dabfe35ff2ba13701ede97837884994dbc9fa", + "size_in_bytes": 28743 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "93578eac2c80cbb68d0846c9c9ce602bb64a5210dbaeffeba710dec78f9e7deb", + "sha256_in_prefix": "93578eac2c80cbb68d0846c9c9ce602bb64a5210dbaeffeba710dec78f9e7deb", + "size_in_bytes": 48479 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_adapters.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9843db161795b79fe551dd515ec0a350ec69d825501b468dd7de2c4d8456f133", + "sha256_in_prefix": "9843db161795b79fe551dd515ec0a350ec69d825501b468dd7de2c4d8456f133", + "size_in_bytes": 3830 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_collections.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "992e89aab2bcee73bb7adfc4af8fdadcc5911bc9d8014166419393f64c05fa6d", + "sha256_in_prefix": "992e89aab2bcee73bb7adfc4af8fdadcc5911bc9d8014166419393f64c05fa6d", + "size_in_bytes": 1878 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_functools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "99843f0c5ad378f503cdf7c7ba16f0aa6b1f0b05c665e9c4c31c4f2d19d89c15", + "sha256_in_prefix": "99843f0c5ad378f503cdf7c7ba16f0aa6b1f0b05c665e9c4c31c4f2d19d89c15", + "size_in_bytes": 3436 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_itertools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c9840d3f99c54ea47f99bd81717a8f5f1ca5d6edc0dfc08d21f365da6def20f7", + "sha256_in_prefix": "c9840d3f99c54ea47f99bd81717a8f5f1ca5d6edc0dfc08d21f365da6def20f7", + "size_in_bytes": 2360 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_meta.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2dbe2676a91f65b0930ecdd15366fa5a29ac981dae2c9f624a2de9179ff2305c", + "sha256_in_prefix": "2dbe2676a91f65b0930ecdd15366fa5a29ac981dae2c9f624a2de9179ff2305c", + "size_in_bytes": 3276 + }, + { + "_path": "lib/python3.12/importlib/metadata/__pycache__/_text.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7d2dce417a54490b41f135f51a583c344b15654e3583f02655a6f62eee93848a", + "sha256_in_prefix": "7d2dce417a54490b41f135f51a583c344b15654e3583f02655a6f62eee93848a", + "size_in_bytes": 3837 + }, + { + "_path": "lib/python3.12/importlib/metadata/_adapters.py", + "path_type": "hardlink", + "sha256": "de9a880abc4513af1b69ce150cd5a5093201c39131717cdc2ba6b19f4364c163", + "sha256_in_prefix": "de9a880abc4513af1b69ce150cd5a5093201c39131717cdc2ba6b19f4364c163", + "size_in_bytes": 2406 + }, + { + "_path": "lib/python3.12/importlib/metadata/_collections.py", + "path_type": "hardlink", + "sha256": "089d0e4c21c88d6034648552e2fa0e440b27d91e11d9c40112d3ec6442690126", + "sha256_in_prefix": "089d0e4c21c88d6034648552e2fa0e440b27d91e11d9c40112d3ec6442690126", + "size_in_bytes": 743 + }, + { + "_path": "lib/python3.12/importlib/metadata/_functools.py", + "path_type": "hardlink", + "sha256": "3ec636fb8aeb297e1155e442d681a9d65075a660bd78a37cf3f7fe6c3f6e3a80", + "sha256_in_prefix": "3ec636fb8aeb297e1155e442d681a9d65075a660bd78a37cf3f7fe6c3f6e3a80", + "size_in_bytes": 2895 + }, + { + "_path": "lib/python3.12/importlib/metadata/_itertools.py", + "path_type": "hardlink", + "sha256": "72faffdaff0145bc5c225e71e6575fa9d1e3848f188bcb3cca4e741bf9e6ea34", + "sha256_in_prefix": "72faffdaff0145bc5c225e71e6575fa9d1e3848f188bcb3cca4e741bf9e6ea34", + "size_in_bytes": 2068 + }, + { + "_path": "lib/python3.12/importlib/metadata/_meta.py", + "path_type": "hardlink", + "sha256": "bd3504040497cd049e6b529bde0b461f63cd2be3070f2d0815d4dd7609b266c8", + "sha256_in_prefix": "bd3504040497cd049e6b529bde0b461f63cd2be3070f2d0815d4dd7609b266c8", + "size_in_bytes": 1590 + }, + { + "_path": "lib/python3.12/importlib/metadata/_text.py", + "path_type": "hardlink", + "sha256": "1c2b0592c66924b7933f734493f9e0ac079755146d4ebb7287d78e001a113f80", + "sha256_in_prefix": "1c2b0592c66924b7933f734493f9e0ac079755146d4ebb7287d78e001a113f80", + "size_in_bytes": 2166 + }, + { + "_path": "lib/python3.12/importlib/readers.py", + "path_type": "hardlink", + "sha256": "d0d57d118d64916f7e6edb04f8bd1a760a1abb879125899ef50a36d09ef54df4", + "sha256_in_prefix": "d0d57d118d64916f7e6edb04f8bd1a760a1abb879125899ef50a36d09ef54df4", + "size_in_bytes": 327 + }, + { + "_path": "lib/python3.12/importlib/resources/__init__.py", + "path_type": "hardlink", + "sha256": "7af3e6d7690b818a939bea5bce6eb46cebae9ae993f08a41356169d2e332af31", + "sha256_in_prefix": "7af3e6d7690b818a939bea5bce6eb46cebae9ae993f08a41356169d2e332af31", + "size_in_bytes": 506 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c5e477cc311f3812962f1af1b7893063eff8d9c5db1c852126a8e75d3ed67631", + "sha256_in_prefix": "c5e477cc311f3812962f1af1b7893063eff8d9c5db1c852126a8e75d3ed67631", + "size_in_bytes": 610 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/_adapters.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4fe66ed3582f855c8d07e096d2a1ea4189265b27609f005f4ac30d074749e9f7", + "sha256_in_prefix": "4fe66ed3582f855c8d07e096d2a1ea4189265b27609f005f4ac30d074749e9f7", + "size_in_bytes": 9621 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/_common.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "dbe3e6ec03e7bc01f1d21ec2a76c5f21cb27f86659649442fe06343452d24c0e", + "sha256_in_prefix": "dbe3e6ec03e7bc01f1d21ec2a76c5f21cb27f86659649442fe06343452d24c0e", + "size_in_bytes": 8706 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/_itertools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a81a08109d374711727cba0164cc990548d3812421cd4aac66b2389cb04e71cf", + "sha256_in_prefix": "a81a08109d374711727cba0164cc990548d3812421cd4aac66b2389cb04e71cf", + "size_in_bytes": 1534 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/_legacy.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7163ba75130a5125c0fa474686f7d40e977b52755b0c09635eadabe31234533e", + "sha256_in_prefix": "7163ba75130a5125c0fa474686f7d40e977b52755b0c09635eadabe31234533e", + "size_in_bytes": 5738 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/abc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "13ecb84869913027e0c6559c916ea1ac3df03f7ef2cc1176482db329ced6c8c7", + "sha256_in_prefix": "13ecb84869913027e0c6559c916ea1ac3df03f7ef2cc1176482db329ced6c8c7", + "size_in_bytes": 8916 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/readers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "76241d165791c667d227627f5291ec2df4db927f60974705cb2d7fab911aee47", + "sha256_in_prefix": "76241d165791c667d227627f5291ec2df4db927f60974705cb2d7fab911aee47", + "size_in_bytes": 8889 + }, + { + "_path": "lib/python3.12/importlib/resources/__pycache__/simple.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0016ed95f3f5d68c904f6813746f90515e5bfaa18750035c4d62b5912da34490", + "sha256_in_prefix": "0016ed95f3f5d68c904f6813746f90515e5bfaa18750035c4d62b5912da34490", + "size_in_bytes": 5459 + }, + { + "_path": "lib/python3.12/importlib/resources/_adapters.py", + "path_type": "hardlink", + "sha256": "be9ac919b51e1db6a35fa5c2b8c3fa27794caea0a2f8ffcc4e5ce225447b8df9", + "sha256_in_prefix": "be9ac919b51e1db6a35fa5c2b8c3fa27794caea0a2f8ffcc4e5ce225447b8df9", + "size_in_bytes": 4482 + }, + { + "_path": "lib/python3.12/importlib/resources/_common.py", + "path_type": "hardlink", + "sha256": "9bfef8de14579936e96c0e921e934a3f4f56b4e32d3cfacc12f3e24436fc37b4", + "sha256_in_prefix": "9bfef8de14579936e96c0e921e934a3f4f56b4e32d3cfacc12f3e24436fc37b4", + "size_in_bytes": 5459 + }, + { + "_path": "lib/python3.12/importlib/resources/_itertools.py", + "path_type": "hardlink", + "sha256": "7838ac57a46a88d64ea202d25dfe8b3861ce61cefd14680faca34bcc52e60ab5", + "sha256_in_prefix": "7838ac57a46a88d64ea202d25dfe8b3861ce61cefd14680faca34bcc52e60ab5", + "size_in_bytes": 1277 + }, + { + "_path": "lib/python3.12/importlib/resources/_legacy.py", + "path_type": "hardlink", + "sha256": "d1329d662c712d603ec70b40670e07729a899a3e17a6bc7566472dcb48134596", + "sha256_in_prefix": "d1329d662c712d603ec70b40670e07729a899a3e17a6bc7566472dcb48134596", + "size_in_bytes": 3481 + }, + { + "_path": "lib/python3.12/importlib/resources/abc.py", + "path_type": "hardlink", + "sha256": "a726c48590b21ba5532f0c654735991571bc0ecafe88145cb8891d82cd364e5e", + "sha256_in_prefix": "a726c48590b21ba5532f0c654735991571bc0ecafe88145cb8891d82cd364e5e", + "size_in_bytes": 5203 + }, + { + "_path": "lib/python3.12/importlib/resources/readers.py", + "path_type": "hardlink", + "sha256": "231e0c485123729f26b706e54b1810d4294d3bd7182a2355b14b8318bd4ecf8e", + "sha256_in_prefix": "231e0c485123729f26b706e54b1810d4294d3bd7182a2355b14b8318bd4ecf8e", + "size_in_bytes": 4303 + }, + { + "_path": "lib/python3.12/importlib/resources/simple.py", + "path_type": "hardlink", + "sha256": "090dd3888305889b3ff34a3eef124bd44a5b5145676b8f8d183ad24d0dc75b66", + "sha256_in_prefix": "090dd3888305889b3ff34a3eef124bd44a5b5145676b8f8d183ad24d0dc75b66", + "size_in_bytes": 2584 + }, + { + "_path": "lib/python3.12/importlib/simple.py", + "path_type": "hardlink", + "sha256": "8e687aeeb1db537d2717cb0352c5f126ff7d4095c6de6dc7f00d5103f3009c40", + "sha256_in_prefix": "8e687aeeb1db537d2717cb0352c5f126ff7d4095c6de6dc7f00d5103f3009c40", + "size_in_bytes": 354 + }, + { + "_path": "lib/python3.12/importlib/util.py", + "path_type": "hardlink", + "sha256": "ca54e6458dbe521d591e5b8d9bb651ef929bfae946706c98470cdd569041a64f", + "sha256_in_prefix": "ca54e6458dbe521d591e5b8d9bb651ef929bfae946706c98470cdd569041a64f", + "size_in_bytes": 10840 + }, + { + "_path": "lib/python3.12/inspect.py", + "path_type": "hardlink", + "sha256": "13945f061d93cf7b8f812d2afc279ff0b3aea799c7146b1c0c58c6e644bbc3e1", + "sha256_in_prefix": "13945f061d93cf7b8f812d2afc279ff0b3aea799c7146b1c0c58c6e644bbc3e1", + "size_in_bytes": 125420 + }, + { + "_path": "lib/python3.12/io.py", + "path_type": "hardlink", + "sha256": "7cec3cb8ac004058dd0a5af246e6d950fb59c7ddd0058fda48bcb3fcb98d8822", + "sha256_in_prefix": "7cec3cb8ac004058dd0a5af246e6d950fb59c7ddd0058fda48bcb3fcb98d8822", + "size_in_bytes": 3582 + }, + { + "_path": "lib/python3.12/ipaddress.py", + "path_type": "hardlink", + "sha256": "687e343fa31d6470a3856d825e410509b24f7117be12ccba8a704d88214e206a", + "sha256_in_prefix": "687e343fa31d6470a3856d825e410509b24f7117be12ccba8a704d88214e206a", + "size_in_bytes": 75012 + }, + { + "_path": "lib/python3.12/json/__init__.py", + "path_type": "hardlink", + "sha256": "d5d41e2c29049515d295d81a6d40b4890fbec8d8482cfb401630f8ef2f77e4d5", + "sha256_in_prefix": "d5d41e2c29049515d295d81a6d40b4890fbec8d8482cfb401630f8ef2f77e4d5", + "size_in_bytes": 14020 + }, + { + "_path": "lib/python3.12/json/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4c8df08166a2558bb928aa41a4eb36ca59377d522fa5c43b1559cfebbc8bc275", + "sha256_in_prefix": "4c8df08166a2558bb928aa41a4eb36ca59377d522fa5c43b1559cfebbc8bc275", + "size_in_bytes": 13615 + }, + { + "_path": "lib/python3.12/json/__pycache__/decoder.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7181260f4f8ce3f6bd737ee390adfc1fa11f6dbe887c7b2ecf3b9f07b1993759", + "sha256_in_prefix": "7181260f4f8ce3f6bd737ee390adfc1fa11f6dbe887c7b2ecf3b9f07b1993759", + "size_in_bytes": 13820 + }, + { + "_path": "lib/python3.12/json/__pycache__/encoder.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "07dfac5224d2f566fb7e86e4b32a1e5144724bc99d665930792238b48a6286db", + "sha256_in_prefix": "07dfac5224d2f566fb7e86e4b32a1e5144724bc99d665930792238b48a6286db", + "size_in_bytes": 15093 + }, + { + "_path": "lib/python3.12/json/__pycache__/scanner.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1ad97bef9c50535bddd9f61a588052143249cb8ed7c40e634033cbc7f58e35e4", + "sha256_in_prefix": "1ad97bef9c50535bddd9f61a588052143249cb8ed7c40e634033cbc7f58e35e4", + "size_in_bytes": 3316 + }, + { + "_path": "lib/python3.12/json/__pycache__/tool.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "28fbf5e280186443b7248be29927ef83fd1649f757736d06842aa4820a304483", + "sha256_in_prefix": "28fbf5e280186443b7248be29927ef83fd1649f757736d06842aa4820a304483", + "size_in_bytes": 4297 + }, + { + "_path": "lib/python3.12/json/decoder.py", + "path_type": "hardlink", + "sha256": "9f02654649816145bc76f8c210a5fe3ba1de142d4d97a1c93105732e747c285b", + "sha256_in_prefix": "9f02654649816145bc76f8c210a5fe3ba1de142d4d97a1c93105732e747c285b", + "size_in_bytes": 12473 + }, + { + "_path": "lib/python3.12/json/encoder.py", + "path_type": "hardlink", + "sha256": "af7bd40a0d0d0a3e726a9b4b3a2a543019f6ab97a340d0162a9c29ca9da97869", + "sha256_in_prefix": "af7bd40a0d0d0a3e726a9b4b3a2a543019f6ab97a340d0162a9c29ca9da97869", + "size_in_bytes": 16070 + }, + { + "_path": "lib/python3.12/json/scanner.py", + "path_type": "hardlink", + "sha256": "8604d9d03786d0d509abb49e9f069337278ea988c244069ae8ca2c89acc2cb08", + "sha256_in_prefix": "8604d9d03786d0d509abb49e9f069337278ea988c244069ae8ca2c89acc2cb08", + "size_in_bytes": 2425 + }, + { + "_path": "lib/python3.12/json/tool.py", + "path_type": "hardlink", + "sha256": "d5174b728b376a12cff3f17472d6b9b609c1d3926f7ee02d74d60c80afd60c77", + "sha256_in_prefix": "d5174b728b376a12cff3f17472d6b9b609c1d3926f7ee02d74d60c80afd60c77", + "size_in_bytes": 3339 + }, + { + "_path": "lib/python3.12/keyword.py", + "path_type": "hardlink", + "sha256": "18c2be738c04ad20ad375f6a71db34b3823c7f40b0340f5294d0e89f3c9b093b", + "sha256_in_prefix": "18c2be738c04ad20ad375f6a71db34b3823c7f40b0340f5294d0e89f3c9b093b", + "size_in_bytes": 1073 + }, + { + "_path": "lib/python3.12/lib-dynload/_asyncio.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "bc37d05cb50bcaa1c96b44070b63f5352cc5b0a82f599dac34b5958d314d95e2", + "sha256_in_prefix": "bc37d05cb50bcaa1c96b44070b63f5352cc5b0a82f599dac34b5958d314d95e2", + "size_in_bytes": 369376 + }, + { + "_path": "lib/python3.12/lib-dynload/_bisect.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "96668ff59166a88aaf882a1126ff17e75fad9cb165f38321093ddc7ff52c5c22", + "sha256_in_prefix": "96668ff59166a88aaf882a1126ff17e75fad9cb165f38321093ddc7ff52c5c22", + "size_in_bytes": 77896 + }, + { + "_path": "lib/python3.12/lib-dynload/_blake2.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "5aaa17701e0ed9e1226ce1a9c710cd3df96156558e7b12e2a69265b04315703e", + "sha256_in_prefix": "5aaa17701e0ed9e1226ce1a9c710cd3df96156558e7b12e2a69265b04315703e", + "size_in_bytes": 227712 + }, + { + "_path": "lib/python3.12/lib-dynload/_bz2.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "ef25224bf093def809112f3318356bdf6400535d722bd10787d66d141f8b1ef9", + "sha256_in_prefix": "ef25224bf093def809112f3318356bdf6400535d722bd10787d66d141f8b1ef9", + "size_in_bytes": 96936 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_cn.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "6b71e9ca38869a82194a5c1663eeee05fef4150be4ab499727555c3b9e7aed85", + "sha256_in_prefix": "6b71e9ca38869a82194a5c1663eeee05fef4150be4ab499727555c3b9e7aed85", + "size_in_bytes": 200640 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_hk.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "1119d66db9af25130026eaa9566ef11e3b2f4fcc62c31d079de8ad910bec65bd", + "sha256_in_prefix": "1119d66db9af25130026eaa9566ef11e3b2f4fcc62c31d079de8ad910bec65bd", + "size_in_bytes": 199016 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_iso2022.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "e43860860e8f836ffcc5d872bee2a5dba6ecca75ba37749d067c79c70c699fe5", + "sha256_in_prefix": "e43860860e8f836ffcc5d872bee2a5dba6ecca75ba37749d067c79c70c699fe5", + "size_in_bytes": 86536 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_jp.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "3963513a2d96f6c8f32151df7ebf707b626646a2526306abbb711cab72a65521", + "sha256_in_prefix": "3963513a2d96f6c8f32151df7ebf707b626646a2526306abbb711cab72a65521", + "size_in_bytes": 333472 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_kr.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "eb06fdd08ffda8caf86da1c6d830e2057d214be7a11b6e20b5ef963d6e909081", + "sha256_in_prefix": "eb06fdd08ffda8caf86da1c6d830e2057d214be7a11b6e20b5ef963d6e909081", + "size_in_bytes": 184232 + }, + { + "_path": "lib/python3.12/lib-dynload/_codecs_tw.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f93b683cb223a00dfffe5143ff57d251495550d3df3dc9a669d05ec02e9fdfa1", + "sha256_in_prefix": "f93b683cb223a00dfffe5143ff57d251495550d3df3dc9a669d05ec02e9fdfa1", + "size_in_bytes": 150360 + }, + { + "_path": "lib/python3.12/lib-dynload/_contextvars.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "5f239b59780d15eabb61b359ea9be5cbe91e805c2d92f4e595deb0c3e7edcbfc", + "sha256_in_prefix": "5f239b59780d15eabb61b359ea9be5cbe91e805c2d92f4e595deb0c3e7edcbfc", + "size_in_bytes": 27384 + }, + { + "_path": "lib/python3.12/lib-dynload/_crypt.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "8d31e5d3a16ea610020bedfc3f7205fdda352959c055b49b626b6b833904b0c8", + "sha256_in_prefix": "8d31e5d3a16ea610020bedfc3f7205fdda352959c055b49b626b6b833904b0c8", + "size_in_bytes": 30368 + }, + { + "_path": "lib/python3.12/lib-dynload/_csv.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "d3d3248515579a32513acb4e8a248e3d4eea00460079830c3cde683eaaf19358", + "sha256_in_prefix": "d3d3248515579a32513acb4e8a248e3d4eea00460079830c3cde683eaaf19358", + "size_in_bytes": 155112 + }, + { + "_path": "lib/python3.12/lib-dynload/_ctypes.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "bc693328cfd48159d8431444e4d984be5f523447e2aa92d9b1ed0d1297c46f98", + "sha256_in_prefix": "bc693328cfd48159d8431444e4d984be5f523447e2aa92d9b1ed0d1297c46f98", + "size_in_bytes": 862856 + }, + { + "_path": "lib/python3.12/lib-dynload/_ctypes_test.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "477be8cd803100a0e30e1f94faea4199e20810d5a41b51883b8c2ed879260842", + "sha256_in_prefix": "477be8cd803100a0e30e1f94faea4199e20810d5a41b51883b8c2ed879260842", + "size_in_bytes": 77880 + }, + { + "_path": "lib/python3.12/lib-dynload/_curses.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "9db2d6bc3de9539217244466bfb66b03cf061d75dfdacd61850f70009f78ee31", + "sha256_in_prefix": "9db2d6bc3de9539217244466bfb66b03cf061d75dfdacd61850f70009f78ee31", + "size_in_bytes": 556888 + }, + { + "_path": "lib/python3.12/lib-dynload/_curses_panel.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "d8f72c69f2143be6625ebfa0dce7093dc1d9ead52a43564959125734a7793073", + "sha256_in_prefix": "d8f72c69f2143be6625ebfa0dce7093dc1d9ead52a43564959125734a7793073", + "size_in_bytes": 78416 + }, + { + "_path": "lib/python3.12/lib-dynload/_datetime.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f8ac9aed1d613914345548a696ac6c875a215efe6f7b2316023cf3a59e46b677", + "sha256_in_prefix": "f8ac9aed1d613914345548a696ac6c875a215efe6f7b2316023cf3a59e46b677", + "size_in_bytes": 726432 + }, + { + "_path": "lib/python3.12/lib-dynload/_decimal.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "03ffc30288b3c45fbbb91c8373528c599bb1d60d9940bb2a996625c0b3feb0b1", + "sha256_in_prefix": "03ffc30288b3c45fbbb91c8373528c599bb1d60d9940bb2a996625c0b3feb0b1", + "size_in_bytes": 1648680 + }, + { + "_path": "lib/python3.12/lib-dynload/_elementtree.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "15753ca0754ca2d00e80ed8fb769975f46e2556ebddec5fb83273eb014a6f4fc", + "sha256_in_prefix": "15753ca0754ca2d00e80ed8fb769975f46e2556ebddec5fb83273eb014a6f4fc", + "size_in_bytes": 406416 + }, + { + "_path": "lib/python3.12/lib-dynload/_hashlib.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "4c35909201e031b96177fb84b9245cf2b9769191c2fb4fbae149eb627f01b745", + "sha256_in_prefix": "4c35909201e031b96177fb84b9245cf2b9769191c2fb4fbae149eb627f01b745", + "size_in_bytes": 210928 + }, + { + "_path": "lib/python3.12/lib-dynload/_heapq.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "bb1dd854911932976899d7f9dcaef9f44f9c4eddf2d485be22d5be24458d38b8", + "sha256_in_prefix": "bb1dd854911932976899d7f9dcaef9f44f9c4eddf2d485be22d5be24458d38b8", + "size_in_bytes": 105744 + }, + { + "_path": "lib/python3.12/lib-dynload/_json.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "c3d8066e4040795b447ecc15174ed1c420315e484b1a50c322ccbecc597d799d", + "sha256_in_prefix": "c3d8066e4040795b447ecc15174ed1c420315e484b1a50c322ccbecc597d799d", + "size_in_bytes": 301160 + }, + { + "_path": "lib/python3.12/lib-dynload/_lsprof.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0a96c212fb3894c731d15c141a48fcf2257f584fed5b72b112e4d7dbbe4b07e5", + "sha256_in_prefix": "0a96c212fb3894c731d15c141a48fcf2257f584fed5b72b112e4d7dbbe4b07e5", + "size_in_bytes": 195192 + }, + { + "_path": "lib/python3.12/lib-dynload/_lzma.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "106ccf6e5069aee42bd9e1d6d23c2871cebd06d9f8e0d9c14655ba973d9f5cde", + "sha256_in_prefix": "106ccf6e5069aee42bd9e1d6d23c2871cebd06d9f8e0d9c14655ba973d9f5cde", + "size_in_bytes": 155896 + }, + { + "_path": "lib/python3.12/lib-dynload/_md5.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "e9ba57b7340a9438baa91d9e0920cf7f792dc5370d043334acdd3d31740be680", + "sha256_in_prefix": "e9ba57b7340a9438baa91d9e0920cf7f792dc5370d043334acdd3d31740be680", + "size_in_bytes": 139880 + }, + { + "_path": "lib/python3.12/lib-dynload/_multibytecodec.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "ffb658b4e4e705f91f2d17475dce324ad6b1273adedacc4915a7f987118b698f", + "sha256_in_prefix": "ffb658b4e4e705f91f2d17475dce324ad6b1273adedacc4915a7f987118b698f", + "size_in_bytes": 223792 + }, + { + "_path": "lib/python3.12/lib-dynload/_multiprocessing.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "6a6e3bc70d4f8e05abc856226f57de25625073ea88f8a083880c6b9ee655e84c", + "sha256_in_prefix": "6a6e3bc70d4f8e05abc856226f57de25625073ea88f8a083880c6b9ee655e84c", + "size_in_bytes": 69272 + }, + { + "_path": "lib/python3.12/lib-dynload/_opcode.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "653f119b0b6283e274a0bd7142fbf170d67e3d481633f2bbe8ae0c0effbe6e94", + "sha256_in_prefix": "653f119b0b6283e274a0bd7142fbf170d67e3d481633f2bbe8ae0c0effbe6e94", + "size_in_bytes": 31472 + }, + { + "_path": "lib/python3.12/lib-dynload/_pickle.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "08c27e927c968819c2eafa34e8226d5c272053c2f8158bef8914bf6c7b86e4aa", + "sha256_in_prefix": "08c27e927c968819c2eafa34e8226d5c272053c2f8158bef8914bf6c7b86e4aa", + "size_in_bytes": 684360 + }, + { + "_path": "lib/python3.12/lib-dynload/_posixshmem.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "ee2fd5709b9f8581cc0545a7506060756ee5b181a8bea6bb2f348787639e3c70", + "sha256_in_prefix": "ee2fd5709b9f8581cc0545a7506060756ee5b181a8bea6bb2f348787639e3c70", + "size_in_bytes": 36328 + }, + { + "_path": "lib/python3.12/lib-dynload/_posixsubprocess.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0b65a5c3742cc66d7db8af2819e765f9db2e9c34f98f6e54e686a46f9f29d852", + "sha256_in_prefix": "0b65a5c3742cc66d7db8af2819e765f9db2e9c34f98f6e54e686a46f9f29d852", + "size_in_bytes": 171352 + }, + { + "_path": "lib/python3.12/lib-dynload/_queue.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "2c065ec715ded35c970ef0881468db7de1c049f8d13549be2b0977faaa395d9d", + "sha256_in_prefix": "2c065ec715ded35c970ef0881468db7de1c049f8d13549be2b0977faaa395d9d", + "size_in_bytes": 58920 + }, + { + "_path": "lib/python3.12/lib-dynload/_random.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "9a7cf4710906d189e2ee2b5feb2ece2efe41627795d7434d4ba3bbb87d940a53", + "sha256_in_prefix": "9a7cf4710906d189e2ee2b5feb2ece2efe41627795d7434d4ba3bbb87d940a53", + "size_in_bytes": 62784 + }, + { + "_path": "lib/python3.12/lib-dynload/_sha1.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0da28d36c32b6b19efd1c59de1d0e6fc98b25b14c2c1d16990117415bfeacd5c", + "sha256_in_prefix": "0da28d36c32b6b19efd1c59de1d0e6fc98b25b14c2c1d16990117415bfeacd5c", + "size_in_bytes": 73512 + }, + { + "_path": "lib/python3.12/lib-dynload/_sha2.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "56f0aa38650152f5e1d37d0a5bb07350cc12fabf62821e5b2ddf736f1c0f5b56", + "sha256_in_prefix": "56f0aa38650152f5e1d37d0a5bb07350cc12fabf62821e5b2ddf736f1c0f5b56", + "size_in_bytes": 459632 + }, + { + "_path": "lib/python3.12/lib-dynload/_sha3.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "5b4d9239638d58f27861858f0654f09ef923b27daa2089ae1d55f38699bd2761", + "sha256_in_prefix": "5b4d9239638d58f27861858f0654f09ef923b27daa2089ae1d55f38699bd2761", + "size_in_bytes": 116048 + }, + { + "_path": "lib/python3.12/lib-dynload/_socket.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "4388d5cd1c7d9a54577497bf1349c03b2edbf2df1e4ee9168150a724ad455d53", + "sha256_in_prefix": "4388d5cd1c7d9a54577497bf1349c03b2edbf2df1e4ee9168150a724ad455d53", + "size_in_bytes": 289712 + }, + { + "_path": "lib/python3.12/lib-dynload/_sqlite3.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0bf7bd298414ce91c44eea63d54ea7fc1dac7f2efe58172c0e71baa113380e3d", + "sha256_in_prefix": "0bf7bd298414ce91c44eea63d54ea7fc1dac7f2efe58172c0e71baa113380e3d", + "size_in_bytes": 639040 + }, + { + "_path": "lib/python3.12/lib-dynload/_ssl.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f8cfe58112234f1bb9c85b076a46ee0f83573992564610255a1c2e4066cec2f0", + "sha256_in_prefix": "f8cfe58112234f1bb9c85b076a46ee0f83573992564610255a1c2e4066cec2f0", + "size_in_bytes": 520184 + }, + { + "_path": "lib/python3.12/lib-dynload/_statistics.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "98fb620a159428d1d966400b4f682e6c791a9f79d9915e952b17c5a6dc6e0652", + "sha256_in_prefix": "98fb620a159428d1d966400b4f682e6c791a9f79d9915e952b17c5a6dc6e0652", + "size_in_bytes": 33368 + }, + { + "_path": "lib/python3.12/lib-dynload/_struct.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "bcb059cd9dd193316cce29a980ce40f440207eade68002093cb05d6b6a6b845f", + "sha256_in_prefix": "bcb059cd9dd193316cce29a980ce40f440207eade68002093cb05d6b6a6b845f", + "size_in_bytes": 218192 + }, + { + "_path": "lib/python3.12/lib-dynload/_testbuffer.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "1e6c95200286e5993c30b216bdc3edb4a85f2e6a9dfb61d9af6fd5f83295810e", + "sha256_in_prefix": "1e6c95200286e5993c30b216bdc3edb4a85f2e6a9dfb61d9af6fd5f83295810e", + "size_in_bytes": 206376 + }, + { + "_path": "lib/python3.12/lib-dynload/_testcapi.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "675d258504115bfc9fd1e527b3ee362cc283719aa8663a4e260cd9c7da27c083", + "sha256_in_prefix": "675d258504115bfc9fd1e527b3ee362cc283719aa8663a4e260cd9c7da27c083", + "size_in_bytes": 1335760 + }, + { + "_path": "lib/python3.12/lib-dynload/_testclinic.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "5db0a1cddcdf4f82cf61adabd772632fc5e98aa0afbb1a988676928063abdb35", + "sha256_in_prefix": "5db0a1cddcdf4f82cf61adabd772632fc5e98aa0afbb1a988676928063abdb35", + "size_in_bytes": 270624 + }, + { + "_path": "lib/python3.12/lib-dynload/_testimportmultiple.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "d0b7b893beceda4a7f2282767a49a8c584723b401e023a26254e7884fadbe7dd", + "sha256_in_prefix": "d0b7b893beceda4a7f2282767a49a8c584723b401e023a26254e7884fadbe7dd", + "size_in_bytes": 25672 + }, + { + "_path": "lib/python3.12/lib-dynload/_testinternalcapi.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "56e41717d0ba36d857860b03f236784d313a9c74dc224dc3685e3b273cd2608b", + "sha256_in_prefix": "56e41717d0ba36d857860b03f236784d313a9c74dc224dc3685e3b273cd2608b", + "size_in_bytes": 203296 + }, + { + "_path": "lib/python3.12/lib-dynload/_testmultiphase.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "4bcb6d1d285d4bf5e88f127f7cda8d24d19b3e4ca1f64d1880ae67395f50017b", + "sha256_in_prefix": "4bcb6d1d285d4bf5e88f127f7cda8d24d19b3e4ca1f64d1880ae67395f50017b", + "size_in_bytes": 80336 + }, + { + "_path": "lib/python3.12/lib-dynload/_testsinglephase.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "b6869bd7b3b148a8b33f7f730b61402f3cc871ebd0ad78afdb34df9335ee15f8", + "sha256_in_prefix": "b6869bd7b3b148a8b33f7f730b61402f3cc871ebd0ad78afdb34df9335ee15f8", + "size_in_bytes": 48912 + }, + { + "_path": "lib/python3.12/lib-dynload/_tkinter.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "9c2acbbfbe9b5931251746920f0d756419978365917c4b5fb9f0196dc47937aa", + "sha256_in_prefix": "9c2acbbfbe9b5931251746920f0d756419978365917c4b5fb9f0196dc47937aa", + "size_in_bytes": 305128 + }, + { + "_path": "lib/python3.12/lib-dynload/_uuid.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "01dc66ffce95ede2f0d83edf0541671cd4c9169c285901b46daa951f57ea3aec", + "sha256_in_prefix": "01dc66ffce95ede2f0d83edf0541671cd4c9169c285901b46daa951f57ea3aec", + "size_in_bytes": 26848 + }, + { + "_path": "lib/python3.12/lib-dynload/_xxinterpchannels.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "86c6495eea760d6cd4f0fc49169e7dc0f096a3b1f2bc6aeb82b09da65d238431", + "sha256_in_prefix": "86c6495eea760d6cd4f0fc49169e7dc0f096a3b1f2bc6aeb82b09da65d238431", + "size_in_bytes": 227000 + }, + { + "_path": "lib/python3.12/lib-dynload/_xxsubinterpreters.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "ad9dca4f2d7910a678835cc0afc96ff1c8a270b566062b1e91076d1f2d51df87", + "sha256_in_prefix": "ad9dca4f2d7910a678835cc0afc96ff1c8a270b566062b1e91076d1f2d51df87", + "size_in_bytes": 157760 + }, + { + "_path": "lib/python3.12/lib-dynload/_xxtestfuzz.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "c2bba0470eb6de27e326a349b6da85eef51cf7cd1de74e48c29e7927e69f0136", + "sha256_in_prefix": "c2bba0470eb6de27e326a349b6da85eef51cf7cd1de74e48c29e7927e69f0136", + "size_in_bytes": 67280 + }, + { + "_path": "lib/python3.12/lib-dynload/_zoneinfo.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "c4f7ce25500dec75b2c2129569277baa6c01539d62cd1a88957edd089aa57f6b", + "sha256_in_prefix": "c4f7ce25500dec75b2c2129569277baa6c01539d62cd1a88957edd089aa57f6b", + "size_in_bytes": 272568 + }, + { + "_path": "lib/python3.12/lib-dynload/array.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "04017441cb254a9b524f9237a8e369553d90ebc328d634886963ef88243d9556", + "sha256_in_prefix": "04017441cb254a9b524f9237a8e369553d90ebc328d634886963ef88243d9556", + "size_in_bytes": 258176 + }, + { + "_path": "lib/python3.12/lib-dynload/audioop.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "b257ef7f6db85c7d11a4699fab8e4661773a6903e120390f495c589a09814085", + "sha256_in_prefix": "b257ef7f6db85c7d11a4699fab8e4661773a6903e120390f495c589a09814085", + "size_in_bytes": 229592 + }, + { + "_path": "lib/python3.12/lib-dynload/binascii.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "842cc16f5f2f516a465faeceffef1f300d61940bdbeeb832691b2d3aaf36790c", + "sha256_in_prefix": "842cc16f5f2f516a465faeceffef1f300d61940bdbeeb832691b2d3aaf36790c", + "size_in_bytes": 191504 + }, + { + "_path": "lib/python3.12/lib-dynload/cmath.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f2a5bb3d6f2def6a5e9cebfb9c6c0ce6bea88bf0db9d10697ccadcf7ce23d0bb", + "sha256_in_prefix": "f2a5bb3d6f2def6a5e9cebfb9c6c0ce6bea88bf0db9d10697ccadcf7ce23d0bb", + "size_in_bytes": 169272 + }, + { + "_path": "lib/python3.12/lib-dynload/fcntl.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "abe1aae762ea217f4fa3912b435d88a18f7464fb892623bce2d6e2c1bf0758aa", + "sha256_in_prefix": "abe1aae762ea217f4fa3912b435d88a18f7464fb892623bce2d6e2c1bf0758aa", + "size_in_bytes": 54752 + }, + { + "_path": "lib/python3.12/lib-dynload/grp.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "fdb4319cde00e5a740e0eaee68f08acd01a45ec8f3711ed27ef0f1f0b2d26215", + "sha256_in_prefix": "fdb4319cde00e5a740e0eaee68f08acd01a45ec8f3711ed27ef0f1f0b2d26215", + "size_in_bytes": 56640 + }, + { + "_path": "lib/python3.12/lib-dynload/math.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "6e8e9c55cab405da1474888667379574dd241a42eaabbc40820d177cc624370b", + "sha256_in_prefix": "6e8e9c55cab405da1474888667379574dd241a42eaabbc40820d177cc624370b", + "size_in_bytes": 382024 + }, + { + "_path": "lib/python3.12/lib-dynload/mmap.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f918ba2d04923f2f9e1f1f6c33d2cdd89ff0f47964cfcfa9f0221388505648e1", + "sha256_in_prefix": "f918ba2d04923f2f9e1f1f6c33d2cdd89ff0f47964cfcfa9f0221388505648e1", + "size_in_bytes": 91920 + }, + { + "_path": "lib/python3.12/lib-dynload/nis.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "8a63218bfe40cc1e30b9db54b2e564c557b330e0e925da234e3525753a003d65", + "sha256_in_prefix": "8a63218bfe40cc1e30b9db54b2e564c557b330e0e925da234e3525753a003d65", + "size_in_bytes": 59880 + }, + { + "_path": "lib/python3.12/lib-dynload/ossaudiodev.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "9a1b46a728e480a2c31c5cbafd24b2874ecdb55c0f4a0714e4752fa34fa579ad", + "sha256_in_prefix": "9a1b46a728e480a2c31c5cbafd24b2874ecdb55c0f4a0714e4752fa34fa579ad", + "size_in_bytes": 100720 + }, + { + "_path": "lib/python3.12/lib-dynload/pyexpat.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "3c898357dae216125feb80dd49788a267aa60db3d20cd3099bdad348ed9798fc", + "sha256_in_prefix": "3c898357dae216125feb80dd49788a267aa60db3d20cd3099bdad348ed9798fc", + "size_in_bytes": 230664 + }, + { + "_path": "lib/python3.12/lib-dynload/readline.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "090f6845f9e0913d913877805ade09dcca766b00899a700855d599cfa53940a0", + "sha256_in_prefix": "090f6845f9e0913d913877805ade09dcca766b00899a700855d599cfa53940a0", + "size_in_bytes": 116744 + }, + { + "_path": "lib/python3.12/lib-dynload/resource.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f3e94d401d6a0784817582dbbda0520b2ac1f4fe19daddbf7b96f3b868ac369c", + "sha256_in_prefix": "f3e94d401d6a0784817582dbbda0520b2ac1f4fe19daddbf7b96f3b868ac369c", + "size_in_bytes": 51136 + }, + { + "_path": "lib/python3.12/lib-dynload/select.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "12a4b15c488208960386f70027156c2c21d947020997422a2acbef298d5764ba", + "sha256_in_prefix": "12a4b15c488208960386f70027156c2c21d947020997422a2acbef298d5764ba", + "size_in_bytes": 116232 + }, + { + "_path": "lib/python3.12/lib-dynload/spwd.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "fe3c0e862f453bda965da17838cb3bca0e3ee52a7f803be5330781fdcd26d143", + "sha256_in_prefix": "fe3c0e862f453bda965da17838cb3bca0e3ee52a7f803be5330781fdcd26d143", + "size_in_bytes": 47744 + }, + { + "_path": "lib/python3.12/lib-dynload/syslog.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0fad7ab554e8833f1dc81faf3f49b730399b47bb75d408267a08b6e957c1a251", + "sha256_in_prefix": "0fad7ab554e8833f1dc81faf3f49b730399b47bb75d408267a08b6e957c1a251", + "size_in_bytes": 52128 + }, + { + "_path": "lib/python3.12/lib-dynload/termios.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "3ad2ef63d661130f224793a6508e96ee154f477141cf3a28ca451aaa097fecad", + "sha256_in_prefix": "3ad2ef63d661130f224793a6508e96ee154f477141cf3a28ca451aaa097fecad", + "size_in_bytes": 79400 + }, + { + "_path": "lib/python3.12/lib-dynload/unicodedata.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "0b8dfd003822225f420cdce2bf626aaff3063e9083ad8bd9f0c5dcb96b9538c3", + "sha256_in_prefix": "0b8dfd003822225f420cdce2bf626aaff3063e9083ad8bd9f0c5dcb96b9538c3", + "size_in_bytes": 1239112 + }, + { + "_path": "lib/python3.12/lib-dynload/xxlimited.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "f502a54513dfc7e484e7a33a9d7813ed543400626b8bafdb65a0254e48da2c5f", + "sha256_in_prefix": "f502a54513dfc7e484e7a33a9d7813ed543400626b8bafdb65a0254e48da2c5f", + "size_in_bytes": 41168 + }, + { + "_path": "lib/python3.12/lib-dynload/xxlimited_35.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "e60a756648d4c9fbdbc0483c6b6efb9e744cf2b9e51424c19507762f13efdef4", + "sha256_in_prefix": "e60a756648d4c9fbdbc0483c6b6efb9e744cf2b9e51424c19507762f13efdef4", + "size_in_bytes": 37688 + }, + { + "_path": "lib/python3.12/lib-dynload/xxsubtype.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "52d9f154c64ba72dd232a9775c94fb298e7dae1bb70fd808ef5c398f38608275", + "sha256_in_prefix": "52d9f154c64ba72dd232a9775c94fb298e7dae1bb70fd808ef5c398f38608275", + "size_in_bytes": 36944 + }, + { + "_path": "lib/python3.12/lib-dynload/zlib.cpython-312-x86_64-linux-gnu.so", + "path_type": "hardlink", + "sha256": "ba01c6ff0b0ffa9b375c391c33e2b88777f6147e25b4659498c3d023e4191676", + "sha256_in_prefix": "ba01c6ff0b0ffa9b375c391c33e2b88777f6147e25b4659498c3d023e4191676", + "size_in_bytes": 166736 + }, + { + "_path": "lib/python3.12/lib2to3/Grammar.txt", + "path_type": "hardlink", + "sha256": "508e62e787dd756eb0a4eb1b8d128320ca02cd246ab14cc8ce0a476dc88cc5b6", + "sha256_in_prefix": "508e62e787dd756eb0a4eb1b8d128320ca02cd246ab14cc8ce0a476dc88cc5b6", + "size_in_bytes": 8696 + }, + { + "_path": "lib/python3.12/lib2to3/Grammar3.12.3.final.0.pickle", + "path_type": "hardlink", + "sha256": "97c8ed74d091fcfd23498029bb819c29d096c3dcb1326edee5dfb0591ade2e4b", + "sha256_in_prefix": "97c8ed74d091fcfd23498029bb819c29d096c3dcb1326edee5dfb0591ade2e4b", + "size_in_bytes": 15313 + }, + { + "_path": "lib/python3.12/lib2to3/PatternGrammar.txt", + "path_type": "hardlink", + "sha256": "ee5ba5db3b6722a0e2fbe2560ebc1c883e72328ef9c3b4da1c7c5d1cc649bce3", + "sha256_in_prefix": "ee5ba5db3b6722a0e2fbe2560ebc1c883e72328ef9c3b4da1c7c5d1cc649bce3", + "size_in_bytes": 793 + }, + { + "_path": "lib/python3.12/lib2to3/PatternGrammar3.12.3.final.0.pickle", + "path_type": "hardlink", + "sha256": "36ee934395b9209737b13893ddaff05fad8e239c2fdfac29d401d3fceeb30768", + "sha256_in_prefix": "36ee934395b9209737b13893ddaff05fad8e239c2fdfac29d401d3fceeb30768", + "size_in_bytes": 1225 + }, + { + "_path": "lib/python3.12/lib2to3/__init__.py", + "path_type": "hardlink", + "sha256": "5373a81ab198cda8e95652dff46ecfee197a0b8901e8432ab448d97b8bc37f87", + "sha256_in_prefix": "5373a81ab198cda8e95652dff46ecfee197a0b8901e8432ab448d97b8bc37f87", + "size_in_bytes": 156 + }, + { + "_path": "lib/python3.12/lib2to3/__main__.py", + "path_type": "hardlink", + "sha256": "c7b09f90e66dea194ad63dc02c6425dff977d16f1f21a157b7475905c219a707", + "sha256_in_prefix": "c7b09f90e66dea194ad63dc02c6425dff977d16f1f21a157b7475905c219a707", + "size_in_bytes": 67 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0b4ce9b4db4f77668af0b9eabcef1607d4802ad40bae1e3fbed11ad426529783", + "sha256_in_prefix": "0b4ce9b4db4f77668af0b9eabcef1607d4802ad40bae1e3fbed11ad426529783", + "size_in_bytes": 339 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7595e052d4aeddd51d33da465b33a8482e5b09d9d1adb4e0a67c4f2c1b2ccc55", + "sha256_in_prefix": "7595e052d4aeddd51d33da465b33a8482e5b09d9d1adb4e0a67c4f2c1b2ccc55", + "size_in_bytes": 270 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/btm_matcher.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "379f7ee9c904ce6a37177763fb598b76a2c52b556ef9668254f011b1bad115c0", + "sha256_in_prefix": "379f7ee9c904ce6a37177763fb598b76a2c52b556ef9668254f011b1bad115c0", + "size_in_bytes": 7366 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/btm_utils.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "63af908f2a1f128e906bcca31028b29a8b2e17d6ee0740cb8d207dc205fb1575", + "sha256_in_prefix": "63af908f2a1f128e906bcca31028b29a8b2e17d6ee0740cb8d207dc205fb1575", + "size_in_bytes": 11119 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/fixer_base.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4d301982957ed016928e70266f9350de4a52d12c22adbafedae97c96386e6052", + "sha256_in_prefix": "4d301982957ed016928e70266f9350de4a52d12c22adbafedae97c96386e6052", + "size_in_bytes": 7864 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/fixer_util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0fa72c17f94d43c3d7ec00f9e494ba8523e7d1581131da1aaeef07b03dfa45f7", + "sha256_in_prefix": "0fa72c17f94d43c3d7ec00f9e494ba8523e7d1581131da1aaeef07b03dfa45f7", + "size_in_bytes": 21823 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/main.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "228b9f669634fbbaea87cd9160e4855e56e1fb1f2364b3a8b3ba489dd379f203", + "sha256_in_prefix": "228b9f669634fbbaea87cd9160e4855e56e1fb1f2364b3a8b3ba489dd379f203", + "size_in_bytes": 14083 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/patcomp.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2157c527db23b1f6697e48ddeed7dfacece1829c18b37240181b0a3c6bb256d7", + "sha256_in_prefix": "2157c527db23b1f6697e48ddeed7dfacece1829c18b37240181b0a3c6bb256d7", + "size_in_bytes": 9962 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/pygram.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d7be8d1a5eb372f1676a86d84ee3c6c98eef00dd37683779f587a762675ab1f0", + "sha256_in_prefix": "d7be8d1a5eb372f1676a86d84ee3c6c98eef00dd37683779f587a762675ab1f0", + "size_in_bytes": 1892 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/pytree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "861d45d589d3355b5472d4ef25b41dee7c9aae422f56238621ef6ad685a90b4e", + "sha256_in_prefix": "861d45d589d3355b5472d4ef25b41dee7c9aae422f56238621ef6ad685a90b4e", + "size_in_bytes": 34834 + }, + { + "_path": "lib/python3.12/lib2to3/__pycache__/refactor.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e52fed3374f99fcea00cf8bd1f048b62e219ed43fa9a7e630c4e9d94a6da2712", + "sha256_in_prefix": "e52fed3374f99fcea00cf8bd1f048b62e219ed43fa9a7e630c4e9d94a6da2712", + "size_in_bytes": 34490 + }, + { + "_path": "lib/python3.12/lib2to3/btm_matcher.py", + "path_type": "hardlink", + "sha256": "a1aa5d35558acf4b6016054963285cb145f97a764926bea07cbd674563f3248d", + "sha256_in_prefix": "a1aa5d35558acf4b6016054963285cb145f97a764926bea07cbd674563f3248d", + "size_in_bytes": 6623 + }, + { + "_path": "lib/python3.12/lib2to3/btm_utils.py", + "path_type": "hardlink", + "sha256": "c0653eb497a1a48195dd9c4ecbbf87e4eab31188be29ab1640e353209741588c", + "sha256_in_prefix": "c0653eb497a1a48195dd9c4ecbbf87e4eab31188be29ab1640e353209741588c", + "size_in_bytes": 9945 + }, + { + "_path": "lib/python3.12/lib2to3/fixer_base.py", + "path_type": "hardlink", + "sha256": "c795a53ca849c42212c8ec33a74284e0377df852eb4ea599aba62d5af1df282a", + "sha256_in_prefix": "c795a53ca849c42212c8ec33a74284e0377df852eb4ea599aba62d5af1df282a", + "size_in_bytes": 6690 + }, + { + "_path": "lib/python3.12/lib2to3/fixer_util.py", + "path_type": "hardlink", + "sha256": "306d0b2ea8169bdca711c6a31c0b1a3ce710d38ae2b6568ef519aa38451af608", + "sha256_in_prefix": "306d0b2ea8169bdca711c6a31c0b1a3ce710d38ae2b6568ef519aa38451af608", + "size_in_bytes": 15206 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__init__.py", + "path_type": "hardlink", + "sha256": "836cdb388117cf81e78d9fa2a141cca1b14b0179733322e710067749a1b16fe9", + "sha256_in_prefix": "836cdb388117cf81e78d9fa2a141cca1b14b0179733322e710067749a1b16fe9", + "size_in_bytes": 47 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0d77133e10b06ac8a4b7dc1663e6d6b55f282345ddb82e183ca9e3b8350f7590", + "sha256_in_prefix": "0d77133e10b06ac8a4b7dc1663e6d6b55f282345ddb82e183ca9e3b8350f7590", + "size_in_bytes": 137 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_apply.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e44a7bc09f685a3c37b9899142c46246867c7161469ca94a9223b4ef485365c9", + "sha256_in_prefix": "e44a7bc09f685a3c37b9899142c46246867c7161469ca94a9223b4ef485365c9", + "size_in_bytes": 2764 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_asserts.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b9aebe42d718ce3084abec8400773931e509a1e5bc56eb001f61ab50f1a356d", + "sha256_in_prefix": "5b9aebe42d718ce3084abec8400773931e509a1e5bc56eb001f61ab50f1a356d", + "size_in_bytes": 1519 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_basestring.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5bf897b809dd9fd336f61d9d172ddc45784ac93fbf0a106a23b5d18951768d2e", + "sha256_in_prefix": "5bf897b809dd9fd336f61d9d172ddc45784ac93fbf0a106a23b5d18951768d2e", + "size_in_bytes": 765 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_buffer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b6a0c72c5365feecf72d2cbf26c31df77f2798f8b4f45b253d04f5c231ed1763", + "sha256_in_prefix": "b6a0c72c5365feecf72d2cbf26c31df77f2798f8b4f45b253d04f5c231ed1763", + "size_in_bytes": 955 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_dict.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9b509f06bdb32f7ad6ec666cad7402e602d67afd4c61aa9f5305a64df2b1d496", + "sha256_in_prefix": "9b509f06bdb32f7ad6ec666cad7402e602d67afd4c61aa9f5305a64df2b1d496", + "size_in_bytes": 4572 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_except.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b525203e76846d84ef9de467e151188e35d68274d3e13a8163d731add41b867f", + "sha256_in_prefix": "b525203e76846d84ef9de467e151188e35d68274d3e13a8163d731add41b867f", + "size_in_bytes": 4023 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_exec.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1acd52fbc1f32e2b1f043f685a1145bee332992ccc240d268ff7c077b99f4242", + "sha256_in_prefix": "1acd52fbc1f32e2b1f043f685a1145bee332992ccc240d268ff7c077b99f4242", + "size_in_bytes": 1600 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_execfile.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a52f48b07efcd8a5ee5acc741f491aa83f95758cafc1289497ebb9ae626d93d0", + "sha256_in_prefix": "a52f48b07efcd8a5ee5acc741f491aa83f95758cafc1289497ebb9ae626d93d0", + "size_in_bytes": 2731 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_exitfunc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bc1148287546e4455255ec026986988aa08391a9d695a89dbcc8b42f5f9fa689", + "sha256_in_prefix": "bc1148287546e4455255ec026986988aa08391a9d695a89dbcc8b42f5f9fa689", + "size_in_bytes": 3564 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_filter.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "401c82809504ba218125d3a137a350371f9f0f5fddf8dcc4665fd4e2230427ee", + "sha256_in_prefix": "401c82809504ba218125d3a137a350371f9f0f5fddf8dcc4665fd4e2230427ee", + "size_in_bytes": 3602 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_funcattrs.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e98b67ed066077e0fc92078039e4ee8a9caa64370bdba140ae8d722d773563c2", + "sha256_in_prefix": "e98b67ed066077e0fc92078039e4ee8a9caa64370bdba140ae8d722d773563c2", + "size_in_bytes": 1159 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_future.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "797776aaa6c76f42cc6306750f297dfbc2f9d9f47fdfdd19cc0f2d71508d6afa", + "sha256_in_prefix": "797776aaa6c76f42cc6306750f297dfbc2f9d9f47fdfdd19cc0f2d71508d6afa", + "size_in_bytes": 904 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_getcwdu.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cba3a52e9f15e79591bb34ee1fa796b44ec8253332276e39e1faf9a008a77730", + "sha256_in_prefix": "cba3a52e9f15e79591bb34ee1fa796b44ec8253332276e39e1faf9a008a77730", + "size_in_bytes": 932 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_has_key.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "20427ac2be9afd0ec9517d3a436595d7ac86ebef537462f6379acc1d4a150c22", + "sha256_in_prefix": "20427ac2be9afd0ec9517d3a436595d7ac86ebef537462f6379acc1d4a150c22", + "size_in_bytes": 4209 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_idioms.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e0454438456137598bc026e43bc3fd4c3e6e916e4b9620742c4ede1da75636e0", + "sha256_in_prefix": "e0454438456137598bc026e43bc3fd4c3e6e916e4b9620742c4ede1da75636e0", + "size_in_bytes": 5455 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_import.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9ca5d4879e1783e3d4fb03595c1d7c1fb0f5e2876d5689bc9f38a835a21ab856", + "sha256_in_prefix": "9ca5d4879e1783e3d4fb03595c1d7c1fb0f5e2876d5689bc9f38a835a21ab856", + "size_in_bytes": 4251 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_imports.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0a1a54703e66b5afd8b34fe8e683504727880e6b0a102239930626c7d10bf427", + "sha256_in_prefix": "0a1a54703e66b5afd8b34fe8e683504727880e6b0a102239930626c7d10bf427", + "size_in_bytes": 6092 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_imports2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "61ad0747ef021df237f71230d1880dd46bc98657dc9146f1b6a9af9f15890992", + "sha256_in_prefix": "61ad0747ef021df237f71230d1880dd46bc98657dc9146f1b6a9af9f15890992", + "size_in_bytes": 605 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_input.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ca6fc22c85d552c9702838434860767f71e9f556f0b716e648bade67a85da9fc", + "sha256_in_prefix": "ca6fc22c85d552c9702838434860767f71e9f556f0b716e648bade67a85da9fc", + "size_in_bytes": 1256 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_intern.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "fea2839ff887a2499c20fd297d48fc92029a24a25e6efcdc3047bd38e49592af", + "sha256_in_prefix": "fea2839ff887a2499c20fd297d48fc92029a24a25e6efcdc3047bd38e49592af", + "size_in_bytes": 1399 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_isinstance.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "524b32fc51cff8eeda7d2db4311c30f364c987b16d5d834b604c9f66f7ee922a", + "sha256_in_prefix": "524b32fc51cff8eeda7d2db4311c30f364c987b16d5d834b604c9f66f7ee922a", + "size_in_bytes": 2341 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_itertools.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6dbc3906c2eccb9a466c4f600a5ad7b51a20bdbe8dee876fe3407520e08ceeae", + "sha256_in_prefix": "6dbc3906c2eccb9a466c4f600a5ad7b51a20bdbe8dee876fe3407520e08ceeae", + "size_in_bytes": 1967 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_itertools_imports.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "850202766d99b180f60dfc98ff04206cccb2ffb991ffbeb6aea7532bbfe3e917", + "sha256_in_prefix": "850202766d99b180f60dfc98ff04206cccb2ffb991ffbeb6aea7532bbfe3e917", + "size_in_bytes": 2711 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_long.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "69f6228ec2dc2586b3ba227ad07a0c6cafe30faff4356dd43b17888fcc92caa5", + "sha256_in_prefix": "69f6228ec2dc2586b3ba227ad07a0c6cafe30faff4356dd43b17888fcc92caa5", + "size_in_bytes": 831 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_map.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "dedb361029a36a8a2e95f210e1c8413b1a622904b53813e5fc89f83a6858ece8", + "sha256_in_prefix": "dedb361029a36a8a2e95f210e1c8413b1a622904b53813e5fc89f83a6858ece8", + "size_in_bytes": 4502 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_metaclass.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c6247c583dfd3418a29275512ec5a5ee982f7a6b2d38197d22538498d43b09f5", + "sha256_in_prefix": "c6247c583dfd3418a29275512ec5a5ee982f7a6b2d38197d22538498d43b09f5", + "size_in_bytes": 10458 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_methodattrs.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7afd7fccec829a2a736af8c78f2d26ed4812307c1afe5425172a6ca31735f4a2", + "sha256_in_prefix": "7afd7fccec829a2a736af8c78f2d26ed4812307c1afe5425172a6ca31735f4a2", + "size_in_bytes": 1139 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_ne.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "57cc7a08271a030376a666dd79d00a4a6b4ee80e30a4fe00b741c44a74952763", + "sha256_in_prefix": "57cc7a08271a030376a666dd79d00a4a6b4ee80e30a4fe00b741c44a74952763", + "size_in_bytes": 1030 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_next.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8946396fca1d7e72138725cfdc3554fb105d892590767d9aeff2c9bd31c22457", + "sha256_in_prefix": "8946396fca1d7e72138725cfdc3554fb105d892590767d9aeff2c9bd31c22457", + "size_in_bytes": 4357 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_nonzero.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c780bec303a912bbebddf1835841f6f8877c6306bbba28b413996a72fc5c45cc", + "sha256_in_prefix": "c780bec303a912bbebddf1835841f6f8877c6306bbba28b413996a72fc5c45cc", + "size_in_bytes": 1069 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_numliterals.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8082ae79f4ad7e2ac88ad2c298c7adce1b7509707bf3522f13dd12087367f3fc", + "sha256_in_prefix": "8082ae79f4ad7e2ac88ad2c298c7adce1b7509707bf3522f13dd12087367f3fc", + "size_in_bytes": 1424 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_operator.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c52d177d2c1d494871a5da23d87b8649261e479604c998998f5d92114fa2cde9", + "sha256_in_prefix": "c52d177d2c1d494871a5da23d87b8649261e479604c998998f5d92114fa2cde9", + "size_in_bytes": 5610 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_paren.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "125ccff8cb3d573d9a4bb2ddf59828e25b638844737fa5e042baa01dd8d05d13", + "sha256_in_prefix": "125ccff8cb3d573d9a4bb2ddf59828e25b638844737fa5e042baa01dd8d05d13", + "size_in_bytes": 1616 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_print.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "155816206f34a1e21aa8fe4326682bcc386f0a07703e664310aad2ca34c5fa37", + "sha256_in_prefix": "155816206f34a1e21aa8fe4326682bcc386f0a07703e664310aad2ca34c5fa37", + "size_in_bytes": 3495 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_raise.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c5be6486b897934a1a8b35b446923f36bbc170e50267efdd68e11713ab9e9132", + "sha256_in_prefix": "c5be6486b897934a1a8b35b446923f36bbc170e50267efdd68e11713ab9e9132", + "size_in_bytes": 3373 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_raw_input.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5433314c1a5cc4c0251522a708b6827958aba57084cf720cec112b1d187382e7", + "sha256_in_prefix": "5433314c1a5cc4c0251522a708b6827958aba57084cf720cec112b1d187382e7", + "size_in_bytes": 937 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_reduce.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1dba43f0672f3157988f85f852cf0a217d24bec0e7768477f64b9483f5a50f55", + "sha256_in_prefix": "1dba43f0672f3157988f85f852cf0a217d24bec0e7768477f64b9483f5a50f55", + "size_in_bytes": 1212 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_reload.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e65faff7b2e5e936b464e2dbe3b860f3b76b44508e541aea1e4fb069cfc19fd0", + "sha256_in_prefix": "e65faff7b2e5e936b464e2dbe3b860f3b76b44508e541aea1e4fb069cfc19fd0", + "size_in_bytes": 1411 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_renames.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "71d4bd7efe7a3071e3606d85e831ec80b184e5066a61745173ea0a42c1c0c9b8", + "sha256_in_prefix": "71d4bd7efe7a3071e3606d85e831ec80b184e5066a61745173ea0a42c1c0c9b8", + "size_in_bytes": 2859 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_repr.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a4c9ae9f2d689e49e94d108799b4124c28cebc4b31548eddb5dedd519dec48fd", + "sha256_in_prefix": "a4c9ae9f2d689e49e94d108799b4124c28cebc4b31548eddb5dedd519dec48fd", + "size_in_bytes": 1117 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_set_literal.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "33825a31bd5b3d63dce683346291bf1d055066a6d839c36037e6495a34fad827", + "sha256_in_prefix": "33825a31bd5b3d63dce683346291bf1d055066a6d839c36037e6495a34fad827", + "size_in_bytes": 2621 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_standarderror.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cd0a3d2bf73541b092caafe43fda22636f64017b9ed8da7c48c3930cf3218756", + "sha256_in_prefix": "cd0a3d2bf73541b092caafe43fda22636f64017b9ed8da7c48c3930cf3218756", + "size_in_bytes": 826 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_sys_exc.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "efdc7227cdabacf3da31b4b1963a242c4ea27d269c7b8e60746ef152f4ac524c", + "sha256_in_prefix": "efdc7227cdabacf3da31b4b1963a242c4ea27d269c7b8e60746ef152f4ac524c", + "size_in_bytes": 2004 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_throw.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "24f834c32f7677ea82244620b3c1a355460b1577a0c1f69288bb2c07245caa78", + "sha256_in_prefix": "24f834c32f7677ea82244620b3c1a355460b1577a0c1f69288bb2c07245caa78", + "size_in_bytes": 2437 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_tuple_params.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2dbe90ebae35d05ceee4f2658aabdaff0602884b8ec486dbc54bb1546e170e8e", + "sha256_in_prefix": "2dbe90ebae35d05ceee4f2658aabdaff0602884b8ec486dbc54bb1546e170e8e", + "size_in_bytes": 7851 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_types.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ef280379cdd1aacab92861be7e9e022eb58c268cef533cfcb5705b41adcd06d1", + "sha256_in_prefix": "ef280379cdd1aacab92861be7e9e022eb58c268cef533cfcb5705b41adcd06d1", + "size_in_bytes": 2266 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_unicode.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bbf36d394da269c2ab2abf025e088687cac4d5bedeb969fae7250fb14a2a6e20", + "sha256_in_prefix": "bbf36d394da269c2ab2abf025e088687cac4d5bedeb969fae7250fb14a2a6e20", + "size_in_bytes": 2154 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_urllib.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8074c2b41a02119272a3f4f977b50d6b39adeaac7966f0694e470df3967becf4", + "sha256_in_prefix": "8074c2b41a02119272a3f4f977b50d6b39adeaac7966f0694e470df3967becf4", + "size_in_bytes": 9196 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_ws_comma.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c9aa241e13767dee52c14c12e8913f984b518c5a582d410600b19e355daa0ac5", + "sha256_in_prefix": "c9aa241e13767dee52c14c12e8913f984b518c5a582d410600b19e355daa0ac5", + "size_in_bytes": 1551 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_xrange.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d452631b1858316327ab9be60914ba899862d006c6a9e2f13711f7900c5a9d32", + "sha256_in_prefix": "d452631b1858316327ab9be60914ba899862d006c6a9e2f13711f7900c5a9d32", + "size_in_bytes": 3810 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_xreadlines.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f36da33983dc752f970b3081a857c657382ff8e255ad26d69f4202e245b35e85", + "sha256_in_prefix": "f36da33983dc752f970b3081a857c657382ff8e255ad26d69f4202e245b35e85", + "size_in_bytes": 1271 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/__pycache__/fix_zip.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "366767f99bcaea0fd8ecf963faeb279a32b0c69759fe0dd76a6d3db208c9a7f7", + "sha256_in_prefix": "366767f99bcaea0fd8ecf963faeb279a32b0c69759fe0dd76a6d3db208c9a7f7", + "size_in_bytes": 1972 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_apply.py", + "path_type": "hardlink", + "sha256": "b5171e32758a78450854f40867775d4aca58665bc920ebece04fcfcc153af02a", + "sha256_in_prefix": "b5171e32758a78450854f40867775d4aca58665bc920ebece04fcfcc153af02a", + "size_in_bytes": 2346 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_asserts.py", + "path_type": "hardlink", + "sha256": "4c77972812cb5ec0a72afbce3e1d618c27ef7b239329c5c952c2bcbe77dba5dd", + "sha256_in_prefix": "4c77972812cb5ec0a72afbce3e1d618c27ef7b239329c5c952c2bcbe77dba5dd", + "size_in_bytes": 984 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_basestring.py", + "path_type": "hardlink", + "sha256": "d041443d6499a735bb78fec9da1bf33b3d034b5192c98bc273b16a44692fc88f", + "sha256_in_prefix": "d041443d6499a735bb78fec9da1bf33b3d034b5192c98bc273b16a44692fc88f", + "size_in_bytes": 320 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_buffer.py", + "path_type": "hardlink", + "sha256": "2da37b49c30d6a0b4db43146ebb4ac8e5ffcb9814816b4742e464cb856977883", + "sha256_in_prefix": "2da37b49c30d6a0b4db43146ebb4ac8e5ffcb9814816b4742e464cb856977883", + "size_in_bytes": 590 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_dict.py", + "path_type": "hardlink", + "sha256": "38f460596ebfb64046aab3d9a65935bd4c76a470118fb7d10a088dc0ecdc53ea", + "sha256_in_prefix": "38f460596ebfb64046aab3d9a65935bd4c76a470118fb7d10a088dc0ecdc53ea", + "size_in_bytes": 3760 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_except.py", + "path_type": "hardlink", + "sha256": "7ff6f560c3c3d7a5d9ceef5ba31c556341f7ce1bc1b52d96b063f6c2c4765651", + "sha256_in_prefix": "7ff6f560c3c3d7a5d9ceef5ba31c556341f7ce1bc1b52d96b063f6c2c4765651", + "size_in_bytes": 3344 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_exec.py", + "path_type": "hardlink", + "sha256": "9e0893327205dea12004e88d18c580286e7977e081b5eda7baf5b7bc93bc6c52", + "sha256_in_prefix": "9e0893327205dea12004e88d18c580286e7977e081b5eda7baf5b7bc93bc6c52", + "size_in_bytes": 979 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_execfile.py", + "path_type": "hardlink", + "sha256": "6ff65db1192099457cb3d9f2618a893c6ac430028550284f3a34d5c08042b0eb", + "sha256_in_prefix": "6ff65db1192099457cb3d9f2618a893c6ac430028550284f3a34d5c08042b0eb", + "size_in_bytes": 2048 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_exitfunc.py", + "path_type": "hardlink", + "sha256": "ef4f18f651d32410c43644c27590903d41e38e763b0e108e6c685a3412a7d29c", + "sha256_in_prefix": "ef4f18f651d32410c43644c27590903d41e38e763b0e108e6c685a3412a7d29c", + "size_in_bytes": 2495 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_filter.py", + "path_type": "hardlink", + "sha256": "2c7f0121193395750eab2b2abf5059d9a3b1a61f81763f52511265d7bca5cb21", + "sha256_in_prefix": "2c7f0121193395750eab2b2abf5059d9a3b1a61f81763f52511265d7bca5cb21", + "size_in_bytes": 2765 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_funcattrs.py", + "path_type": "hardlink", + "sha256": "111df53fac6a121d61abe33883a68e731820ddc4864b0a4c1000cf2ac5f019cd", + "sha256_in_prefix": "111df53fac6a121d61abe33883a68e731820ddc4864b0a4c1000cf2ac5f019cd", + "size_in_bytes": 644 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_future.py", + "path_type": "hardlink", + "sha256": "baba8cafb48dd9181a0e1f7b0f20b585ce2925e8f347e00b87407a256bb16663", + "sha256_in_prefix": "baba8cafb48dd9181a0e1f7b0f20b585ce2925e8f347e00b87407a256bb16663", + "size_in_bytes": 547 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_getcwdu.py", + "path_type": "hardlink", + "sha256": "5bc5252f683a401e7d81c5911617c4af1a1bcdf99a51c4bf1cfccb00446ff220", + "sha256_in_prefix": "5bc5252f683a401e7d81c5911617c4af1a1bcdf99a51c4bf1cfccb00446ff220", + "size_in_bytes": 451 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_has_key.py", + "path_type": "hardlink", + "sha256": "32943d3b921c1c3f0d3776d19e5120806990b817bc99a7e22799847abfda1f63", + "sha256_in_prefix": "32943d3b921c1c3f0d3776d19e5120806990b817bc99a7e22799847abfda1f63", + "size_in_bytes": 3196 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_idioms.py", + "path_type": "hardlink", + "sha256": "600e34faf36e14307e59d55088e3979881d497b8fc9d77659e77709f9e8bafd7", + "sha256_in_prefix": "600e34faf36e14307e59d55088e3979881d497b8fc9d77659e77709f9e8bafd7", + "size_in_bytes": 4876 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_import.py", + "path_type": "hardlink", + "sha256": "803baf96f9603c957eb974f252b0ad9829c889a293e0ce6829db1bce3da6dd4e", + "sha256_in_prefix": "803baf96f9603c957eb974f252b0ad9829c889a293e0ce6829db1bce3da6dd4e", + "size_in_bytes": 3256 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_imports.py", + "path_type": "hardlink", + "sha256": "cdf7ee6d85e2b148230984cfc4ea3f193be458958ea42ef290854a9672a64370", + "sha256_in_prefix": "cdf7ee6d85e2b148230984cfc4ea3f193be458958ea42ef290854a9672a64370", + "size_in_bytes": 5684 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_imports2.py", + "path_type": "hardlink", + "sha256": "b6f3c628839ffe7fd72569dd6ca2210e18edae3e180002747ea011b76b7ec0ef", + "sha256_in_prefix": "b6f3c628839ffe7fd72569dd6ca2210e18edae3e180002747ea011b76b7ec0ef", + "size_in_bytes": 289 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_input.py", + "path_type": "hardlink", + "sha256": "10c5ef3b45a4ee7e88af8852181916a788aae2bea52b08f3473815c1c43598d1", + "sha256_in_prefix": "10c5ef3b45a4ee7e88af8852181916a788aae2bea52b08f3473815c1c43598d1", + "size_in_bytes": 708 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_intern.py", + "path_type": "hardlink", + "sha256": "8d29a162536b99c91bd2f9259dda7f39fec751949d6354d2c1f2e5d070c87d66", + "sha256_in_prefix": "8d29a162536b99c91bd2f9259dda7f39fec751949d6354d2c1f2e5d070c87d66", + "size_in_bytes": 1144 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_isinstance.py", + "path_type": "hardlink", + "sha256": "8408c92b99f50d8c4978b47a2b2155588e315f2ebbe58c160dcdcdcb89e19914", + "sha256_in_prefix": "8408c92b99f50d8c4978b47a2b2155588e315f2ebbe58c160dcdcdcb89e19914", + "size_in_bytes": 1608 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_itertools.py", + "path_type": "hardlink", + "sha256": "578a51b9935020b03a510de15ece55fcd02c9474f37a54c158fb97ba5fd15af1", + "sha256_in_prefix": "578a51b9935020b03a510de15ece55fcd02c9474f37a54c158fb97ba5fd15af1", + "size_in_bytes": 1548 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_itertools_imports.py", + "path_type": "hardlink", + "sha256": "2e419cfbd7f2a326ae7fa10873aa377112ebec32545238fdf988acb088c3cdb7", + "sha256_in_prefix": "2e419cfbd7f2a326ae7fa10873aa377112ebec32545238fdf988acb088c3cdb7", + "size_in_bytes": 2086 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_long.py", + "path_type": "hardlink", + "sha256": "306b80e0a72c0d16dd934b7d51ab0c9a4224f83be5d6cbad8a7158a0a5d73551", + "sha256_in_prefix": "306b80e0a72c0d16dd934b7d51ab0c9a4224f83be5d6cbad8a7158a0a5d73551", + "size_in_bytes": 476 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_map.py", + "path_type": "hardlink", + "sha256": "b82c0762c44adf2af7745c030afe291e2badfe360925046c8e58d85340717696", + "sha256_in_prefix": "b82c0762c44adf2af7745c030afe291e2badfe360925046c8e58d85340717696", + "size_in_bytes": 3640 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_metaclass.py", + "path_type": "hardlink", + "sha256": "45a30c866aa2ff69e089da147ed09986aad4516b5e5dd943f8dfcb7d3946a3e1", + "sha256_in_prefix": "45a30c866aa2ff69e089da147ed09986aad4516b5e5dd943f8dfcb7d3946a3e1", + "size_in_bytes": 8197 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_methodattrs.py", + "path_type": "hardlink", + "sha256": "8d60082f98ce52ee4955099bfd447cbadfa0e9b24ccb8d135cecc833168d44e8", + "sha256_in_prefix": "8d60082f98ce52ee4955099bfd447cbadfa0e9b24ccb8d135cecc833168d44e8", + "size_in_bytes": 606 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_ne.py", + "path_type": "hardlink", + "sha256": "4f9cb1388ba86f29422d20979d3423fdf3541ba35a17ed44d6f4a517ff784ecd", + "sha256_in_prefix": "4f9cb1388ba86f29422d20979d3423fdf3541ba35a17ed44d6f4a517ff784ecd", + "size_in_bytes": 571 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_next.py", + "path_type": "hardlink", + "sha256": "5c7d86d9f81b2498486d626c7feced1b92f23171cf9e42881abb78de1a93bccd", + "sha256_in_prefix": "5c7d86d9f81b2498486d626c7feced1b92f23171cf9e42881abb78de1a93bccd", + "size_in_bytes": 3174 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_nonzero.py", + "path_type": "hardlink", + "sha256": "c2cd7e3ba44508643a20eec4ea4c19f2f1adfd36f6b974d7c143e449571ae736", + "sha256_in_prefix": "c2cd7e3ba44508643a20eec4ea4c19f2f1adfd36f6b974d7c143e449571ae736", + "size_in_bytes": 591 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_numliterals.py", + "path_type": "hardlink", + "sha256": "1c4dd0f7881999abde6cf4d232836fa3e55fc41a7d5aa2b9866092f65707db7f", + "sha256_in_prefix": "1c4dd0f7881999abde6cf4d232836fa3e55fc41a7d5aa2b9866092f65707db7f", + "size_in_bytes": 768 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_operator.py", + "path_type": "hardlink", + "sha256": "023872fe9f03a25387cf2c17fc950cf0f990353df66e603c3a1cd3199dbccd86", + "sha256_in_prefix": "023872fe9f03a25387cf2c17fc950cf0f990353df66e603c3a1cd3199dbccd86", + "size_in_bytes": 3426 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_paren.py", + "path_type": "hardlink", + "sha256": "53734f1d7778ad28a4ec3ab4415923e2da8f230de4cd527589829f570e9f254d", + "sha256_in_prefix": "53734f1d7778ad28a4ec3ab4415923e2da8f230de4cd527589829f570e9f254d", + "size_in_bytes": 1226 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_print.py", + "path_type": "hardlink", + "sha256": "cf2690f1b502249289f52cd544190db0b94d59df5eca139829cd2bf0742e9dba", + "sha256_in_prefix": "cf2690f1b502249289f52cd544190db0b94d59df5eca139829cd2bf0742e9dba", + "size_in_bytes": 2844 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_raise.py", + "path_type": "hardlink", + "sha256": "c38ffec5862597ee8f9dac50385af943ee312bfc394366be08b2fc12563ca1a5", + "sha256_in_prefix": "c38ffec5862597ee8f9dac50385af943ee312bfc394366be08b2fc12563ca1a5", + "size_in_bytes": 2926 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_raw_input.py", + "path_type": "hardlink", + "sha256": "ce04cbaa76d414949afc230360dd9a29ff579bd868cc7f8805230d126ac9ce9b", + "sha256_in_prefix": "ce04cbaa76d414949afc230360dd9a29ff579bd868cc7f8805230d126ac9ce9b", + "size_in_bytes": 454 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_reduce.py", + "path_type": "hardlink", + "sha256": "9a03910a6c183586e1db01863fcde6417d06745fb3e63032333d71c5e82e7919", + "sha256_in_prefix": "9a03910a6c183586e1db01863fcde6417d06745fb3e63032333d71c5e82e7919", + "size_in_bytes": 837 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_reload.py", + "path_type": "hardlink", + "sha256": "17570148167e43b2155b6e1c814a3cca9e3ef53750c504932a9c7d62a8b68a3f", + "sha256_in_prefix": "17570148167e43b2155b6e1c814a3cca9e3ef53750c504932a9c7d62a8b68a3f", + "size_in_bytes": 1081 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_renames.py", + "path_type": "hardlink", + "sha256": "8b71472317bf3adabf819e665c725d03e3064baa45f6ffbfd78cca83eaa46e8d", + "sha256_in_prefix": "8b71472317bf3adabf819e665c725d03e3064baa45f6ffbfd78cca83eaa46e8d", + "size_in_bytes": 2221 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_repr.py", + "path_type": "hardlink", + "sha256": "d16930b7ef8577747cfef602aba854c64ce85d4ae1e54a18a456eaa202643e3d", + "sha256_in_prefix": "d16930b7ef8577747cfef602aba854c64ce85d4ae1e54a18a456eaa202643e3d", + "size_in_bytes": 613 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_set_literal.py", + "path_type": "hardlink", + "sha256": "33f2c0b6e16357e083c3a98877e7317abe1578a44c288e5979c9d96fb5aa6727", + "sha256_in_prefix": "33f2c0b6e16357e083c3a98877e7317abe1578a44c288e5979c9d96fb5aa6727", + "size_in_bytes": 1697 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_standarderror.py", + "path_type": "hardlink", + "sha256": "ce7eb37bc7fb29aa138b1cec6656ae8b4886cbfa700e119a1bb8484284cb717a", + "sha256_in_prefix": "ce7eb37bc7fb29aa138b1cec6656ae8b4886cbfa700e119a1bb8484284cb717a", + "size_in_bytes": 449 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_sys_exc.py", + "path_type": "hardlink", + "sha256": "0143830586d09d702ca3eeaa8f86698e5fd18af69fd28147e71a1a77600d356a", + "sha256_in_prefix": "0143830586d09d702ca3eeaa8f86698e5fd18af69fd28147e71a1a77600d356a", + "size_in_bytes": 1034 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_throw.py", + "path_type": "hardlink", + "sha256": "fec731ed523d5cdfa21893833b52b2844eabfd1549792c1c9f8ceac2d0e8e901", + "sha256_in_prefix": "fec731ed523d5cdfa21893833b52b2844eabfd1549792c1c9f8ceac2d0e8e901", + "size_in_bytes": 1582 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_tuple_params.py", + "path_type": "hardlink", + "sha256": "f3307d4750d0657d9c42b857d5f37bdb5824f9358939da7d16d13f61eb8abc72", + "sha256_in_prefix": "f3307d4750d0657d9c42b857d5f37bdb5824f9358939da7d16d13f61eb8abc72", + "size_in_bytes": 5565 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_types.py", + "path_type": "hardlink", + "sha256": "a0a133cfc78e82e1f71ce628408e7d10a38552ba3e3228ebd113838c1ce44484", + "sha256_in_prefix": "a0a133cfc78e82e1f71ce628408e7d10a38552ba3e3228ebd113838c1ce44484", + "size_in_bytes": 1774 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_unicode.py", + "path_type": "hardlink", + "sha256": "01b2a9b1084b6a0424f27eec488c761f75f053a409608ec36a9ee0ede0d38097", + "sha256_in_prefix": "01b2a9b1084b6a0424f27eec488c761f75f053a409608ec36a9ee0ede0d38097", + "size_in_bytes": 1256 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_urllib.py", + "path_type": "hardlink", + "sha256": "3d1c04d976ff4d2841025a785aaab0cc4ee06c9c9b4e09d1e2456949fa273856", + "sha256_in_prefix": "3d1c04d976ff4d2841025a785aaab0cc4ee06c9c9b4e09d1e2456949fa273856", + "size_in_bytes": 8367 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_ws_comma.py", + "path_type": "hardlink", + "sha256": "5e7a16daec0b2619110516804bf90cac459a4d0315198fd4eff69c36c54378dd", + "sha256_in_prefix": "5e7a16daec0b2619110516804bf90cac459a4d0315198fd4eff69c36c54378dd", + "size_in_bytes": 1090 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_xrange.py", + "path_type": "hardlink", + "sha256": "60d8ce92db6f399606d2e40a3c631ba566127e8cd637ebbf35b822672139cab2", + "sha256_in_prefix": "60d8ce92db6f399606d2e40a3c631ba566127e8cd637ebbf35b822672139cab2", + "size_in_bytes": 2694 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_xreadlines.py", + "path_type": "hardlink", + "sha256": "e8c2f19f7047bfc7539fd78839929004d8fe0efba1fbcbd9d712d285e43834ba", + "sha256_in_prefix": "e8c2f19f7047bfc7539fd78839929004d8fe0efba1fbcbd9d712d285e43834ba", + "size_in_bytes": 689 + }, + { + "_path": "lib/python3.12/lib2to3/fixes/fix_zip.py", + "path_type": "hardlink", + "sha256": "55ce115556c7513dd967364dc6a40c39210c874e8168cf090ddd6dc606df34cb", + "sha256_in_prefix": "55ce115556c7513dd967364dc6a40c39210c874e8168cf090ddd6dc606df34cb", + "size_in_bytes": 1289 + }, + { + "_path": "lib/python3.12/lib2to3/main.py", + "path_type": "hardlink", + "sha256": "8f5dfa77b8c8b375daba8bb88aaa195395674311e2513b29575a70821e3aa0b8", + "sha256_in_prefix": "8f5dfa77b8c8b375daba8bb88aaa195395674311e2513b29575a70821e3aa0b8", + "size_in_bytes": 11854 + }, + { + "_path": "lib/python3.12/lib2to3/patcomp.py", + "path_type": "hardlink", + "sha256": "a033a3eb91a39f96747d4300aa3394965e529c71896cd6503dd27e6b685eede5", + "sha256_in_prefix": "a033a3eb91a39f96747d4300aa3394965e529c71896cd6503dd27e6b685eede5", + "size_in_bytes": 7054 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__init__.py", + "path_type": "hardlink", + "sha256": "858eb0f50533bd3bd16fe32815f77fabfed92ede885070b6cb15827ec66ea500", + "sha256_in_prefix": "858eb0f50533bd3bd16fe32815f77fabfed92ede885070b6cb15827ec66ea500", + "size_in_bytes": 143 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5b1244e4c93867dcabffe21f7894e8fc04445b28b447b286ee4763b7b41baacc", + "sha256_in_prefix": "5b1244e4c93867dcabffe21f7894e8fc04445b28b447b286ee4763b7b41baacc", + "size_in_bytes": 172 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/conv.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "dcac58336a6ca54fcc153832e4e336fd5e8916b99ef35f2dbffa138ba9a4d9f9", + "sha256_in_prefix": "dcac58336a6ca54fcc153832e4e336fd5e8916b99ef35f2dbffa138ba9a4d9f9", + "size_in_bytes": 11792 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/driver.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3fde08e4f657ec864048bcdd35b27e488c4ce1d708a3df66680043307f2bff9f", + "sha256_in_prefix": "3fde08e4f657ec864048bcdd35b27e488c4ce1d708a3df66680043307f2bff9f", + "size_in_bytes": 8112 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/grammar.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ba532903fdf679c7ef67bf3b9b46801600ee7a00742353860791d2f047472406", + "sha256_in_prefix": "ba532903fdf679c7ef67bf3b9b46801600ee7a00742353860791d2f047472406", + "size_in_bytes": 7029 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/literals.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a3e99d9327a4c4ec1aea0af4ee5f0dd7d2f98a1027b331bd666375e8c4e7b4c3", + "sha256_in_prefix": "a3e99d9327a4c4ec1aea0af4ee5f0dd7d2f98a1027b331bd666375e8c4e7b4c3", + "size_in_bytes": 2591 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/parse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9ae7f8c3be1db61a42197813c0119bb60ae876f5848ffd9219bf6615e0c3862a", + "sha256_in_prefix": "9ae7f8c3be1db61a42197813c0119bb60ae876f5848ffd9219bf6615e0c3862a", + "size_in_bytes": 8726 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/pgen.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "31377b0126094e2b8055b01831a46854cb5109425542418e360f5daebc4d0dd8", + "sha256_in_prefix": "31377b0126094e2b8055b01831a46854cb5109425542418e360f5daebc4d0dd8", + "size_in_bytes": 18829 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/token.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c2c1dec2a7bda5e90df695beaa42ad137b4e65256725b4680a1449343ceac3c1", + "sha256_in_prefix": "c2c1dec2a7bda5e90df695beaa42ad137b4e65256725b4680a1449343ceac3c1", + "size_in_bytes": 2242 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/__pycache__/tokenize.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4453f41b2b7b9c523530190945ce5ae3eab3e777eadb96eb8e4b920055ca42a7", + "sha256_in_prefix": "4453f41b2b7b9c523530190945ce5ae3eab3e777eadb96eb8e4b920055ca42a7", + "size_in_bytes": 20929 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/conv.py", + "path_type": "hardlink", + "sha256": "e2946a686c12e02248fafb1a57e7514e0c22bdb2b4a66e644215c86fedc37bff", + "sha256_in_prefix": "e2946a686c12e02248fafb1a57e7514e0c22bdb2b4a66e644215c86fedc37bff", + "size_in_bytes": 9642 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/driver.py", + "path_type": "hardlink", + "sha256": "57af5e220cd6c6b75e8dead2cea395ead2297dd98e398ad705ca2bce0e9e6594", + "sha256_in_prefix": "57af5e220cd6c6b75e8dead2cea395ead2297dd98e398ad705ca2bce0e9e6594", + "size_in_bytes": 5969 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/grammar.py", + "path_type": "hardlink", + "sha256": "4898d446d6ae73f7259a3f91839eca1a3380670a9f378b80780707f714fad17c", + "sha256_in_prefix": "4898d446d6ae73f7259a3f91839eca1a3380670a9f378b80780707f714fad17c", + "size_in_bytes": 5552 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/literals.py", + "path_type": "hardlink", + "sha256": "84bc9d5387a2e20fab844e530358571afa39fa3fc0e8024270b5f7d8ac5a595a", + "sha256_in_prefix": "84bc9d5387a2e20fab844e530358571afa39fa3fc0e8024270b5f7d8ac5a595a", + "size_in_bytes": 1635 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/parse.py", + "path_type": "hardlink", + "sha256": "e245e005e524ab445a570df31f70c6fd7b901ee3b0b68bd3bcf4b41b37fa7bb6", + "sha256_in_prefix": "e245e005e524ab445a570df31f70c6fd7b901ee3b0b68bd3bcf4b41b37fa7bb6", + "size_in_bytes": 8155 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/pgen.py", + "path_type": "hardlink", + "sha256": "8fe2ac7e0303f0110d75832d746e6661fcd5373fa498d929163f557fd1027434", + "sha256_in_prefix": "8fe2ac7e0303f0110d75832d746e6661fcd5373fa498d929163f557fd1027434", + "size_in_bytes": 13830 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/token.py", + "path_type": "hardlink", + "sha256": "7ee05616410d46d8caed0cb0755bf780c62cccf17e3c93c8ccb8dcaaa1e7094c", + "sha256_in_prefix": "7ee05616410d46d8caed0cb0755bf780c62cccf17e3c93c8ccb8dcaaa1e7094c", + "size_in_bytes": 1302 + }, + { + "_path": "lib/python3.12/lib2to3/pgen2/tokenize.py", + "path_type": "hardlink", + "sha256": "aaa0b98f6a65e08e9f8e34358198e329d29554a0d4b5f5059924a252eeb0f5c4", + "sha256_in_prefix": "aaa0b98f6a65e08e9f8e34358198e329d29554a0d4b5f5059924a252eeb0f5c4", + "size_in_bytes": 21119 + }, + { + "_path": "lib/python3.12/lib2to3/pygram.py", + "path_type": "hardlink", + "sha256": "b49d77876a9d1822ff6be04daf464341a8e4c0c3414240abf519254de2a97a48", + "sha256_in_prefix": "b49d77876a9d1822ff6be04daf464341a8e4c0c3414240abf519254de2a97a48", + "size_in_bytes": 1305 + }, + { + "_path": "lib/python3.12/lib2to3/pytree.py", + "path_type": "hardlink", + "sha256": "e53689352fb4fc83d85a09369650389ee01db802ad872a8abfc0bf6603ec38b9", + "sha256_in_prefix": "e53689352fb4fc83d85a09369650389ee01db802ad872a8abfc0bf6603ec38b9", + "size_in_bytes": 27974 + }, + { + "_path": "lib/python3.12/lib2to3/refactor.py", + "path_type": "hardlink", + "sha256": "6e9a4262fb65cd4d277f009df73ffa5748f5fe3b963d3c5395c160d5f88b089b", + "sha256_in_prefix": "6e9a4262fb65cd4d277f009df73ffa5748f5fe3b963d3c5395c160d5f88b089b", + "size_in_bytes": 27507 + }, + { + "_path": "lib/python3.12/linecache.py", + "path_type": "hardlink", + "sha256": "c985113d9219c02950916e75090158bccf44cacac09014741b1c59b07968d111", + "sha256_in_prefix": "c985113d9219c02950916e75090158bccf44cacac09014741b1c59b07968d111", + "size_in_bytes": 5649 + }, + { + "_path": "lib/python3.12/locale.py", + "path_type": "hardlink", + "sha256": "5caa43b5ca0d60fd8a6c0bf7e9b8c8a23e86c58e49f1f8b4398f0d2fdf237b6e", + "sha256_in_prefix": "5caa43b5ca0d60fd8a6c0bf7e9b8c8a23e86c58e49f1f8b4398f0d2fdf237b6e", + "size_in_bytes": 78558 + }, + { + "_path": "lib/python3.12/logging/__init__.py", + "path_type": "hardlink", + "sha256": "43f86bbc08fdd5c7b6e697abffe1381f534a92bb32e1f1aee8360d6a142592a1", + "sha256_in_prefix": "43f86bbc08fdd5c7b6e697abffe1381f534a92bb32e1f1aee8360d6a142592a1", + "size_in_bytes": 83437 + }, + { + "_path": "lib/python3.12/logging/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0c6868c6a8721bfddc2184d9cab4c74b145e658171866be944ec94444b219e19", + "sha256_in_prefix": "0c6868c6a8721bfddc2184d9cab4c74b145e658171866be944ec94444b219e19", + "size_in_bytes": 95458 + }, + { + "_path": "lib/python3.12/logging/__pycache__/config.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "aedd91e4131fdb55f627152c4192b0d8104018ef3b55689acce9ffce3623660b", + "sha256_in_prefix": "aedd91e4131fdb55f627152c4192b0d8104018ef3b55689acce9ffce3623660b", + "size_in_bytes": 43055 + }, + { + "_path": "lib/python3.12/logging/__pycache__/handlers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "14833ebc6799e87b2c167a6a66b339187b48f075e6c9a6126412b181503cd3e5", + "sha256_in_prefix": "14833ebc6799e87b2c167a6a66b339187b48f075e6c9a6126412b181503cd3e5", + "size_in_bytes": 66790 + }, + { + "_path": "lib/python3.12/logging/config.py", + "path_type": "hardlink", + "sha256": "4f39b6fab0d83992524c1e8fa5e96251cc7a22f490e4e60b15c732740bf741ae", + "sha256_in_prefix": "4f39b6fab0d83992524c1e8fa5e96251cc7a22f490e4e60b15c732740bf741ae", + "size_in_bytes": 41526 + }, + { + "_path": "lib/python3.12/logging/handlers.py", + "path_type": "hardlink", + "sha256": "9bee4f9ee58c3a8858ef8a5f5ba597600667eddaa404e2653dfd1079b219e6bc", + "sha256_in_prefix": "9bee4f9ee58c3a8858ef8a5f5ba597600667eddaa404e2653dfd1079b219e6bc", + "size_in_bytes": 62007 + }, + { + "_path": "lib/python3.12/lzma.py", + "path_type": "hardlink", + "sha256": "58fb9d2fdc8a8af7b25e218f17ea3b51bdfa53bdf40f440ab33c605974ca5c2e", + "sha256_in_prefix": "58fb9d2fdc8a8af7b25e218f17ea3b51bdfa53bdf40f440ab33c605974ca5c2e", + "size_in_bytes": 13277 + }, + { + "_path": "lib/python3.12/mailbox.py", + "path_type": "hardlink", + "sha256": "1c356f03e8df0b99d9d40a08ac7f3f5f71e9626c3ee1149cbed7307968ba0a4f", + "sha256_in_prefix": "1c356f03e8df0b99d9d40a08ac7f3f5f71e9626c3ee1149cbed7307968ba0a4f", + "size_in_bytes": 78911 + }, + { + "_path": "lib/python3.12/mailcap.py", + "path_type": "hardlink", + "sha256": "d3242c92bfedb13c7cf5e7aa116e9a38c07e9c6de58f53d03f72a469e9448ca6", + "sha256_in_prefix": "d3242c92bfedb13c7cf5e7aa116e9a38c07e9c6de58f53d03f72a469e9448ca6", + "size_in_bytes": 9333 + }, + { + "_path": "lib/python3.12/mimetypes.py", + "path_type": "hardlink", + "sha256": "63e4e00b6004bfe60fcca6ab1cce7a90b6e676cf049d1f33445d2720790d8e06", + "sha256_in_prefix": "63e4e00b6004bfe60fcca6ab1cce7a90b6e676cf049d1f33445d2720790d8e06", + "size_in_bytes": 22888 + }, + { + "_path": "lib/python3.12/modulefinder.py", + "path_type": "hardlink", + "sha256": "e07ab000c3698a7530af2c52955ac8bb7647140d22dca1c30f83443faa191e0f", + "sha256_in_prefix": "e07ab000c3698a7530af2c52955ac8bb7647140d22dca1c30f83443faa191e0f", + "size_in_bytes": 23699 + }, + { + "_path": "lib/python3.12/multiprocessing/__init__.py", + "path_type": "hardlink", + "sha256": "a5a42976033c7d63ee2740acceef949a3582dcb0e0442845f9717e1be771c68b", + "sha256_in_prefix": "a5a42976033c7d63ee2740acceef949a3582dcb0e0442845f9717e1be771c68b", + "size_in_bytes": 916 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d5552dea348d03f544ee0406b87bd6aeb797f4423f848e5d095199319cfba92e", + "sha256_in_prefix": "d5552dea348d03f544ee0406b87bd6aeb797f4423f848e5d095199319cfba92e", + "size_in_bytes": 949 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/connection.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4cb76af9e829c3c2a3f755cdc31afe0badf321b7a2d3ab7b54146c928e352f71", + "sha256_in_prefix": "4cb76af9e829c3c2a3f755cdc31afe0badf321b7a2d3ab7b54146c928e352f71", + "size_in_bytes": 48161 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/context.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ced2081e7cd0f6af1482023795cf001d00b697550b0d092a4ffba64b59a4e13e", + "sha256_in_prefix": "ced2081e7cd0f6af1482023795cf001d00b697550b0d092a4ffba64b59a4e13e", + "size_in_bytes": 17022 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/forkserver.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c4dbd740487f66d28c5b3b18cda6046537b3ab40a006b3780dc448dd44efc85f", + "sha256_in_prefix": "c4dbd740487f66d28c5b3b18cda6046537b3ab40a006b3780dc448dd44efc85f", + "size_in_bytes": 15155 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/heap.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bd4097368dffd8ba031439736d37f35ebaa90d57ad8e783683721f3f850ef905", + "sha256_in_prefix": "bd4097368dffd8ba031439736d37f35ebaa90d57ad8e783683721f3f850ef905", + "size_in_bytes": 13862 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/managers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "866aaa70f8226628c81471371ae8d55cd70064564fda2987dff59dbbab990c74", + "sha256_in_prefix": "866aaa70f8226628c81471371ae8d55cd70064564fda2987dff59dbbab990c74", + "size_in_bytes": 68022 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/pool.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "28667bb46f930755db7bcbda26cd9a7dc5943c6dcc31ab9d66c7ad3ce6c21a35", + "sha256_in_prefix": "28667bb46f930755db7bcbda26cd9a7dc5943c6dcc31ab9d66c7ad3ce6c21a35", + "size_in_bytes": 44035 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/popen_fork.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0e67dcd0c0757b131101a1a2b063f2ad0b067158d0bec2a603bded7b41058564", + "sha256_in_prefix": "0e67dcd0c0757b131101a1a2b063f2ad0b067158d0bec2a603bded7b41058564", + "size_in_bytes": 4099 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/popen_forkserver.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0ab64640de1f2c90180aab1f74e56281f033fcd76dbb0bd96df2cb3502e66153", + "sha256_in_prefix": "0ab64640de1f2c90180aab1f74e56281f033fcd76dbb0bd96df2cb3502e66153", + "size_in_bytes": 3959 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/popen_spawn_posix.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0622c8e8bf26ba7b956653332f490b91f27781485410ce4f8a289b32abb34cef", + "sha256_in_prefix": "0622c8e8bf26ba7b956653332f490b91f27781485410ce4f8a289b32abb34cef", + "size_in_bytes": 3940 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/popen_spawn_win32.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "42cbf604045a6b3408505a6b9eae980d2096a9e2463b172437dac5d5acce7789", + "sha256_in_prefix": "42cbf604045a6b3408505a6b9eae980d2096a9e2463b172437dac5d5acce7789", + "size_in_bytes": 6164 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/process.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f6145d8c8b2a72586fc4ea178a254498784cc7550595d9f9d25a875b77cd6f27", + "sha256_in_prefix": "f6145d8c8b2a72586fc4ea178a254498784cc7550595d9f9d25a875b77cd6f27", + "size_in_bytes": 17763 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/queues.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1b67e4888381a9bd0d18567c549bff1465784e362542c4341bd80c47f6b555a1", + "sha256_in_prefix": "1b67e4888381a9bd0d18567c549bff1465784e362542c4341bd80c47f6b555a1", + "size_in_bytes": 18515 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/reduction.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a8e5a63e83c9120b39680bffa5f204a92557faadd543f5a874029f8290fabd93", + "sha256_in_prefix": "a8e5a63e83c9120b39680bffa5f204a92557faadd543f5a874029f8290fabd93", + "size_in_bytes": 13894 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/resource_sharer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4ef1ee610456953d264b6bcb817ed461b55687c27208ad429df051ceaed26645", + "sha256_in_prefix": "4ef1ee610456953d264b6bcb817ed461b55687c27208ad429df051ceaed26645", + "size_in_bytes": 8903 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/resource_tracker.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "47630068b129b9e2d23eab814e9ce706bf964617a455535854f6df398b817c4d", + "sha256_in_prefix": "47630068b129b9e2d23eab814e9ce706bf964617a455535854f6df398b817c4d", + "size_in_bytes": 11149 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/shared_memory.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "34f7f74c88be4ab00cd5498b7655199c772d56068f5284b1f043307e76c59965", + "sha256_in_prefix": "34f7f74c88be4ab00cd5498b7655199c772d56068f5284b1f043307e76c59965", + "size_in_bytes": 23563 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/sharedctypes.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "080bc54fa8c218d590b99b5f526f0e35b89f49342fae79065ea88726642b0459", + "sha256_in_prefix": "080bc54fa8c218d590b99b5f526f0e35b89f49342fae79065ea88726642b0459", + "size_in_bytes": 10697 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/spawn.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "60316de6b7e9f763e83ca1972101de0ad6aaa73efa22b37fee4dcbf6eeafdf37", + "sha256_in_prefix": "60316de6b7e9f763e83ca1972101de0ad6aaa73efa22b37fee4dcbf6eeafdf37", + "size_in_bytes": 11670 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/synchronize.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3a11608e36821d5f0de9c358af1da25d997b78741cea708bea37fd72628a939a", + "sha256_in_prefix": "3a11608e36821d5f0de9c358af1da25d997b78741cea708bea37fd72628a939a", + "size_in_bytes": 20845 + }, + { + "_path": "lib/python3.12/multiprocessing/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c3c45d70f326f37b884ada12d42a4668cef2d477fa52dbe34bac89196fe387f9", + "sha256_in_prefix": "c3c45d70f326f37b884ada12d42a4668cef2d477fa52dbe34bac89196fe387f9", + "size_in_bytes": 18678 + }, + { + "_path": "lib/python3.12/multiprocessing/connection.py", + "path_type": "hardlink", + "sha256": "3b1591b340a6e8f68eab4af6a6ed158d51c9c35bb5b500827b677bf97e8afd51", + "sha256_in_prefix": "3b1591b340a6e8f68eab4af6a6ed158d51c9c35bb5b500827b677bf97e8afd51", + "size_in_bytes": 41382 + }, + { + "_path": "lib/python3.12/multiprocessing/context.py", + "path_type": "hardlink", + "sha256": "63f15d3169f4453eb80af4ce673a193a0670941206673ab5192ea16a17e8419f", + "sha256_in_prefix": "63f15d3169f4453eb80af4ce673a193a0670941206673ab5192ea16a17e8419f", + "size_in_bytes": 11673 + }, + { + "_path": "lib/python3.12/multiprocessing/dummy/__init__.py", + "path_type": "hardlink", + "sha256": "9127a40ea0ff342cb414383b5e7c594a05be2dd835fe246bd3bb0dc036a32a90", + "sha256_in_prefix": "9127a40ea0ff342cb414383b5e7c594a05be2dd835fe246bd3bb0dc036a32a90", + "size_in_bytes": 3061 + }, + { + "_path": "lib/python3.12/multiprocessing/dummy/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "51328a68e28f767815cf20e3a6826c5f088045be84b07666957d09af37cbbdbd", + "sha256_in_prefix": "51328a68e28f767815cf20e3a6826c5f088045be84b07666957d09af37cbbdbd", + "size_in_bytes": 5599 + }, + { + "_path": "lib/python3.12/multiprocessing/dummy/__pycache__/connection.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "73c3bd5fd6e19cebb4046385fff0955462287ae78354ff9232e7f3401ff7aebb", + "sha256_in_prefix": "73c3bd5fd6e19cebb4046385fff0955462287ae78354ff9232e7f3401ff7aebb", + "size_in_bytes": 3490 + }, + { + "_path": "lib/python3.12/multiprocessing/dummy/connection.py", + "path_type": "hardlink", + "sha256": "d63dd1979fde9c133efe430ee870e6ba6de43c0a0513866ce3ce475791fe57ab", + "sha256_in_prefix": "d63dd1979fde9c133efe430ee870e6ba6de43c0a0513866ce3ce475791fe57ab", + "size_in_bytes": 1598 + }, + { + "_path": "lib/python3.12/multiprocessing/forkserver.py", + "path_type": "hardlink", + "sha256": "e99f0aa2e4dc41af9d259f220c5eb2632e2ace89b6851e712223bf2682016f29", + "sha256_in_prefix": "e99f0aa2e4dc41af9d259f220c5eb2632e2ace89b6851e712223bf2682016f29", + "size_in_bytes": 12134 + }, + { + "_path": "lib/python3.12/multiprocessing/heap.py", + "path_type": "hardlink", + "sha256": "f6bb79bb99b9ae484935f0d68822e9603a1622dd0b6c4966c79db232a93ba614", + "sha256_in_prefix": "f6bb79bb99b9ae484935f0d68822e9603a1622dd0b6c4966c79db232a93ba614", + "size_in_bytes": 11626 + }, + { + "_path": "lib/python3.12/multiprocessing/managers.py", + "path_type": "hardlink", + "sha256": "7c5431f44b7f966ada442a8524e2df857e6319447001094e78fc4fb041a58f4e", + "sha256_in_prefix": "7c5431f44b7f966ada442a8524e2df857e6319447001094e78fc4fb041a58f4e", + "size_in_bytes": 47616 + }, + { + "_path": "lib/python3.12/multiprocessing/pool.py", + "path_type": "hardlink", + "sha256": "418cd41ea5c341e66c6979a38070f6f552cbbdf0539073022b6d15c67e53f480", + "sha256_in_prefix": "418cd41ea5c341e66c6979a38070f6f552cbbdf0539073022b6d15c67e53f480", + "size_in_bytes": 32760 + }, + { + "_path": "lib/python3.12/multiprocessing/popen_fork.py", + "path_type": "hardlink", + "sha256": "0a09db57e7fab7061c01a61778feea6e2b6bb02ccbc150332f2960b05258ef95", + "sha256_in_prefix": "0a09db57e7fab7061c01a61778feea6e2b6bb02ccbc150332f2960b05258ef95", + "size_in_bytes": 2377 + }, + { + "_path": "lib/python3.12/multiprocessing/popen_forkserver.py", + "path_type": "hardlink", + "sha256": "0588ad0e5a36718b4377dc2a2a97864a10986c25a33dc3bfed12595711b0cdab", + "sha256_in_prefix": "0588ad0e5a36718b4377dc2a2a97864a10986c25a33dc3bfed12595711b0cdab", + "size_in_bytes": 2230 + }, + { + "_path": "lib/python3.12/multiprocessing/popen_spawn_posix.py", + "path_type": "hardlink", + "sha256": "97b5d25aa479516894489877e6a7921252ee35f51e118c2f1f91f32919e7caa8", + "sha256_in_prefix": "97b5d25aa479516894489877e6a7921252ee35f51e118c2f1f91f32919e7caa8", + "size_in_bytes": 2029 + }, + { + "_path": "lib/python3.12/multiprocessing/popen_spawn_win32.py", + "path_type": "hardlink", + "sha256": "6ef8efd9cd4e99c64a6778f7ad0957e924de9eb4aa167337ed121a2621b1ffaa", + "sha256_in_prefix": "6ef8efd9cd4e99c64a6778f7ad0957e924de9eb4aa167337ed121a2621b1ffaa", + "size_in_bytes": 4515 + }, + { + "_path": "lib/python3.12/multiprocessing/process.py", + "path_type": "hardlink", + "sha256": "67f0c2a7a3a83c92dd024705bac18619a2e123c9df77c414beb81035ea4a0e18", + "sha256_in_prefix": "67f0c2a7a3a83c92dd024705bac18619a2e123c9df77c414beb81035ea4a0e18", + "size_in_bytes": 12139 + }, + { + "_path": "lib/python3.12/multiprocessing/queues.py", + "path_type": "hardlink", + "sha256": "f4721a323ab2981a172dd2b853d2cfeded696e9716fba340cf6e168f5ed95f83", + "sha256_in_prefix": "f4721a323ab2981a172dd2b853d2cfeded696e9716fba340cf6e168f5ed95f83", + "size_in_bytes": 12693 + }, + { + "_path": "lib/python3.12/multiprocessing/reduction.py", + "path_type": "hardlink", + "sha256": "4999f8b9ae7b3e8a7f5de302612b4131498dc2e238a2c47f894905c1c63294fe", + "sha256_in_prefix": "4999f8b9ae7b3e8a7f5de302612b4131498dc2e238a2c47f894905c1c63294fe", + "size_in_bytes": 9512 + }, + { + "_path": "lib/python3.12/multiprocessing/resource_sharer.py", + "path_type": "hardlink", + "sha256": "bba3c7f2b76a9cf4e8ceb642801c405411da95adf91947d81b0043586038290e", + "sha256_in_prefix": "bba3c7f2b76a9cf4e8ceb642801c405411da95adf91947d81b0043586038290e", + "size_in_bytes": 5145 + }, + { + "_path": "lib/python3.12/multiprocessing/resource_tracker.py", + "path_type": "hardlink", + "sha256": "b0099f5e2285fe2462b77c47bbf29220b57c778741a34f386c10c1e9940884c8", + "sha256_in_prefix": "b0099f5e2285fe2462b77c47bbf29220b57c778741a34f386c10c1e9940884c8", + "size_in_bytes": 10332 + }, + { + "_path": "lib/python3.12/multiprocessing/shared_memory.py", + "path_type": "hardlink", + "sha256": "51301e70710220e1c494ff5383ac94442a38a4a6622f2eb94e40128c45de1aeb", + "sha256_in_prefix": "51301e70710220e1c494ff5383ac94442a38a4a6622f2eb94e40128c45de1aeb", + "size_in_bytes": 18458 + }, + { + "_path": "lib/python3.12/multiprocessing/sharedctypes.py", + "path_type": "hardlink", + "sha256": "77ef522912474652490b7df523112858e51721e63dcf109b8567a35ce9b31b0d", + "sha256_in_prefix": "77ef522912474652490b7df523112858e51721e63dcf109b8567a35ce9b31b0d", + "size_in_bytes": 6306 + }, + { + "_path": "lib/python3.12/multiprocessing/spawn.py", + "path_type": "hardlink", + "sha256": "ebf9fa40eb622384c37690d8c78e7208744df031155ab4ceedab0fc791a1669b", + "sha256_in_prefix": "ebf9fa40eb622384c37690d8c78e7208744df031155ab4ceedab0fc791a1669b", + "size_in_bytes": 9644 + }, + { + "_path": "lib/python3.12/multiprocessing/synchronize.py", + "path_type": "hardlink", + "sha256": "9afc08f6d99deb0cefcbe2f0302dadf3942114aa5564afa0b41bc69f54d1ecaf", + "sha256_in_prefix": "9afc08f6d99deb0cefcbe2f0302dadf3942114aa5564afa0b41bc69f54d1ecaf", + "size_in_bytes": 12285 + }, + { + "_path": "lib/python3.12/multiprocessing/util.py", + "path_type": "hardlink", + "sha256": "6752c4515ec69f82e9df64e017da490c3754e51d818c270ea1ad2d64e09268be", + "sha256_in_prefix": "6752c4515ec69f82e9df64e017da490c3754e51d818c270ea1ad2d64e09268be", + "size_in_bytes": 14261 + }, + { + "_path": "lib/python3.12/netrc.py", + "path_type": "hardlink", + "sha256": "229da6d0cbe6a10295be6c64ac3806420ea018124c09e4887410548fc2fc8b5d", + "sha256_in_prefix": "229da6d0cbe6a10295be6c64ac3806420ea018124c09e4887410548fc2fc8b5d", + "size_in_bytes": 6922 + }, + { + "_path": "lib/python3.12/nntplib.py", + "path_type": "hardlink", + "sha256": "6a76a94b951b273aa87335d7c9c4d7273e4c59485c784b057f681443b32d9004", + "sha256_in_prefix": "6a76a94b951b273aa87335d7c9c4d7273e4c59485c784b057f681443b32d9004", + "size_in_bytes": 41087 + }, + { + "_path": "lib/python3.12/ntpath.py", + "path_type": "hardlink", + "sha256": "0ba5b71169c209deaf39bb3c6f043f65586c931424236ed10cfe9b932b1e6197", + "sha256_in_prefix": "0ba5b71169c209deaf39bb3c6f043f65586c931424236ed10cfe9b932b1e6197", + "size_in_bytes": 31483 + }, + { + "_path": "lib/python3.12/nturl2path.py", + "path_type": "hardlink", + "sha256": "980982ba66cc403d17874369d2770e09845b3d49f1d4514e1c52e01518114332", + "sha256_in_prefix": "980982ba66cc403d17874369d2770e09845b3d49f1d4514e1c52e01518114332", + "size_in_bytes": 2887 + }, + { + "_path": "lib/python3.12/numbers.py", + "path_type": "hardlink", + "sha256": "ac381960a3dc1db0498b0bd43d8ef278d6599713121a186b153ff09d9552e0db", + "sha256_in_prefix": "ac381960a3dc1db0498b0bd43d8ef278d6599713121a186b153ff09d9552e0db", + "size_in_bytes": 11467 + }, + { + "_path": "lib/python3.12/opcode.py", + "path_type": "hardlink", + "sha256": "192f6008508f28d3273bff42eaea9b01c8394dab1607cd36aea778bdd166c3a6", + "sha256_in_prefix": "192f6008508f28d3273bff42eaea9b01c8394dab1607cd36aea778bdd166c3a6", + "size_in_bytes": 13174 + }, + { + "_path": "lib/python3.12/operator.py", + "path_type": "hardlink", + "sha256": "b2af20f67667203c1730e686cc5d0427becc94db4c97f1d3efe3ed2158473f6a", + "sha256_in_prefix": "b2af20f67667203c1730e686cc5d0427becc94db4c97f1d3efe3ed2158473f6a", + "size_in_bytes": 10965 + }, + { + "_path": "lib/python3.12/optparse.py", + "path_type": "hardlink", + "sha256": "07d224301cba312fa0697bff9cd5a4bb4f778a90629632091b3f4ae874d89af5", + "sha256_in_prefix": "07d224301cba312fa0697bff9cd5a4bb4f778a90629632091b3f4ae874d89af5", + "size_in_bytes": 60369 + }, + { + "_path": "lib/python3.12/os.py", + "path_type": "hardlink", + "sha256": "316d1b7307fd851bded3423c9d437e0a383c725d993f0fcff2e8b749fe560b62", + "sha256_in_prefix": "316d1b7307fd851bded3423c9d437e0a383c725d993f0fcff2e8b749fe560b62", + "size_in_bytes": 39786 + }, + { + "_path": "lib/python3.12/pathlib.py", + "path_type": "hardlink", + "sha256": "dc14d8207519fb8bcdd9c7bae1d54da3ad1b339aa83d4979c16057cd552a3487", + "sha256_in_prefix": "dc14d8207519fb8bcdd9c7bae1d54da3ad1b339aa83d4979c16057cd552a3487", + "size_in_bytes": 51105 + }, + { + "_path": "lib/python3.12/pdb.py", + "path_type": "hardlink", + "sha256": "c689d3d31be642cd4016022d833512b569eceb743117991b463091adbe2d1870", + "sha256_in_prefix": "c689d3d31be642cd4016022d833512b569eceb743117991b463091adbe2d1870", + "size_in_bytes": 69460 + }, + { + "_path": "lib/python3.12/pickle.py", + "path_type": "hardlink", + "sha256": "865b5788a1e35433f89d047187a514057e15ddc2a301b06b5f85da62b4259c04", + "sha256_in_prefix": "865b5788a1e35433f89d047187a514057e15ddc2a301b06b5f85da62b4259c04", + "size_in_bytes": 64901 + }, + { + "_path": "lib/python3.12/pickletools.py", + "path_type": "hardlink", + "sha256": "1d43b5d94c640f5fc7569a0cda0ecb3b08e97cc1ba9c1907ba72bac610903a3e", + "sha256_in_prefix": "1d43b5d94c640f5fc7569a0cda0ecb3b08e97cc1ba9c1907ba72bac610903a3e", + "size_in_bytes": 93861 + }, + { + "_path": "lib/python3.12/pipes.py", + "path_type": "hardlink", + "sha256": "153f2d249d954b5536c6a049202617ff43ba2f9b109c426e06676c577ddedc61", + "sha256_in_prefix": "153f2d249d954b5536c6a049202617ff43ba2f9b109c426e06676c577ddedc61", + "size_in_bytes": 8978 + }, + { + "_path": "lib/python3.12/pkgutil.py", + "path_type": "hardlink", + "sha256": "44300bc77f6f52ef2ad74d26e5053309c04f49eaa91c099356eb61426cde504f", + "sha256_in_prefix": "44300bc77f6f52ef2ad74d26e5053309c04f49eaa91c099356eb61426cde504f", + "size_in_bytes": 18281 + }, + { + "_path": "lib/python3.12/platform.py", + "path_type": "hardlink", + "sha256": "dbfb80dd05e351a45456b40d272c869bb9e8f6c4d7ef22fda738755318f147ca", + "sha256_in_prefix": "dbfb80dd05e351a45456b40d272c869bb9e8f6c4d7ef22fda738755318f147ca", + "size_in_bytes": 43516 + }, + { + "_path": "lib/python3.12/plistlib.py", + "path_type": "hardlink", + "sha256": "502ea7953e190f0bb03c6acec41c6ab54eb51bbdbd9d8e1c41e53a2d2191aebf", + "sha256_in_prefix": "502ea7953e190f0bb03c6acec41c6ab54eb51bbdbd9d8e1c41e53a2d2191aebf", + "size_in_bytes": 28342 + }, + { + "_path": "lib/python3.12/poplib.py", + "path_type": "hardlink", + "sha256": "08609dc8298e62bf9232de174f5ae4307f27ebef490bf7996625f88d837f08ad", + "sha256_in_prefix": "08609dc8298e62bf9232de174f5ae4307f27ebef490bf7996625f88d837f08ad", + "size_in_bytes": 14163 + }, + { + "_path": "lib/python3.12/posixpath.py", + "path_type": "hardlink", + "sha256": "8396232224e1b9df7896a32980046825b64c00bb010ddd2a4ccc23fe4fbfe262", + "sha256_in_prefix": "8396232224e1b9df7896a32980046825b64c00bb010ddd2a4ccc23fe4fbfe262", + "size_in_bytes": 17564 + }, + { + "_path": "lib/python3.12/pprint.py", + "path_type": "hardlink", + "sha256": "1585c8d74d7f485590db2af46680ae0a73737ca9fb66022b2bcbbc4c4925e203", + "sha256_in_prefix": "1585c8d74d7f485590db2af46680ae0a73737ca9fb66022b2bcbbc4c4925e203", + "size_in_bytes": 24158 + }, + { + "_path": "lib/python3.12/profile.py", + "path_type": "hardlink", + "sha256": "dee2125b2a0913fcfd0330b75d7fb752f2dbbe1bf43e479fb0cba117b9ae6e17", + "sha256_in_prefix": "dee2125b2a0913fcfd0330b75d7fb752f2dbbe1bf43e479fb0cba117b9ae6e17", + "size_in_bytes": 23093 + }, + { + "_path": "lib/python3.12/pstats.py", + "path_type": "hardlink", + "sha256": "3e89c57f1e9d2501abf2e49701cf7d7f1e9525b1b88aeacdfb1c4cc530f4168e", + "sha256_in_prefix": "3e89c57f1e9d2501abf2e49701cf7d7f1e9525b1b88aeacdfb1c4cc530f4168e", + "size_in_bytes": 29289 + }, + { + "_path": "lib/python3.12/pty.py", + "path_type": "hardlink", + "sha256": "ddbb1749387539c2929957c7ec1235fd201d7ec15d285fe5246e88b35c722a4a", + "sha256_in_prefix": "ddbb1749387539c2929957c7ec1235fd201d7ec15d285fe5246e88b35c722a4a", + "size_in_bytes": 6137 + }, + { + "_path": "lib/python3.12/py_compile.py", + "path_type": "hardlink", + "sha256": "3464f04938b57a7aafbc5c394ccd4c46823ee607f7fe36b48b91ecbc30ff4e48", + "sha256_in_prefix": "3464f04938b57a7aafbc5c394ccd4c46823ee607f7fe36b48b91ecbc30ff4e48", + "size_in_bytes": 7837 + }, + { + "_path": "lib/python3.12/pyclbr.py", + "path_type": "hardlink", + "sha256": "e8ca09333701ba41244e20b8c2c37b7ed0499b88c4b2ca82cac51ef89ca9e647", + "sha256_in_prefix": "e8ca09333701ba41244e20b8c2c37b7ed0499b88c4b2ca82cac51ef89ca9e647", + "size_in_bytes": 11396 + }, + { + "_path": "lib/python3.12/pydoc.py", + "path_type": "hardlink", + "sha256": "1dd1cc5a13b4f86a587c3c43dbea548413e31151d2319b62e6b434b4fe109f82", + "sha256_in_prefix": "1dd1cc5a13b4f86a587c3c43dbea548413e31151d2319b62e6b434b4fe109f82", + "size_in_bytes": 112795 + }, + { + "_path": "lib/python3.12/pydoc_data/__init__.py", + "path_type": "hardlink", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "sha256_in_prefix": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "size_in_bytes": 0 + }, + { + "_path": "lib/python3.12/pydoc_data/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "79f4de7fd3b3fcff566d6290516e74428feb61e3b84363ed174d309c76cb71c7", + "sha256_in_prefix": "79f4de7fd3b3fcff566d6290516e74428feb61e3b84363ed174d309c76cb71c7", + "size_in_bytes": 134 + }, + { + "_path": "lib/python3.12/pydoc_data/__pycache__/topics.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bce870f92300977e9b6612ba85ef8bc5721e92d02dc3256ace00a7cdf9a14e0e", + "sha256_in_prefix": "bce870f92300977e9b6612ba85ef8bc5721e92d02dc3256ace00a7cdf9a14e0e", + "size_in_bytes": 502301 + }, + { + "_path": "lib/python3.12/pydoc_data/_pydoc.css", + "path_type": "hardlink", + "sha256": "038d4bf51b4d373284640f3658d70eaa856def24d8d02b8e29b289beaabf1cc9", + "sha256_in_prefix": "038d4bf51b4d373284640f3658d70eaa856def24d8d02b8e29b289beaabf1cc9", + "size_in_bytes": 1325 + }, + { + "_path": "lib/python3.12/pydoc_data/topics.py", + "path_type": "hardlink", + "sha256": "56f235c690ef8b5b2497884aac3ee1128332532c25bd387dfee750e83432dfa7", + "sha256_in_prefix": "56f235c690ef8b5b2497884aac3ee1128332532c25bd387dfee750e83432dfa7", + "size_in_bytes": 805508 + }, + { + "_path": "lib/python3.12/queue.py", + "path_type": "hardlink", + "sha256": "f6c37fc37cd7440979f7d22d40ee818fa3b714c573610c08fa52911d541193f0", + "sha256_in_prefix": "f6c37fc37cd7440979f7d22d40ee818fa3b714c573610c08fa52911d541193f0", + "size_in_bytes": 11496 + }, + { + "_path": "lib/python3.12/quopri.py", + "path_type": "hardlink", + "sha256": "a1cd7f3b22033d32151209886cc855d4b71cc4c83530769f920097582339013a", + "sha256_in_prefix": "a1cd7f3b22033d32151209886cc855d4b71cc4c83530769f920097582339013a", + "size_in_bytes": 7184 + }, + { + "_path": "lib/python3.12/random.py", + "path_type": "hardlink", + "sha256": "0693d4ded36916f5b07d6c395cc331dbf1011bb70e90daaa29eaa32490a09425", + "sha256_in_prefix": "0693d4ded36916f5b07d6c395cc331dbf1011bb70e90daaa29eaa32490a09425", + "size_in_bytes": 34683 + }, + { + "_path": "lib/python3.12/re/__init__.py", + "path_type": "hardlink", + "sha256": "8ff3c37c63b917fcf8dc8d50993a502292a3dc159e41de4f4018c72a53d1c07b", + "sha256_in_prefix": "8ff3c37c63b917fcf8dc8d50993a502292a3dc159e41de4f4018c72a53d1c07b", + "size_in_bytes": 16315 + }, + { + "_path": "lib/python3.12/re/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e69977f53f4689c19d2f9fc63a38d84c08f21be3d7a86c65810746dd72e5ef9f", + "sha256_in_prefix": "e69977f53f4689c19d2f9fc63a38d84c08f21be3d7a86c65810746dd72e5ef9f", + "size_in_bytes": 17933 + }, + { + "_path": "lib/python3.12/re/__pycache__/_casefix.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b938909683274d4edbe199e5e3f2f479147ef6e8aae9292018fee5083c01196e", + "sha256_in_prefix": "b938909683274d4edbe199e5e3f2f479147ef6e8aae9292018fee5083c01196e", + "size_in_bytes": 1811 + }, + { + "_path": "lib/python3.12/re/__pycache__/_compiler.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ffb1e847cc5ba6dbbf3e460cd7b276b2382fe4d04e462c1db18e5fd1a7c92b6e", + "sha256_in_prefix": "ffb1e847cc5ba6dbbf3e460cd7b276b2382fe4d04e462c1db18e5fd1a7c92b6e", + "size_in_bytes": 26511 + }, + { + "_path": "lib/python3.12/re/__pycache__/_constants.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "efaed394f32b2cc5c8b68829f22efbb41a5ed955652d08a0b317fdb3018dff8a", + "sha256_in_prefix": "efaed394f32b2cc5c8b68829f22efbb41a5ed955652d08a0b317fdb3018dff8a", + "size_in_bytes": 5291 + }, + { + "_path": "lib/python3.12/re/__pycache__/_parser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8f04d475fbd95631491270f9cf4d5fd3977bc255563c879f148750da945c4884", + "sha256_in_prefix": "8f04d475fbd95631491270f9cf4d5fd3977bc255563c879f148750da945c4884", + "size_in_bytes": 42002 + }, + { + "_path": "lib/python3.12/re/_casefix.py", + "path_type": "hardlink", + "sha256": "41572ac50cf96b04496e676d8a6708898bb8e752e06dad34ed4c50c5d8f1fe40", + "sha256_in_prefix": "41572ac50cf96b04496e676d8a6708898bb8e752e06dad34ed4c50c5d8f1fe40", + "size_in_bytes": 5446 + }, + { + "_path": "lib/python3.12/re/_compiler.py", + "path_type": "hardlink", + "sha256": "c05067f8bfa4c13cbbf1eedc4d5cafc9b621bcb6ebc5771ba0518a18095af15a", + "sha256_in_prefix": "c05067f8bfa4c13cbbf1eedc4d5cafc9b621bcb6ebc5771ba0518a18095af15a", + "size_in_bytes": 26089 + }, + { + "_path": "lib/python3.12/re/_constants.py", + "path_type": "hardlink", + "sha256": "fa4fdb200f238f9e7817b63892b0d69833d8165134801e775e10cc113348a375", + "sha256_in_prefix": "fa4fdb200f238f9e7817b63892b0d69833d8165134801e775e10cc113348a375", + "size_in_bytes": 5930 + }, + { + "_path": "lib/python3.12/re/_parser.py", + "path_type": "hardlink", + "sha256": "a51a85b37cf3f44ba7ff25754da5f31306e4ccfa6eb3c017f9d37bdf4e770840", + "sha256_in_prefix": "a51a85b37cf3f44ba7ff25754da5f31306e4ccfa6eb3c017f9d37bdf4e770840", + "size_in_bytes": 41201 + }, + { + "_path": "lib/python3.12/reprlib.py", + "path_type": "hardlink", + "sha256": "8da31054076803065758311f54b18b8a616824941977d907dc3ee729228e9015", + "sha256_in_prefix": "8da31054076803065758311f54b18b8a616824941977d907dc3ee729228e9015", + "size_in_bytes": 6569 + }, + { + "_path": "lib/python3.12/rlcompleter.py", + "path_type": "hardlink", + "sha256": "fee9ad9c55529be48329b78e982fbba0201bd218326eaf80a87996c9f8c805bb", + "sha256_in_prefix": "fee9ad9c55529be48329b78e982fbba0201bd218326eaf80a87996c9f8c805bb", + "size_in_bytes": 7827 + }, + { + "_path": "lib/python3.12/runpy.py", + "path_type": "hardlink", + "sha256": "b1f47f717848022b83b511c74e0f862f58d1e11afa768910e87a49fccf0be2ff", + "sha256_in_prefix": "b1f47f717848022b83b511c74e0f862f58d1e11afa768910e87a49fccf0be2ff", + "size_in_bytes": 12898 + }, + { + "_path": "lib/python3.12/sched.py", + "path_type": "hardlink", + "sha256": "edfb309483d7cb05e06ad86d1fdeb819629f71402dc6710a1bec36c7afcaac50", + "sha256_in_prefix": "edfb309483d7cb05e06ad86d1fdeb819629f71402dc6710a1bec36c7afcaac50", + "size_in_bytes": 6351 + }, + { + "_path": "lib/python3.12/secrets.py", + "path_type": "hardlink", + "sha256": "277000574358a6ecda4bb40e73332ae81a3bc1c8e1fa36f50e5c6a7d4d3f0f17", + "sha256_in_prefix": "277000574358a6ecda4bb40e73332ae81a3bc1c8e1fa36f50e5c6a7d4d3f0f17", + "size_in_bytes": 1984 + }, + { + "_path": "lib/python3.12/selectors.py", + "path_type": "hardlink", + "sha256": "1eeb102373e18c96311203f30c516e785bd8642275aa0bd66e43a284c9692385", + "sha256_in_prefix": "1eeb102373e18c96311203f30c516e785bd8642275aa0bd66e43a284c9692385", + "size_in_bytes": 19671 + }, + { + "_path": "lib/python3.12/shelve.py", + "path_type": "hardlink", + "sha256": "b978c6f0ffa901b041d6518afed03f2938a62168066013ee7d23baac31c356c0", + "sha256_in_prefix": "b978c6f0ffa901b041d6518afed03f2938a62168066013ee7d23baac31c356c0", + "size_in_bytes": 8560 + }, + { + "_path": "lib/python3.12/shlex.py", + "path_type": "hardlink", + "sha256": "f927227de5ba5b1b2bdd75e3d9c8cb72b602b3bba3cc8edbf8fb554de0dc1fd7", + "sha256_in_prefix": "f927227de5ba5b1b2bdd75e3d9c8cb72b602b3bba3cc8edbf8fb554de0dc1fd7", + "size_in_bytes": 13353 + }, + { + "_path": "lib/python3.12/shutil.py", + "path_type": "hardlink", + "sha256": "819e518cb7a539d09b2526138015541b34d2646afb9c2f6ae4ffd476d6a0fcf4", + "sha256_in_prefix": "819e518cb7a539d09b2526138015541b34d2646afb9c2f6ae4ffd476d6a0fcf4", + "size_in_bytes": 58120 + }, + { + "_path": "lib/python3.12/signal.py", + "path_type": "hardlink", + "sha256": "0363c964c90ac0b3e515de5749205e6e6454051a1211058375d84d91eab6071a", + "sha256_in_prefix": "0363c964c90ac0b3e515de5749205e6e6454051a1211058375d84d91eab6071a", + "size_in_bytes": 2495 + }, + { + "_path": "lib/python3.12/site-packages/README.txt", + "path_type": "hardlink", + "sha256": "cba8fece8f62c36306ba27a128f124a257710e41fc619301ee97be93586917cb", + "sha256_in_prefix": "cba8fece8f62c36306ba27a128f124a257710e41fc619301ee97be93586917cb", + "size_in_bytes": 119 + }, + { + "_path": "lib/python3.12/site.py", + "path_type": "hardlink", + "sha256": "72296c68b28b4af912b6cf361d529562210679468e0e3ed04bec8e40a273bb62", + "sha256_in_prefix": "72296c68b28b4af912b6cf361d529562210679468e0e3ed04bec8e40a273bb62", + "size_in_bytes": 22823 + }, + { + "_path": "lib/python3.12/smtplib.py", + "path_type": "hardlink", + "sha256": "f19369e751e199f5dfc05882e2f77b6a692719cebd8a18c84552544a0b93e963", + "sha256_in_prefix": "f19369e751e199f5dfc05882e2f77b6a692719cebd8a18c84552544a0b93e963", + "size_in_bytes": 43532 + }, + { + "_path": "lib/python3.12/sndhdr.py", + "path_type": "hardlink", + "sha256": "d1cb49f6545ef831a69322275ef26f6ca6964953e70d81a8a80fcca8d600ffc0", + "sha256_in_prefix": "d1cb49f6545ef831a69322275ef26f6ca6964953e70d81a8a80fcca8d600ffc0", + "size_in_bytes": 7448 + }, + { + "_path": "lib/python3.12/socket.py", + "path_type": "hardlink", + "sha256": "b59366f7c35583a274c8031351c146d9c64c4e680adf45d99a3335536a20a6cc", + "sha256_in_prefix": "b59366f7c35583a274c8031351c146d9c64c4e680adf45d99a3335536a20a6cc", + "size_in_bytes": 37411 + }, + { + "_path": "lib/python3.12/socketserver.py", + "path_type": "hardlink", + "sha256": "177f7e4c71a255eecb94ef404df1682843a416b7c5083ae2b07a38016d7e16d7", + "sha256_in_prefix": "177f7e4c71a255eecb94ef404df1682843a416b7c5083ae2b07a38016d7e16d7", + "size_in_bytes": 27851 + }, + { + "_path": "lib/python3.12/sqlite3/__init__.py", + "path_type": "hardlink", + "sha256": "f7cc982617b68e147540ef352d38310fe4d25c2c9c2542b67d0590c871df09a8", + "sha256_in_prefix": "f7cc982617b68e147540ef352d38310fe4d25c2c9c2542b67d0590c871df09a8", + "size_in_bytes": 2501 + }, + { + "_path": "lib/python3.12/sqlite3/__main__.py", + "path_type": "hardlink", + "sha256": "495a939623e825a487cde07b62a68aeefdbb1704b53a8b5388af070dc3fac690", + "sha256_in_prefix": "495a939623e825a487cde07b62a68aeefdbb1704b53a8b5388af070dc3fac690", + "size_in_bytes": 3855 + }, + { + "_path": "lib/python3.12/sqlite3/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "86ee6e5e9d09602610ee92337ad6a7b91c5b50059b5c49421d1a298dac01bb4c", + "sha256_in_prefix": "86ee6e5e9d09602610ee92337ad6a7b91c5b50059b5c49421d1a298dac01bb4c", + "size_in_bytes": 1822 + }, + { + "_path": "lib/python3.12/sqlite3/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ae636140e6fec5d88b65af1a9a48749eeded8c1ce825033f70b6180e96ca79e4", + "sha256_in_prefix": "ae636140e6fec5d88b65af1a9a48749eeded8c1ce825033f70b6180e96ca79e4", + "size_in_bytes": 5580 + }, + { + "_path": "lib/python3.12/sqlite3/__pycache__/dbapi2.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d300e5c88a36043ca9ff3bc38db0d4fa7a1d9af93d07d7182db86df02afc321d", + "sha256_in_prefix": "d300e5c88a36043ca9ff3bc38db0d4fa7a1d9af93d07d7182db86df02afc321d", + "size_in_bytes": 5040 + }, + { + "_path": "lib/python3.12/sqlite3/__pycache__/dump.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cff4bf0f03432ca871469952139d8066348a40586eae71df23043b8bab91ad16", + "sha256_in_prefix": "cff4bf0f03432ca871469952139d8066348a40586eae71df23043b8bab91ad16", + "size_in_bytes": 3650 + }, + { + "_path": "lib/python3.12/sqlite3/dbapi2.py", + "path_type": "hardlink", + "sha256": "7c5c8d98df1f2c50c4062a3be2c0f0499190c179fa4fc281507a1ef763a98f28", + "sha256_in_prefix": "7c5c8d98df1f2c50c4062a3be2c0f0499190c179fa4fc281507a1ef763a98f28", + "size_in_bytes": 3631 + }, + { + "_path": "lib/python3.12/sqlite3/dump.py", + "path_type": "hardlink", + "sha256": "7b23e13d844d448f6b34fa8b051cec57c9a2c37a94eae96c57b03233b64457d8", + "sha256_in_prefix": "7b23e13d844d448f6b34fa8b051cec57c9a2c37a94eae96c57b03233b64457d8", + "size_in_bytes": 3471 + }, + { + "_path": "lib/python3.12/sre_compile.py", + "path_type": "hardlink", + "sha256": "f7fd87f8ac9dad7d1387e2401761ec05806c5108201a6d1ede6ab2f481f6df54", + "sha256_in_prefix": "f7fd87f8ac9dad7d1387e2401761ec05806c5108201a6d1ede6ab2f481f6df54", + "size_in_bytes": 231 + }, + { + "_path": "lib/python3.12/sre_constants.py", + "path_type": "hardlink", + "sha256": "87013dc0b349c2c044100f70a8daa9d713e60a527e26f6ab8ee1fc978a6d3234", + "sha256_in_prefix": "87013dc0b349c2c044100f70a8daa9d713e60a527e26f6ab8ee1fc978a6d3234", + "size_in_bytes": 232 + }, + { + "_path": "lib/python3.12/sre_parse.py", + "path_type": "hardlink", + "sha256": "c4929134532306081918f185c99305c6f55213bc16b32f8c259bc60f7f81e810", + "sha256_in_prefix": "c4929134532306081918f185c99305c6f55213bc16b32f8c259bc60f7f81e810", + "size_in_bytes": 229 + }, + { + "_path": "lib/python3.12/ssl.py", + "path_type": "hardlink", + "sha256": "ca7dd38c7d39af5112b9669abffcef3f1bb374fb8fa0a2cd071aea09fce203da", + "sha256_in_prefix": "ca7dd38c7d39af5112b9669abffcef3f1bb374fb8fa0a2cd071aea09fce203da", + "size_in_bytes": 50822 + }, + { + "_path": "lib/python3.12/stat.py", + "path_type": "hardlink", + "sha256": "052af0327eae6941b69b05c088b3e748f79995635f80ac4cc7125eb333eb4c77", + "sha256_in_prefix": "052af0327eae6941b69b05c088b3e748f79995635f80ac4cc7125eb333eb4c77", + "size_in_bytes": 5485 + }, + { + "_path": "lib/python3.12/statistics.py", + "path_type": "hardlink", + "sha256": "b9ef01a757de37e9fbf13d32beeb9530c8271582cabec4998226dcb7e0613cd0", + "sha256_in_prefix": "b9ef01a757de37e9fbf13d32beeb9530c8271582cabec4998226dcb7e0613cd0", + "size_in_bytes": 50227 + }, + { + "_path": "lib/python3.12/string.py", + "path_type": "hardlink", + "sha256": "24aeae1f0526250f442022022bf98df9a823b1cb330543ee79e70e44907462e9", + "sha256_in_prefix": "24aeae1f0526250f442022022bf98df9a823b1cb330543ee79e70e44907462e9", + "size_in_bytes": 11786 + }, + { + "_path": "lib/python3.12/stringprep.py", + "path_type": "hardlink", + "sha256": "60b6c83581093029312efb6670b11c540090b3f78bcf72264467b494f02f21a5", + "sha256_in_prefix": "60b6c83581093029312efb6670b11c540090b3f78bcf72264467b494f02f21a5", + "size_in_bytes": 12917 + }, + { + "_path": "lib/python3.12/struct.py", + "path_type": "hardlink", + "sha256": "9c231f9497caf513a22dee8f790b07f969b0e45854a0bdd6dd84b492e08c2856", + "sha256_in_prefix": "9c231f9497caf513a22dee8f790b07f969b0e45854a0bdd6dd84b492e08c2856", + "size_in_bytes": 257 + }, + { + "_path": "lib/python3.12/subprocess.py", + "path_type": "hardlink", + "sha256": "baa9f9138d8d20df6284f67e7d2e790f847f65e2c5370de322d54cccd737f2d9", + "sha256_in_prefix": "baa9f9138d8d20df6284f67e7d2e790f847f65e2c5370de322d54cccd737f2d9", + "size_in_bytes": 88725 + }, + { + "_path": "lib/python3.12/sunau.py", + "path_type": "hardlink", + "sha256": "7e4f850f6460bcd302439d6d2a9fc1bfc31f88f87ad86c508489f5612b346b7a", + "sha256_in_prefix": "7e4f850f6460bcd302439d6d2a9fc1bfc31f88f87ad86c508489f5612b346b7a", + "size_in_bytes": 18478 + }, + { + "_path": "lib/python3.12/symtable.py", + "path_type": "hardlink", + "sha256": "53801d0f6d9b7702d9537e6a13dfac06b89340f70d9f046aa512f37b3e0ca7a6", + "sha256_in_prefix": "53801d0f6d9b7702d9537e6a13dfac06b89340f70d9f046aa512f37b3e0ca7a6", + "size_in_bytes": 10753 + }, + { + "_path": "lib/python3.12/sysconfig.py", + "path_type": "hardlink", + "sha256": "42d47318d7b26a578adc466a3c5b25266a6ceb154fb67b825b163ed2d02341fb", + "sha256_in_prefix": "42d47318d7b26a578adc466a3c5b25266a6ceb154fb67b825b163ed2d02341fb", + "size_in_bytes": 31075 + }, + { + "_path": "lib/python3.12/tabnanny.py", + "path_type": "hardlink", + "sha256": "edd89dcff09ac08bf48a135cd839bc295d8f74438872973b31c07a75bba7944a", + "sha256_in_prefix": "edd89dcff09ac08bf48a135cd839bc295d8f74438872973b31c07a75bba7944a", + "size_in_bytes": 11531 + }, + { + "_path": "lib/python3.12/tarfile.py", + "path_type": "hardlink", + "sha256": "5dd00cc68e88d9581551b1a457398c5b63d87ae1152fa03ef298743485d12cc8", + "sha256_in_prefix": "5dd00cc68e88d9581551b1a457398c5b63d87ae1152fa03ef298743485d12cc8", + "size_in_bytes": 106883 + }, + { + "_path": "lib/python3.12/telnetlib.py", + "path_type": "hardlink", + "sha256": "1984cebfb50180759ca075b0ea340d3624500dc22fab524a4dbf57c18bb548ca", + "sha256_in_prefix": "1984cebfb50180759ca075b0ea340d3624500dc22fab524a4dbf57c18bb548ca", + "size_in_bytes": 23301 + }, + { + "_path": "lib/python3.12/tempfile.py", + "path_type": "hardlink", + "sha256": "fb44155f430fac1923d3d7b6af1a0210edcfb580291d664e66f338491d68b62b", + "sha256_in_prefix": "fb44155f430fac1923d3d7b6af1a0210edcfb580291d664e66f338491d68b62b", + "size_in_bytes": 32236 + }, + { + "_path": "lib/python3.12/test/__init__.py", + "path_type": "hardlink", + "sha256": "836cdb388117cf81e78d9fa2a141cca1b14b0179733322e710067749a1b16fe9", + "sha256_in_prefix": "836cdb388117cf81e78d9fa2a141cca1b14b0179733322e710067749a1b16fe9", + "size_in_bytes": 47 + }, + { + "_path": "lib/python3.12/test/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c39563a478d12259c34ce52556a4402bb56a1fe66f0d4bcfdbe030b9a04502e0", + "sha256_in_prefix": "c39563a478d12259c34ce52556a4402bb56a1fe66f0d4bcfdbe030b9a04502e0", + "size_in_bytes": 128 + }, + { + "_path": "lib/python3.12/test/__pycache__/test_script_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "25b410d2b02cec47c75a705079bc4595aab8a42b735ebe5597ff8a7c2ec8af64", + "sha256_in_prefix": "25b410d2b02cec47c75a705079bc4595aab8a42b735ebe5597ff8a7c2ec8af64", + "size_in_bytes": 10243 + }, + { + "_path": "lib/python3.12/test/__pycache__/test_support.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3e12fe018f21e450bba96466bd2355f5bede0d2586146ab1d900f3040bb9bf8c", + "sha256_in_prefix": "3e12fe018f21e450bba96466bd2355f5bede0d2586146ab1d900f3040bb9bf8c", + "size_in_bytes": 45191 + }, + { + "_path": "lib/python3.12/test/support/__init__.py", + "path_type": "hardlink", + "sha256": "b83a63661be2ab77e0034fa2ef7bb42fb4c881d8f38d5eff1ed4ab8d089f83db", + "sha256_in_prefix": "b83a63661be2ab77e0034fa2ef7bb42fb4c881d8f38d5eff1ed4ab8d089f83db", + "size_in_bytes": 80010 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d9c929bba09c58a59275cc2baf6a3d513d5a8dea16c65062fdf66d1c15ff0abb", + "sha256_in_prefix": "d9c929bba09c58a59275cc2baf6a3d513d5a8dea16c65062fdf66d1c15ff0abb", + "size_in_bytes": 97323 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/ast_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "da267d7a7bd4c02c4dcf0c4e33c94e3fa06c488213817f0b316c6b049fd64736", + "sha256_in_prefix": "da267d7a7bd4c02c4dcf0c4e33c94e3fa06c488213817f0b316c6b049fd64736", + "size_in_bytes": 2207 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/asynchat.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f938f9c52d7a90384716117278f8f27b98da263c46e94c15fcfedbf160b8aae2", + "sha256_in_prefix": "f938f9c52d7a90384716117278f8f27b98da263c46e94c15fcfedbf160b8aae2", + "size_in_bytes": 10728 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/asyncore.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2f114032aea7396b6d1c797a283e4737f7b88673c5558419db80101d963b12f4", + "sha256_in_prefix": "2f114032aea7396b6d1c797a283e4737f7b88673c5558419db80101d963b12f4", + "size_in_bytes": 24982 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/bytecode_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ca1105f13ee0611125cca3456021b589a85b8e430c384afd74ff056275c1aece", + "sha256_in_prefix": "ca1105f13ee0611125cca3456021b589a85b8e430c384afd74ff056275c1aece", + "size_in_bytes": 7721 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/hashlib_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "141542af98b40a80fcfb62e0fff524fea79fc54d634ebc7c40ffee0c0a7c7d22", + "sha256_in_prefix": "141542af98b40a80fcfb62e0fff524fea79fc54d634ebc7c40ffee0c0a7c7d22", + "size_in_bytes": 2544 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/hypothesis_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f26e8851916e154744c61a1f8c84dd5eaacd1be807ffb321779f4040969ed7cc", + "sha256_in_prefix": "f26e8851916e154744c61a1f8c84dd5eaacd1be807ffb321779f4040969ed7cc", + "size_in_bytes": 1295 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/import_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a73ee42593a49fcb8570fe25faa3c7545f12903293fc086b6c2a34591b65d15f", + "sha256_in_prefix": "a73ee42593a49fcb8570fe25faa3c7545f12903293fc086b6c2a34591b65d15f", + "size_in_bytes": 14761 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/interpreters.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "32ef39eb5b515064df3b7f330a3e4d3ea751ffc78d78875ab8d4c7f15f872acd", + "sha256_in_prefix": "32ef39eb5b515064df3b7f330a3e4d3ea751ffc78d78875ab8d4c7f15f872acd", + "size_in_bytes": 9594 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/logging_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e2512f85da25fc95fff6f3a043ef817b6979b840ef26f4b5462bbf30127f5762", + "sha256_in_prefix": "e2512f85da25fc95fff6f3a043ef817b6979b840ef26f4b5462bbf30127f5762", + "size_in_bytes": 1577 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/os_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ab7f3740829e0277c8c34ad0d8d4521875226c752f00cbe27f5a177f80c46e82", + "sha256_in_prefix": "ab7f3740829e0277c8c34ad0d8d4521875226c752f00cbe27f5a177f80c46e82", + "size_in_bytes": 29780 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/pty_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9d3826271d0c5739a432e2174cff5613a82bafb9e35021296d1e532bb580d0e7", + "sha256_in_prefix": "9d3826271d0c5739a432e2174cff5613a82bafb9e35021296d1e532bb580d0e7", + "size_in_bytes": 3791 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/script_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7f90176d81fe8aefb972c387b676b79c665e4987cb17bd2ec50e67cae10769ba", + "sha256_in_prefix": "7f90176d81fe8aefb972c387b676b79c665e4987cb17bd2ec50e67cae10769ba", + "size_in_bytes": 13046 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/smtpd.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b6b2cb03181ed643cf7ed817beec2d8858a12322b0b840fabaa45e687ccc8b6e", + "sha256_in_prefix": "b6b2cb03181ed643cf7ed817beec2d8858a12322b0b840fabaa45e687ccc8b6e", + "size_in_bytes": 39157 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/socket_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0c2cd003baab90a9057bbfbffc9dafc073a0f702e65506ce70d151a2ac86a02e", + "sha256_in_prefix": "0c2cd003baab90a9057bbfbffc9dafc073a0f702e65506ce70d151a2ac86a02e", + "size_in_bytes": 16231 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/testcase.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f94f1df3d73a0387593da0c9738e6f04401e6c578899d6846d64268c0d709064", + "sha256_in_prefix": "f94f1df3d73a0387593da0c9738e6f04401e6c578899d6846d64268c0d709064", + "size_in_bytes": 1786 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/threading_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7d7f2f4fc41dc06288ab38eab3638ce3020f1938fa025a87892699dc81427662", + "sha256_in_prefix": "7d7f2f4fc41dc06288ab38eab3638ce3020f1938fa025a87892699dc81427662", + "size_in_bytes": 11754 + }, + { + "_path": "lib/python3.12/test/support/__pycache__/warnings_helper.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f07caf4087761b16ab270a178813142e96f11fe851fb2423057816c047e087f1", + "sha256_in_prefix": "f07caf4087761b16ab270a178813142e96f11fe851fb2423057816c047e087f1", + "size_in_bytes": 9906 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/__init__.py", + "path_type": "hardlink", + "sha256": "6addb9fbd5d9007e5d50c40c4af5710d73bd62a5c1192b6d067a35cf580be219", + "sha256_in_prefix": "6addb9fbd5d9007e5d50c40c4af5710d73bd62a5c1192b6d067a35cf580be219", + "size_in_bytes": 2444 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e6d345aea538502b2a0d0a3a85ecb4f86b543e70b1e391fd6ca641a262243e11", + "sha256_in_prefix": "e6d345aea538502b2a0d0a3a85ecb4f86b543e70b1e391fd6ca641a262243e11", + "size_in_bytes": 3926 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/_helpers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8cecfab641dcb8991fb43e535df9c5990a2cb425a81e33b2cdb9c2b06d347fa5", + "sha256_in_prefix": "8cecfab641dcb8991fb43e535df9c5990a2cb425a81e33b2cdb9c2b06d347fa5", + "size_in_bytes": 2576 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/__pycache__/strategies.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "51dec676c81b3679809cbc0a7f04ce6704eb6c276f1f1aaf810c2168ba7b8ce3", + "sha256_in_prefix": "51dec676c81b3679809cbc0a7f04ce6704eb6c276f1f1aaf810c2168ba7b8ce3", + "size_in_bytes": 3094 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/_helpers.py", + "path_type": "hardlink", + "sha256": "7d1d2fc87b9cbaf744af1ed8e31a96947b13da28bf2e7a0358996af9c195e380", + "sha256_in_prefix": "7d1d2fc87b9cbaf744af1ed8e31a96947b13da28bf2e7a0358996af9c195e380", + "size_in_bytes": 1298 + }, + { + "_path": "lib/python3.12/test/support/_hypothesis_stubs/strategies.py", + "path_type": "hardlink", + "sha256": "1fd24490e10dec6271a006fc01014adcccf9d486b7c201dde975092927246b68", + "sha256_in_prefix": "1fd24490e10dec6271a006fc01014adcccf9d486b7c201dde975092927246b68", + "size_in_bytes": 1857 + }, + { + "_path": "lib/python3.12/test/support/ast_helper.py", + "path_type": "hardlink", + "sha256": "5c72e61f5972cec7e2f830aa0bcdd6c8f3d56c7736a8e78af679d994aa7af84e", + "sha256_in_prefix": "5c72e61f5972cec7e2f830aa0bcdd6c8f3d56c7736a8e78af679d994aa7af84e", + "size_in_bytes": 1828 + }, + { + "_path": "lib/python3.12/test/support/asynchat.py", + "path_type": "hardlink", + "sha256": "67f2619c60c171d03b091931851b658f7a92446e131ac261a3352eb0ccc1b17e", + "sha256_in_prefix": "67f2619c60c171d03b091931851b658f7a92446e131ac261a3352eb0ccc1b17e", + "size_in_bytes": 11602 + }, + { + "_path": "lib/python3.12/test/support/asyncore.py", + "path_type": "hardlink", + "sha256": "4cc554dcb58d602bd9d557b2aa497fe9a325d9e021d97a95c0358e907291a47a", + "sha256_in_prefix": "4cc554dcb58d602bd9d557b2aa497fe9a325d9e021d97a95c0358e907291a47a", + "size_in_bytes": 20381 + }, + { + "_path": "lib/python3.12/test/support/bytecode_helper.py", + "path_type": "hardlink", + "sha256": "fb67d0e9f8e7869235e94949b06313e412be59c29ad1f089f323019f0f3a0e49", + "sha256_in_prefix": "fb67d0e9f8e7869235e94949b06313e412be59c29ad1f089f323019f0f3a0e49", + "size_in_bytes": 4999 + }, + { + "_path": "lib/python3.12/test/support/hashlib_helper.py", + "path_type": "hardlink", + "sha256": "19924c427e33c86284ef2a41f76ab6937ab36f12e3d1ef4e617cdbf616a8fc12", + "sha256_in_prefix": "19924c427e33c86284ef2a41f76ab6937ab36f12e3d1ef4e617cdbf616a8fc12", + "size_in_bytes": 1907 + }, + { + "_path": "lib/python3.12/test/support/hypothesis_helper.py", + "path_type": "hardlink", + "sha256": "0cbf55d49bdb78c5a93446d44dfe0bf247a408ae159813989285f7e8c87fd469", + "sha256_in_prefix": "0cbf55d49bdb78c5a93446d44dfe0bf247a408ae159813989285f7e8c87fd469", + "size_in_bytes": 1383 + }, + { + "_path": "lib/python3.12/test/support/import_helper.py", + "path_type": "hardlink", + "sha256": "8466c98fbe5fc76e145a86bf16ef64596aff5f93d1ac943b4079392f7b4b6925", + "sha256_in_prefix": "8466c98fbe5fc76e145a86bf16ef64596aff5f93d1ac943b4079392f7b4b6925", + "size_in_bytes": 10735 + }, + { + "_path": "lib/python3.12/test/support/interpreters.py", + "path_type": "hardlink", + "sha256": "b74464655baa283d2de961e223e0853b498ca51f0889cb790267c8554ac79c92", + "sha256_in_prefix": "b74464655baa283d2de961e223e0853b498ca51f0889cb790267c8554ac79c92", + "size_in_bytes": 5808 + }, + { + "_path": "lib/python3.12/test/support/logging_helper.py", + "path_type": "hardlink", + "sha256": "be1927e654180fcf6d84257be161fe6fa59796774e862c89b6b78adb656738f3", + "sha256_in_prefix": "be1927e654180fcf6d84257be161fe6fa59796774e862c89b6b78adb656738f3", + "size_in_bytes": 916 + }, + { + "_path": "lib/python3.12/test/support/os_helper.py", + "path_type": "hardlink", + "sha256": "927aa94e0831b09c237b129749e06bb355deb007be0e1fd63dc0cdf4ef5c265d", + "sha256_in_prefix": "927aa94e0831b09c237b129749e06bb355deb007be0e1fd63dc0cdf4ef5c265d", + "size_in_bytes": 24286 + }, + { + "_path": "lib/python3.12/test/support/pty_helper.py", + "path_type": "hardlink", + "sha256": "d724296e344278ce3ffb39962c5761dd04b19e987f8068a09fff02cab7418cc2", + "sha256_in_prefix": "d724296e344278ce3ffb39962c5761dd04b19e987f8068a09fff02cab7418cc2", + "size_in_bytes": 3052 + }, + { + "_path": "lib/python3.12/test/support/script_helper.py", + "path_type": "hardlink", + "sha256": "4548165a86eecd536d0231efea5adf656cbfec33371e62a7679724af19a5e204", + "sha256_in_prefix": "4548165a86eecd536d0231efea5adf656cbfec33371e62a7679724af19a5e204", + "size_in_bytes": 11721 + }, + { + "_path": "lib/python3.12/test/support/smtpd.py", + "path_type": "hardlink", + "sha256": "00599762dd76cb7f6e0763238079c436f96f6a50331abaf2511cad8f0169ae40", + "sha256_in_prefix": "00599762dd76cb7f6e0763238079c436f96f6a50331abaf2511cad8f0169ae40", + "size_in_bytes": 30733 + }, + { + "_path": "lib/python3.12/test/support/socket_helper.py", + "path_type": "hardlink", + "sha256": "482196211cee77253034cb6b85b50bffb302fde20f083a5e888f34af603ea4ec", + "sha256_in_prefix": "482196211cee77253034cb6b85b50bffb302fde20f083a5e888f34af603ea4ec", + "size_in_bytes": 13794 + }, + { + "_path": "lib/python3.12/test/support/testcase.py", + "path_type": "hardlink", + "sha256": "3181376673273db26aa634b690c176d9b5cc176351f5f0d0d5f5a480d6fa0ece", + "sha256_in_prefix": "3181376673273db26aa634b690c176d9b5cc176351f5f0d0d5f5a480d6fa0ece", + "size_in_bytes": 1047 + }, + { + "_path": "lib/python3.12/test/support/threading_helper.py", + "path_type": "hardlink", + "sha256": "7f191895d8e33cb8b36645d0ef197096c459c6f63450366114753a85eaa8c113", + "sha256_in_prefix": "7f191895d8e33cb8b36645d0ef197096c459c6f63450366114753a85eaa8c113", + "size_in_bytes": 8049 + }, + { + "_path": "lib/python3.12/test/support/warnings_helper.py", + "path_type": "hardlink", + "sha256": "515c10201568a2fcb868d1c34ffe9d7f04e3f617a2cb61d587167359a83b09ec", + "sha256_in_prefix": "515c10201568a2fcb868d1c34ffe9d7f04e3f617a2cb61d587167359a83b09ec", + "size_in_bytes": 6853 + }, + { + "_path": "lib/python3.12/test/test_script_helper.py", + "path_type": "hardlink", + "sha256": "f484f6c67bdf6c47322799d6d9437dd4d00ff194c98f6caf97bb69e7bd65e867", + "sha256_in_prefix": "f484f6c67bdf6c47322799d6d9437dd4d00ff194c98f6caf97bb69e7bd65e867", + "size_in_bytes": 5960 + }, + { + "_path": "lib/python3.12/test/test_support.py", + "path_type": "hardlink", + "sha256": "abb8f0e9bce292ff4ce907541aa4fcae663064e9340b0fe9a41a3e9c07729fdc", + "sha256_in_prefix": "abb8f0e9bce292ff4ce907541aa4fcae663064e9340b0fe9a41a3e9c07729fdc", + "size_in_bytes": 27701 + }, + { + "_path": "lib/python3.12/textwrap.py", + "path_type": "hardlink", + "sha256": "62867e40cdea6669b361f72af4d7daf0359f207c92cbeddfc7c7506397c1f31c", + "sha256_in_prefix": "62867e40cdea6669b361f72af4d7daf0359f207c92cbeddfc7c7506397c1f31c", + "size_in_bytes": 19718 + }, + { + "_path": "lib/python3.12/this.py", + "path_type": "hardlink", + "sha256": "481d0cb3de511eae0b5713dad18542b07eafd9c013bb7690f7497bad49923a71", + "sha256_in_prefix": "481d0cb3de511eae0b5713dad18542b07eafd9c013bb7690f7497bad49923a71", + "size_in_bytes": 1003 + }, + { + "_path": "lib/python3.12/threading.py", + "path_type": "hardlink", + "sha256": "8273b4cf5b6f274b4993f5cae08634dd272c6952af9867ff9aa13ed446f1549b", + "sha256_in_prefix": "8273b4cf5b6f274b4993f5cae08634dd272c6952af9867ff9aa13ed446f1549b", + "size_in_bytes": 60123 + }, + { + "_path": "lib/python3.12/timeit.py", + "path_type": "hardlink", + "sha256": "d47d9deb6be0136d817e04d0e4824aa66c66efa01fe61cf62860fff08ecfe83a", + "sha256_in_prefix": "d47d9deb6be0136d817e04d0e4824aa66c66efa01fe61cf62860fff08ecfe83a", + "size_in_bytes": 13464 + }, + { + "_path": "lib/python3.12/tkinter/__init__.py", + "path_type": "hardlink", + "sha256": "a2bd0d90e51582cf816f31914487397f1949f38b3c6b7aeeb5a2bfe4293a2973", + "sha256_in_prefix": "a2bd0d90e51582cf816f31914487397f1949f38b3c6b7aeeb5a2bfe4293a2973", + "size_in_bytes": 172818 + }, + { + "_path": "lib/python3.12/tkinter/__main__.py", + "path_type": "hardlink", + "sha256": "9738a6cb9cdd8139721dd82118bd527897db5325d807222883f70fb1c5a1c27e", + "sha256_in_prefix": "9738a6cb9cdd8139721dd82118bd527897db5325d807222883f70fb1c5a1c27e", + "size_in_bytes": 148 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6ad50f727edd215bf674eff1ee82c1736260c131ea5548ea9d451f07aafc6b76", + "sha256_in_prefix": "6ad50f727edd215bf674eff1ee82c1736260c131ea5548ea9d451f07aafc6b76", + "size_in_bytes": 245226 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b3f3d85c6c985011c111b1ff29f7546599a61fb1adda30f6cb63b30117afa384", + "sha256_in_prefix": "b3f3d85c6c985011c111b1ff29f7546599a61fb1adda30f6cb63b30117afa384", + "size_in_bytes": 417 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/colorchooser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "14face1e505d8e955fdca171c458ac72e47c8ffeb782535bcf6ec815740f8bbc", + "sha256_in_prefix": "14face1e505d8e955fdca171c458ac72e47c8ffeb782535bcf6ec815740f8bbc", + "size_in_bytes": 2751 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/commondialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "223c1fbd5cb0f27f6265d44c727df73b81e89657192208830979d2123e6f8da3", + "sha256_in_prefix": "223c1fbd5cb0f27f6265d44c727df73b81e89657192208830979d2123e6f8da3", + "size_in_bytes": 1889 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/constants.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "15501da089c90a06aa5377d11051cb41c663014ece067e674779f1cfbcf621c3", + "sha256_in_prefix": "15501da089c90a06aa5377d11051cb41c663014ece067e674779f1cfbcf621c3", + "size_in_bytes": 1927 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/dialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "72d3bf0f1a0219bed0fadfcd4538654c3718d6f632e3527d18f919183ce57de4", + "sha256_in_prefix": "72d3bf0f1a0219bed0fadfcd4538654c3718d6f632e3527d18f919183ce57de4", + "size_in_bytes": 2105 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/dnd.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "484027aea1f27af493a35517af5afc0b1e2b2723821efd81baf08dc154b037eb", + "sha256_in_prefix": "484027aea1f27af493a35517af5afc0b1e2b2723821efd81baf08dc154b037eb", + "size_in_bytes": 16320 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/filedialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "39efc6785eb8f7502b8dc118b3dffaadd9fa3b9ae1677a5fc11a0a53b81efe44", + "sha256_in_prefix": "39efc6785eb8f7502b8dc118b3dffaadd9fa3b9ae1677a5fc11a0a53b81efe44", + "size_in_bytes": 22625 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/font.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "940327cbe0cf6e9f07d755af8cac79b2a147de014f98cb7ada73344ca6d93cf9", + "sha256_in_prefix": "940327cbe0cf6e9f07d755af8cac79b2a147de014f98cb7ada73344ca6d93cf9", + "size_in_bytes": 10887 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/messagebox.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "471c4d98203b89bfdde51539228114d19500a3d4ad243a3f774185392eb2495f", + "sha256_in_prefix": "471c4d98203b89bfdde51539228114d19500a3d4ad243a3f774185392eb2495f", + "size_in_bytes": 4095 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/scrolledtext.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c9f8daee1369d4731b181c71149f00466a155b32ee5ae279c81bf64dcd9d77a6", + "sha256_in_prefix": "c9f8daee1369d4731b181c71149f00466a155b32ee5ae279c81bf64dcd9d77a6", + "size_in_bytes": 3324 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/simpledialog.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "2f47bb73e66641f9f23d160c0d43edb649682837ea5693a86f0cb6d4b1a6413f", + "sha256_in_prefix": "2f47bb73e66641f9f23d160c0d43edb649682837ea5693a86f0cb6d4b1a6413f", + "size_in_bytes": 17538 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/tix.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "84cc9dc4675f3d68d66c0c4fdb4a6368e011669b840b6f0ba7b23148555f47aa", + "sha256_in_prefix": "84cc9dc4675f3d68d66c0c4fdb4a6368e011669b840b6f0ba7b23148555f47aa", + "size_in_bytes": 111814 + }, + { + "_path": "lib/python3.12/tkinter/__pycache__/ttk.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b732a93e25cc9d6a5f90649d35397ab1d3d4fd6a576dbb331e7c9c983a5de429", + "sha256_in_prefix": "b732a93e25cc9d6a5f90649d35397ab1d3d4fd6a576dbb331e7c9c983a5de429", + "size_in_bytes": 73574 + }, + { + "_path": "lib/python3.12/tkinter/colorchooser.py", + "path_type": "hardlink", + "sha256": "1224241dcfb4ec6aff3cafc66adeb2b2a3759397a28693173915458c50040143", + "sha256_in_prefix": "1224241dcfb4ec6aff3cafc66adeb2b2a3759397a28693173915458c50040143", + "size_in_bytes": 2660 + }, + { + "_path": "lib/python3.12/tkinter/commondialog.py", + "path_type": "hardlink", + "sha256": "e683ab0ee9404baec656a88d637910bcb2badb4b4e5d5def2b80cc4534551e6f", + "sha256_in_prefix": "e683ab0ee9404baec656a88d637910bcb2badb4b4e5d5def2b80cc4534551e6f", + "size_in_bytes": 1289 + }, + { + "_path": "lib/python3.12/tkinter/constants.py", + "path_type": "hardlink", + "sha256": "c01314dc51d1c8effeba2528720a65da133596d4143200c68595c02067bf1da2", + "sha256_in_prefix": "c01314dc51d1c8effeba2528720a65da133596d4143200c68595c02067bf1da2", + "size_in_bytes": 1493 + }, + { + "_path": "lib/python3.12/tkinter/dialog.py", + "path_type": "hardlink", + "sha256": "4f8201d3ada7b6d0f450b417e55747adaee5f894412c4875169b0736a5ff0faa", + "sha256_in_prefix": "4f8201d3ada7b6d0f450b417e55747adaee5f894412c4875169b0736a5ff0faa", + "size_in_bytes": 1535 + }, + { + "_path": "lib/python3.12/tkinter/dnd.py", + "path_type": "hardlink", + "sha256": "542b804b243b502b5525a8b1f04a02a120b1db4e3599f5c7865e60693ed3672a", + "sha256_in_prefix": "542b804b243b502b5525a8b1f04a02a120b1db4e3599f5c7865e60693ed3672a", + "size_in_bytes": 11644 + }, + { + "_path": "lib/python3.12/tkinter/filedialog.py", + "path_type": "hardlink", + "sha256": "d75c1eb4131db658b8622acffd8262ecbd7337425c799ea3be8d605ea6be7b94", + "sha256_in_prefix": "d75c1eb4131db658b8622acffd8262ecbd7337425c799ea3be8d605ea6be7b94", + "size_in_bytes": 14939 + }, + { + "_path": "lib/python3.12/tkinter/font.py", + "path_type": "hardlink", + "sha256": "a73482badacc4a69ff7fae9445793a4d858212fdef103360a478bbfd6ed2f496", + "sha256_in_prefix": "a73482badacc4a69ff7fae9445793a4d858212fdef103360a478bbfd6ed2f496", + "size_in_bytes": 7000 + }, + { + "_path": "lib/python3.12/tkinter/messagebox.py", + "path_type": "hardlink", + "sha256": "cdbf655c66778a19f0e25754a5f198a850c8bd958ce651e8fe4b2b52ad7f9c63", + "sha256_in_prefix": "cdbf655c66778a19f0e25754a5f198a850c8bd958ce651e8fe4b2b52ad7f9c63", + "size_in_bytes": 3861 + }, + { + "_path": "lib/python3.12/tkinter/scrolledtext.py", + "path_type": "hardlink", + "sha256": "c7cc050ec9cc3cc6a47215b5bc79b2d3e5c6ed895a4300ab0e20f6c249385e3f", + "sha256_in_prefix": "c7cc050ec9cc3cc6a47215b5bc79b2d3e5c6ed895a4300ab0e20f6c249385e3f", + "size_in_bytes": 1816 + }, + { + "_path": "lib/python3.12/tkinter/simpledialog.py", + "path_type": "hardlink", + "sha256": "63349ae75f9d74a49376f3375e38e5059c9424b918bfd2c67cf45ec70dcf3eac", + "sha256_in_prefix": "63349ae75f9d74a49376f3375e38e5059c9424b918bfd2c67cf45ec70dcf3eac", + "size_in_bytes": 11753 + }, + { + "_path": "lib/python3.12/tkinter/tix.py", + "path_type": "hardlink", + "sha256": "5d7a11093a1f6510de786b0e9d67902ab33a57f637cd8f5e2603cf6c5c609a18", + "sha256_in_prefix": "5d7a11093a1f6510de786b0e9d67902ab33a57f637cd8f5e2603cf6c5c609a18", + "size_in_bytes": 77032 + }, + { + "_path": "lib/python3.12/tkinter/ttk.py", + "path_type": "hardlink", + "sha256": "9e10f6f4434357958dc813ae4d9128d36d51f7bf9193ebc3f1ea049176a8b5ad", + "sha256_in_prefix": "9e10f6f4434357958dc813ae4d9128d36d51f7bf9193ebc3f1ea049176a8b5ad", + "size_in_bytes": 56242 + }, + { + "_path": "lib/python3.12/token.py", + "path_type": "hardlink", + "sha256": "fc76ed1a1cbdb2c961d27cd67acee766abcfcdab06661701db4d9524efb5bd41", + "sha256_in_prefix": "fc76ed1a1cbdb2c961d27cd67acee766abcfcdab06661701db4d9524efb5bd41", + "size_in_bytes": 2479 + }, + { + "_path": "lib/python3.12/tokenize.py", + "path_type": "hardlink", + "sha256": "a39cd5ee895abc085117448fba78ccc18bea3faf073ac18c5365b26e0dd1fe7c", + "sha256_in_prefix": "a39cd5ee895abc085117448fba78ccc18bea3faf073ac18c5365b26e0dd1fe7c", + "size_in_bytes": 21214 + }, + { + "_path": "lib/python3.12/tomllib/__init__.py", + "path_type": "hardlink", + "sha256": "71f67036895f4c5acab942618af0cbd3d814451ba61e967f358d0f341a5b8f51", + "sha256_in_prefix": "71f67036895f4c5acab942618af0cbd3d814451ba61e967f358d0f341a5b8f51", + "size_in_bytes": 308 + }, + { + "_path": "lib/python3.12/tomllib/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9e6350ccd0a15a6fee5ac2b33df28a864472981cb5d5974354a8c10d70c3b6ec", + "sha256_in_prefix": "9e6350ccd0a15a6fee5ac2b33df28a864472981cb5d5974354a8c10d70c3b6ec", + "size_in_bytes": 298 + }, + { + "_path": "lib/python3.12/tomllib/__pycache__/_parser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e39a02d99dcba5962f881560f0b6ca66cffa84b36f20331f2de31dd59a91ad31", + "sha256_in_prefix": "e39a02d99dcba5962f881560f0b6ca66cffa84b36f20331f2de31dd59a91ad31", + "size_in_bytes": 26868 + }, + { + "_path": "lib/python3.12/tomllib/__pycache__/_re.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ceaf3f5e40deb922f7d68e63fb9868fbd11077dc5fc8be347e4fcbe6f5277359", + "sha256_in_prefix": "ceaf3f5e40deb922f7d68e63fb9868fbd11077dc5fc8be347e4fcbe6f5277359", + "size_in_bytes": 3851 + }, + { + "_path": "lib/python3.12/tomllib/__pycache__/_types.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d22e4e542376ac774e2d0604f9ad12434f75d9c893ad087e224f7e098d8d0690", + "sha256_in_prefix": "d22e4e542376ac774e2d0604f9ad12434f75d9c893ad087e224f7e098d8d0690", + "size_in_bytes": 309 + }, + { + "_path": "lib/python3.12/tomllib/_parser.py", + "path_type": "hardlink", + "sha256": "4579b04a7566452304781ccce37d3ebc1c36e810b058bdb1f33c0e51ddab0397", + "sha256_in_prefix": "4579b04a7566452304781ccce37d3ebc1c36e810b058bdb1f33c0e51ddab0397", + "size_in_bytes": 22631 + }, + { + "_path": "lib/python3.12/tomllib/_re.py", + "path_type": "hardlink", + "sha256": "75b8e0e428594f6dca6bdcfd0c73977ddb52a4fc147dd80c5e78fc34ea25cbec", + "sha256_in_prefix": "75b8e0e428594f6dca6bdcfd0c73977ddb52a4fc147dd80c5e78fc34ea25cbec", + "size_in_bytes": 2943 + }, + { + "_path": "lib/python3.12/tomllib/_types.py", + "path_type": "hardlink", + "sha256": "f864c6d9552a929c7032ace654ee05ef26ca75d21b027b801d77e65907138b74", + "sha256_in_prefix": "f864c6d9552a929c7032ace654ee05ef26ca75d21b027b801d77e65907138b74", + "size_in_bytes": 254 + }, + { + "_path": "lib/python3.12/trace.py", + "path_type": "hardlink", + "sha256": "dd08f8dc9adfd264e52adaf319be22246e59f2b3a9c2b6fd8cfd62bc915be639", + "sha256_in_prefix": "dd08f8dc9adfd264e52adaf319be22246e59f2b3a9c2b6fd8cfd62bc915be639", + "size_in_bytes": 29182 + }, + { + "_path": "lib/python3.12/traceback.py", + "path_type": "hardlink", + "sha256": "a96b7d5bfe46a8be9b90613b1555dbd795d51f46aec6b769af06cec465bee39e", + "sha256_in_prefix": "a96b7d5bfe46a8be9b90613b1555dbd795d51f46aec6b769af06cec465bee39e", + "size_in_bytes": 46325 + }, + { + "_path": "lib/python3.12/tracemalloc.py", + "path_type": "hardlink", + "sha256": "c2cc84a05b824df79840c98729a0e94ef8909b11c528a1b2c5a00aa436b97b25", + "sha256_in_prefix": "c2cc84a05b824df79840c98729a0e94ef8909b11c528a1b2c5a00aa436b97b25", + "size_in_bytes": 18047 + }, + { + "_path": "lib/python3.12/tty.py", + "path_type": "hardlink", + "sha256": "1ab5e5e047130b310355e907a3306178299b9f2044fb526ac63bd116e9a16d2b", + "sha256_in_prefix": "1ab5e5e047130b310355e907a3306178299b9f2044fb526ac63bd116e9a16d2b", + "size_in_bytes": 2035 + }, + { + "_path": "lib/python3.12/turtle.py", + "path_type": "hardlink", + "sha256": "1140915f9d17dc0b9ca8ced708d21d75fb38ae395b063a351d85874c7b9fc154", + "sha256_in_prefix": "1140915f9d17dc0b9ca8ced708d21d75fb38ae395b063a351d85874c7b9fc154", + "size_in_bytes": 146361 + }, + { + "_path": "lib/python3.12/turtledemo/__init__.py", + "path_type": "hardlink", + "sha256": "5f465277c96c107a5af544b0a962561f97cb0bfd75906d9bf9741450ed02b0e1", + "sha256_in_prefix": "5f465277c96c107a5af544b0a962561f97cb0bfd75906d9bf9741450ed02b0e1", + "size_in_bytes": 314 + }, + { + "_path": "lib/python3.12/turtledemo/__main__.py", + "path_type": "hardlink", + "sha256": "6620f0af34be5e144cf5097f120b3c9e457be5389b8b35c7aae2e88495486aee", + "sha256_in_prefix": "6620f0af34be5e144cf5097f120b3c9e457be5389b8b35c7aae2e88495486aee", + "size_in_bytes": 15285 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "7bee9c136ce42e4faef85ec6b9d19da05f2339b602ccdeed8b9229cf9c3fa419", + "sha256_in_prefix": "7bee9c136ce42e4faef85ec6b9d19da05f2339b602ccdeed8b9229cf9c3fa419", + "size_in_bytes": 461 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d7867152eb635ae50289aecd55596ee63cb68a9038bb128e4cce3bfe639de93c", + "sha256_in_prefix": "d7867152eb635ae50289aecd55596ee63cb68a9038bb128e4cce3bfe639de93c", + "size_in_bytes": 21367 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/bytedesign.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "908c7c96c5a1eee087ef1dd45a5b25efd0e4b0d1aa7f68fa9ae0f4f7e086a207", + "sha256_in_prefix": "908c7c96c5a1eee087ef1dd45a5b25efd0e4b0d1aa7f68fa9ae0f4f7e086a207", + "size_in_bytes": 8222 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/chaos.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "c28aaf3356557d3378c64fbe0a100cfd6c7e1ced5eab6a0977f6b974c71d2a4a", + "sha256_in_prefix": "c28aaf3356557d3378c64fbe0a100cfd6c7e1ced5eab6a0977f6b974c71d2a4a", + "size_in_bytes": 2481 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/clock.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b85201ca094543e9ae1d635136669fd6fc4e9da5364bb89d8521afcd9fb174c7", + "sha256_in_prefix": "b85201ca094543e9ae1d635136669fd6fc4e9da5364bb89d8521afcd9fb174c7", + "size_in_bytes": 5911 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/colormixer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "90c62677d76ea2b5cc891e97f6129c6b8568dd89680ce457a0814b8b989b862c", + "sha256_in_prefix": "90c62677d76ea2b5cc891e97f6129c6b8568dd89680ce457a0814b8b989b862c", + "size_in_bytes": 3313 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/forest.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d71901069376826da96f53138cb496ea6f5e7805c1242a2a4888b461b5fd2223", + "sha256_in_prefix": "d71901069376826da96f53138cb496ea6f5e7805c1242a2a4888b461b5fd2223", + "size_in_bytes": 5093 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/fractalcurves.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "71c454fae2e1578207c486370f0a2ffd4275b39747505479d639d1f863d382c2", + "sha256_in_prefix": "71c454fae2e1578207c486370f0a2ffd4275b39747505479d639d1f863d382c2", + "size_in_bytes": 5789 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/lindenmayer.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e599af1b1f518137ce59388cf6bab3a66dea8e0ad371ce230f42c5d163de1280", + "sha256_in_prefix": "e599af1b1f518137ce59388cf6bab3a66dea8e0ad371ce230f42c5d163de1280", + "size_in_bytes": 3775 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/minimal_hanoi.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ec2dbe3c887e080ef593910063725fcbad89dda1c8998a346d3ba79fd5e99f5d", + "sha256_in_prefix": "ec2dbe3c887e080ef593910063725fcbad89dda1c8998a346d3ba79fd5e99f5d", + "size_in_bytes": 3975 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/nim.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8f6b748c58eede37d7f8cfa37e8019190d2cdeb957c0c9a3ce57c6b87681a9d8", + "sha256_in_prefix": "8f6b748c58eede37d7f8cfa37e8019190d2cdeb957c0c9a3ce57c6b87681a9d8", + "size_in_bytes": 13529 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/paint.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b4d20c3fb73953d1528e2617a42881812a23e412ce3586f5e7a370a59f6924ca", + "sha256_in_prefix": "b4d20c3fb73953d1528e2617a42881812a23e412ce3586f5e7a370a59f6924ca", + "size_in_bytes": 2066 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/peace.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "17d68921b4bdb5748a31ec9e186eed020a1ca44e58e32c35d1e156e180cdfcb1", + "sha256_in_prefix": "17d68921b4bdb5748a31ec9e186eed020a1ca44e58e32c35d1e156e180cdfcb1", + "size_in_bytes": 1809 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/penrose.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6967233d9d92b9d3de59966fed3e610fe7a008ca5c27ac1290bc38b3f05dba8e", + "sha256_in_prefix": "6967233d9d92b9d3de59966fed3e610fe7a008ca5c27ac1290bc38b3f05dba8e", + "size_in_bytes": 7198 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/planet_and_moon.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1a2b2a53492745589ebb5f82e08fd3cf3fbcd4dfe771a09d5a63c3cb2c91b928", + "sha256_in_prefix": "1a2b2a53492745589ebb5f82e08fd3cf3fbcd4dfe771a09d5a63c3cb2c91b928", + "size_in_bytes": 6305 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/rosette.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b68d37f218b4872a9531191c8bc91e8124f20c658694b1595c737a35f5222429", + "sha256_in_prefix": "b68d37f218b4872a9531191c8bc91e8124f20c658694b1595c737a35f5222429", + "size_in_bytes": 2831 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/round_dance.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a7930b257a41cc47b37428d27e8186e8dd4f7a26d5c0d5bc5733b3f20ee2a897", + "sha256_in_prefix": "a7930b257a41cc47b37428d27e8186e8dd4f7a26d5c0d5bc5733b3f20ee2a897", + "size_in_bytes": 2823 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/sorting_animate.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8a151dae98d624a6c86e10dfcbf3bba0806c9a9395ac19d81abc9bad64f119fc", + "sha256_in_prefix": "8a151dae98d624a6c86e10dfcbf3bba0806c9a9395ac19d81abc9bad64f119fc", + "size_in_bytes": 10271 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/tree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1d20c3b006e8bd6f61b97e244a0c855ae1c6047656ba1b6e6d203799ce3aadce", + "sha256_in_prefix": "1d20c3b006e8bd6f61b97e244a0c855ae1c6047656ba1b6e6d203799ce3aadce", + "size_in_bytes": 2542 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/two_canvases.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f27cfecf48302a86ff673fb1828ba92e2d019fbca952042748f5f4b0e842bc4f", + "sha256_in_prefix": "f27cfecf48302a86ff673fb1828ba92e2d019fbca952042748f5f4b0e842bc4f", + "size_in_bytes": 2301 + }, + { + "_path": "lib/python3.12/turtledemo/__pycache__/yinyang.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "68c14f4a65724ed3d086416c53c48b13701be82de8066832517f66c968a211a1", + "sha256_in_prefix": "68c14f4a65724ed3d086416c53c48b13701be82de8066832517f66c968a211a1", + "size_in_bytes": 1654 + }, + { + "_path": "lib/python3.12/turtledemo/bytedesign.py", + "path_type": "hardlink", + "sha256": "6deeee99e0ddb4ed29a648f95d4d33e9f3292c21dbecec301337c22a605a280f", + "sha256_in_prefix": "6deeee99e0ddb4ed29a648f95d4d33e9f3292c21dbecec301337c22a605a280f", + "size_in_bytes": 4248 + }, + { + "_path": "lib/python3.12/turtledemo/chaos.py", + "path_type": "hardlink", + "sha256": "bc8a3a9b77e90446fb7060ff68ee008ffd6b23b366052207ec225cc163b4dae5", + "sha256_in_prefix": "bc8a3a9b77e90446fb7060ff68ee008ffd6b23b366052207ec225cc163b4dae5", + "size_in_bytes": 951 + }, + { + "_path": "lib/python3.12/turtledemo/clock.py", + "path_type": "hardlink", + "sha256": "8728b6e1f7e81e8c9fbc5797588d1766e6be15d353e0f29c38f3e75d28084fcd", + "sha256_in_prefix": "8728b6e1f7e81e8c9fbc5797588d1766e6be15d353e0f29c38f3e75d28084fcd", + "size_in_bytes": 3180 + }, + { + "_path": "lib/python3.12/turtledemo/colormixer.py", + "path_type": "hardlink", + "sha256": "bbb065830edb37fd53b1c004118853176fd8da32ee532cb0d363960880920374", + "sha256_in_prefix": "bbb065830edb37fd53b1c004118853176fd8da32ee532cb0d363960880920374", + "size_in_bytes": 1339 + }, + { + "_path": "lib/python3.12/turtledemo/forest.py", + "path_type": "hardlink", + "sha256": "68cd81b7da35ca49d9066cc2cba24768cddbf90797dbd619a559cf899cde926b", + "sha256_in_prefix": "68cd81b7da35ca49d9066cc2cba24768cddbf90797dbd619a559cf899cde926b", + "size_in_bytes": 2966 + }, + { + "_path": "lib/python3.12/turtledemo/fractalcurves.py", + "path_type": "hardlink", + "sha256": "29fadf34c5eabda4649848d052fa2ed3ae829e55bc3ac5933f2aedf3fb04b320", + "sha256_in_prefix": "29fadf34c5eabda4649848d052fa2ed3ae829e55bc3ac5933f2aedf3fb04b320", + "size_in_bytes": 3473 + }, + { + "_path": "lib/python3.12/turtledemo/lindenmayer.py", + "path_type": "hardlink", + "sha256": "4b597f52c1cb35ae8ed540d1db2dab52276c7874febd7a659ee50f26be26f61e", + "sha256_in_prefix": "4b597f52c1cb35ae8ed540d1db2dab52276c7874febd7a659ee50f26be26f61e", + "size_in_bytes": 2434 + }, + { + "_path": "lib/python3.12/turtledemo/minimal_hanoi.py", + "path_type": "hardlink", + "sha256": "0e458a6257fb5a4ecd2785962850fa87924b23d4ead8aebb70aab38904ff8ef5", + "sha256_in_prefix": "0e458a6257fb5a4ecd2785962850fa87924b23d4ead8aebb70aab38904ff8ef5", + "size_in_bytes": 2051 + }, + { + "_path": "lib/python3.12/turtledemo/nim.py", + "path_type": "hardlink", + "sha256": "939d1ee904a7b00579bb44719b0286e7524bf560c7ffff6d482064b41b09fdb3", + "sha256_in_prefix": "939d1ee904a7b00579bb44719b0286e7524bf560c7ffff6d482064b41b09fdb3", + "size_in_bytes": 6513 + }, + { + "_path": "lib/python3.12/turtledemo/paint.py", + "path_type": "hardlink", + "sha256": "81aa22d0da1d934cb47edfef1883f9fe8ef864c56d484f79f9ec4b46457d047e", + "sha256_in_prefix": "81aa22d0da1d934cb47edfef1883f9fe8ef864c56d484f79f9ec4b46457d047e", + "size_in_bytes": 1291 + }, + { + "_path": "lib/python3.12/turtledemo/peace.py", + "path_type": "hardlink", + "sha256": "b260b857164684b3065ad760fec0245ab6505c220814fb179a3d080f2bba0814", + "sha256_in_prefix": "b260b857164684b3065ad760fec0245ab6505c220814fb179a3d080f2bba0814", + "size_in_bytes": 1066 + }, + { + "_path": "lib/python3.12/turtledemo/penrose.py", + "path_type": "hardlink", + "sha256": "14aeb10db966bfd4ec923a19eb96892eb2aa2723c0962c0824fe2ca9f30e300a", + "sha256_in_prefix": "14aeb10db966bfd4ec923a19eb96892eb2aa2723c0962c0824fe2ca9f30e300a", + "size_in_bytes": 3380 + }, + { + "_path": "lib/python3.12/turtledemo/planet_and_moon.py", + "path_type": "hardlink", + "sha256": "cd2c5344b67dbe781cf4c7f0f1eb1b97e6d8a5bf50329bdaa4e42e7d390ea609", + "sha256_in_prefix": "cd2c5344b67dbe781cf4c7f0f1eb1b97e6d8a5bf50329bdaa4e42e7d390ea609", + "size_in_bytes": 2825 + }, + { + "_path": "lib/python3.12/turtledemo/rosette.py", + "path_type": "hardlink", + "sha256": "61dfd5bb932cc5a0c3bb9caa8ed74889a19a8d3ee3cb6707ea8f63595ec350b0", + "sha256_in_prefix": "61dfd5bb932cc5a0c3bb9caa8ed74889a19a8d3ee3cb6707ea8f63595ec350b0", + "size_in_bytes": 1361 + }, + { + "_path": "lib/python3.12/turtledemo/round_dance.py", + "path_type": "hardlink", + "sha256": "4ecaac02e68f11ec1a406a6ce8a4b17e4f8af74f76157e0776360d0dd041f276", + "sha256_in_prefix": "4ecaac02e68f11ec1a406a6ce8a4b17e4f8af74f76157e0776360d0dd041f276", + "size_in_bytes": 1804 + }, + { + "_path": "lib/python3.12/turtledemo/sorting_animate.py", + "path_type": "hardlink", + "sha256": "a82a7608d3620cd8a956d3335bddbc2e30320486645de5d2ec26f481b0a74254", + "sha256_in_prefix": "a82a7608d3620cd8a956d3335bddbc2e30320486645de5d2ec26f481b0a74254", + "size_in_bytes": 5052 + }, + { + "_path": "lib/python3.12/turtledemo/tree.py", + "path_type": "hardlink", + "sha256": "3318448046c83c176f95a97c33b5cd82e0076bee038d72810bef3dac1085e590", + "sha256_in_prefix": "3318448046c83c176f95a97c33b5cd82e0076bee038d72810bef3dac1085e590", + "size_in_bytes": 1401 + }, + { + "_path": "lib/python3.12/turtledemo/turtle.cfg", + "path_type": "hardlink", + "sha256": "de66698dc4f083792df6aaed1e5d94e879852d72f1f24ac09c8fb4cd144c6c88", + "sha256_in_prefix": "de66698dc4f083792df6aaed1e5d94e879852d72f1f24ac09c8fb4cd144c6c88", + "size_in_bytes": 160 + }, + { + "_path": "lib/python3.12/turtledemo/two_canvases.py", + "path_type": "hardlink", + "sha256": "3300593114fb9286af9360cc9d871a40e5dcbea4aedc24b832607d1dd71c7b96", + "sha256_in_prefix": "3300593114fb9286af9360cc9d871a40e5dcbea4aedc24b832607d1dd71c7b96", + "size_in_bytes": 1119 + }, + { + "_path": "lib/python3.12/turtledemo/yinyang.py", + "path_type": "hardlink", + "sha256": "0737a80b939aafcf3d8a1bf60b63e781979c749337d02b6c216680893f9fffc5", + "sha256_in_prefix": "0737a80b939aafcf3d8a1bf60b63e781979c749337d02b6c216680893f9fffc5", + "size_in_bytes": 821 + }, + { + "_path": "lib/python3.12/types.py", + "path_type": "hardlink", + "sha256": "345474ef027a1273f353da9bdc1f7c18f65335e72e681bcc0376774cc51f2405", + "sha256_in_prefix": "345474ef027a1273f353da9bdc1f7c18f65335e72e681bcc0376774cc51f2405", + "size_in_bytes": 10993 + }, + { + "_path": "lib/python3.12/typing.py", + "path_type": "hardlink", + "sha256": "c45d935c17234b1d6ae42d2d5499d3e03b4e2548fae0c4fce15477e23502214d", + "sha256_in_prefix": "c45d935c17234b1d6ae42d2d5499d3e03b4e2548fae0c4fce15477e23502214d", + "size_in_bytes": 117428 + }, + { + "_path": "lib/python3.12/unittest/__init__.py", + "path_type": "hardlink", + "sha256": "32ed48385c0377bc2900a76e9a6acc3705aeef402c72de8554b3c637420506f0", + "sha256_in_prefix": "32ed48385c0377bc2900a76e9a6acc3705aeef402c72de8554b3c637420506f0", + "size_in_bytes": 3487 + }, + { + "_path": "lib/python3.12/unittest/__main__.py", + "path_type": "hardlink", + "sha256": "ff6b9a100d32001715b40d61bc4d613623b139edb1fdc3566427b83c331caae3", + "sha256_in_prefix": "ff6b9a100d32001715b40d61bc4d613623b139edb1fdc3566427b83c331caae3", + "size_in_bytes": 472 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "641de2ef43249fcedf77aaac02d0631f120f294bb6b0f2c969f65f13b3033a92", + "sha256_in_prefix": "641de2ef43249fcedf77aaac02d0631f120f294bb6b0f2c969f65f13b3033a92", + "size_in_bytes": 3427 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "583501e5a21bea5949d8f36d87f7899c6c58dc8cb1f177b946e30d1275efa2c0", + "sha256_in_prefix": "583501e5a21bea5949d8f36d87f7899c6c58dc8cb1f177b946e30d1275efa2c0", + "size_in_bytes": 611 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/_log.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8af3b1d45d2eaadf22469f95a437a6f3279e2b03e23322c4b3ed1c1c0a20c8db", + "sha256_in_prefix": "8af3b1d45d2eaadf22469f95a437a6f3279e2b03e23322c4b3ed1c1c0a20c8db", + "size_in_bytes": 4671 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/async_case.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a1fda2da018425d113ac74adca1705099f073c7c5e8d752604d954645a0d308e", + "sha256_in_prefix": "a1fda2da018425d113ac74adca1705099f073c7c5e8d752604d954645a0d308e", + "size_in_bytes": 6368 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/case.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "87eae8bb37428c32d99a5c00adb996edb394b727976adce55df5b7c9fd5822d2", + "sha256_in_prefix": "87eae8bb37428c32d99a5c00adb996edb394b727976adce55df5b7c9fd5822d2", + "size_in_bytes": 69823 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/loader.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1ed29d4e29c254884b5989285781806be595547fbd6e0650810f14896d91593f", + "sha256_in_prefix": "1ed29d4e29c254884b5989285781806be595547fbd6e0650810f14896d91593f", + "size_in_bytes": 23940 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/main.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "56169a68a62d44078fd6b812e78691ea1edc7ffcbd3e8c97172d64fd4c8cad4f", + "sha256_in_prefix": "56169a68a62d44078fd6b812e78691ea1edc7ffcbd3e8c97172d64fd4c8cad4f", + "size_in_bytes": 13560 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/mock.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "10c8a4362e0c865d75583ad1579f132b1e4665c4b51df71a6b52f2bb38875728", + "sha256_in_prefix": "10c8a4362e0c865d75583ad1579f132b1e4665c4b51df71a6b52f2bb38875728", + "size_in_bytes": 117653 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/result.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e40752311df864668152546c69987fbd77b2e451c05d656b02e1424551e4717d", + "sha256_in_prefix": "e40752311df864668152546c69987fbd77b2e451c05d656b02e1424551e4717d", + "size_in_bytes": 12738 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/runner.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d28cd7820f558a80588bad7ea87f45b9fb7e72735f5469645fc8c4f3942610be", + "sha256_in_prefix": "d28cd7820f558a80588bad7ea87f45b9fb7e72735f5469645fc8c4f3942610be", + "size_in_bytes": 16482 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/signals.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "28afd4df515de74b2040c63584483da0cc1ca41498c8d7a9de1aaf1576013fb6", + "sha256_in_prefix": "28afd4df515de74b2040c63584483da0cc1ca41498c8d7a9de1aaf1576013fb6", + "size_in_bytes": 3608 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/suite.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "eb5b4f5298ffcac67b69bb43d179378790d9d901abfabb8fd5c7a274fdd17155", + "sha256_in_prefix": "eb5b4f5298ffcac67b69bb43d179378790d9d901abfabb8fd5c7a274fdd17155", + "size_in_bytes": 15457 + }, + { + "_path": "lib/python3.12/unittest/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ddec6fc4b376ca2877a98bfd560f069f470b9b501d75ef991f9acf121b7c6863", + "sha256_in_prefix": "ddec6fc4b376ca2877a98bfd560f069f470b9b501d75ef991f9acf121b7c6863", + "size_in_bytes": 7286 + }, + { + "_path": "lib/python3.12/unittest/_log.py", + "path_type": "hardlink", + "sha256": "905672317ab26c656c600defce25d477728068f597f00a7f94e22e8128c323b9", + "sha256_in_prefix": "905672317ab26c656c600defce25d477728068f597f00a7f94e22e8128c323b9", + "size_in_bytes": 2746 + }, + { + "_path": "lib/python3.12/unittest/async_case.py", + "path_type": "hardlink", + "sha256": "b389b976f622c28223105998bf0be011f2b8c48eb33d2f1133e41e562867ee31", + "sha256_in_prefix": "b389b976f622c28223105998bf0be011f2b8c48eb33d2f1133e41e562867ee31", + "size_in_bytes": 5465 + }, + { + "_path": "lib/python3.12/unittest/case.py", + "path_type": "hardlink", + "sha256": "45bac6d80a4fc3a0dea8340a80681e30b263f017b4a5002cb8f489a632e0f987", + "sha256_in_prefix": "45bac6d80a4fc3a0dea8340a80681e30b263f017b4a5002cb8f489a632e0f987", + "size_in_bytes": 57531 + }, + { + "_path": "lib/python3.12/unittest/loader.py", + "path_type": "hardlink", + "sha256": "b7d18839241a4339d4913e73867c639e2a7dd20345f53c9fb30be5c639b20513", + "sha256_in_prefix": "b7d18839241a4339d4913e73867c639e2a7dd20345f53c9fb30be5c639b20513", + "size_in_bytes": 21010 + }, + { + "_path": "lib/python3.12/unittest/main.py", + "path_type": "hardlink", + "sha256": "db58280574389c0d6cba9559cc51e1787f5b418c4e85d354aa55ca43335c487a", + "sha256_in_prefix": "db58280574389c0d6cba9559cc51e1787f5b418c4e85d354aa55ca43335c487a", + "size_in_bytes": 11991 + }, + { + "_path": "lib/python3.12/unittest/mock.py", + "path_type": "hardlink", + "sha256": "9b7fb2946f5b9a9db9b80247d235e396abc1654fde898f2c2a215503f45a8145", + "sha256_in_prefix": "9b7fb2946f5b9a9db9b80247d235e396abc1654fde898f2c2a215503f45a8145", + "size_in_bytes": 104961 + }, + { + "_path": "lib/python3.12/unittest/result.py", + "path_type": "hardlink", + "sha256": "5db286bdd3821d64150377e554d7edbdd58db7bb8b950772f977e9ec1d535617", + "sha256_in_prefix": "5db286bdd3821d64150377e554d7edbdd58db7bb8b950772f977e9ec1d535617", + "size_in_bytes": 9130 + }, + { + "_path": "lib/python3.12/unittest/runner.py", + "path_type": "hardlink", + "sha256": "76d9beb9c21d0d367a1b040a921ad43f90b7971fcc8cacfccd6f9760bedf1ce2", + "sha256_in_prefix": "76d9beb9c21d0d367a1b040a921ad43f90b7971fcc8cacfccd6f9760bedf1ce2", + "size_in_bytes": 10368 + }, + { + "_path": "lib/python3.12/unittest/signals.py", + "path_type": "hardlink", + "sha256": "f8286e818ca56e10e03745bc056cdfd31147678f9a1dc8cb6b0fe96ef9a4362a", + "sha256_in_prefix": "f8286e818ca56e10e03745bc056cdfd31147678f9a1dc8cb6b0fe96ef9a4362a", + "size_in_bytes": 2403 + }, + { + "_path": "lib/python3.12/unittest/suite.py", + "path_type": "hardlink", + "sha256": "ed2da92bc9f97c53403ee2d3d12cc53b16a96e85d596ebc887b5a93458f3f6bc", + "sha256_in_prefix": "ed2da92bc9f97c53403ee2d3d12cc53b16a96e85d596ebc887b5a93458f3f6bc", + "size_in_bytes": 13512 + }, + { + "_path": "lib/python3.12/unittest/util.py", + "path_type": "hardlink", + "sha256": "fdcc640c3505d16deab9c32eae7c3f5f67c3b5e81c563dc6698fa7fcf403854d", + "sha256_in_prefix": "fdcc640c3505d16deab9c32eae7c3f5f67c3b5e81c563dc6698fa7fcf403854d", + "size_in_bytes": 5215 + }, + { + "_path": "lib/python3.12/urllib/__init__.py", + "path_type": "hardlink", + "sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "sha256_in_prefix": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "size_in_bytes": 0 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b79c7ca2655960e5211e8907c694b5bc526152b40f48b3ba0b04227ee5c61592", + "sha256_in_prefix": "b79c7ca2655960e5211e8907c694b5bc526152b40f48b3ba0b04227ee5c61592", + "size_in_bytes": 130 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/error.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5f157c9f3da8015d0f23f383fe72f6eb2a967148dea286ffb9aba008217c73a3", + "sha256_in_prefix": "5f157c9f3da8015d0f23f383fe72f6eb2a967148dea286ffb9aba008217c73a3", + "size_in_bytes": 3643 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/parse.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5d624a611f0d0b8822b33bf65f3289805336068b3671054b519bf01384523e98", + "sha256_in_prefix": "5d624a611f0d0b8822b33bf65f3289805336068b3671054b519bf01384523e98", + "size_in_bytes": 50089 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/request.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "70725ba71d0b7c37cfa3fec81f23e4725e16a38ba63c9fed5dc5a5715b860c68", + "sha256_in_prefix": "70725ba71d0b7c37cfa3fec81f23e4725e16a38ba63c9fed5dc5a5715b860c68", + "size_in_bytes": 115164 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/response.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e63bcd21d35d4c30516e9d9b396ac73b52bc0ebb3bd85dd4661725fe43a30391", + "sha256_in_prefix": "e63bcd21d35d4c30516e9d9b396ac73b52bc0ebb3bd85dd4661725fe43a30391", + "size_in_bytes": 4409 + }, + { + "_path": "lib/python3.12/urllib/__pycache__/robotparser.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5d63ed8e6c521787decbf0a23dbf7fab871764984c9c5dbf6dd6c427f18f0030", + "sha256_in_prefix": "5d63ed8e6c521787decbf0a23dbf7fab871764984c9c5dbf6dd6c427f18f0030", + "size_in_bytes": 12291 + }, + { + "_path": "lib/python3.12/urllib/error.py", + "path_type": "hardlink", + "sha256": "d12b3cc66af3f42a8ebe63e1c91d24f92c6237b6a93a3702938dffabd812d77b", + "sha256_in_prefix": "d12b3cc66af3f42a8ebe63e1c91d24f92c6237b6a93a3702938dffabd812d77b", + "size_in_bytes": 2415 + }, + { + "_path": "lib/python3.12/urllib/parse.py", + "path_type": "hardlink", + "sha256": "19db1c75711a43c7c11bcf8962586dfdd1f6c1c6ee759c3018d866cfb87380ba", + "sha256_in_prefix": "19db1c75711a43c7c11bcf8962586dfdd1f6c1c6ee759c3018d866cfb87380ba", + "size_in_bytes": 44923 + }, + { + "_path": "lib/python3.12/urllib/request.py", + "path_type": "hardlink", + "sha256": "94897f6f53f96839637ec3637318a51176b0076907099de0ade84f9338514318", + "sha256_in_prefix": "94897f6f53f96839637ec3637318a51176b0076907099de0ade84f9338514318", + "size_in_bytes": 102804 + }, + { + "_path": "lib/python3.12/urllib/response.py", + "path_type": "hardlink", + "sha256": "7e6c3b6d7a95f0d74f5968f51a87adae8a51bf42390cdfec98c7a99203e7bb76", + "sha256_in_prefix": "7e6c3b6d7a95f0d74f5968f51a87adae8a51bf42390cdfec98c7a99203e7bb76", + "size_in_bytes": 2361 + }, + { + "_path": "lib/python3.12/urllib/robotparser.py", + "path_type": "hardlink", + "sha256": "389b811835f9a3ba72b192c3487b0266fa31f6e571b7a83ceb2a34792dc0d9fc", + "sha256_in_prefix": "389b811835f9a3ba72b192c3487b0266fa31f6e571b7a83ceb2a34792dc0d9fc", + "size_in_bytes": 9424 + }, + { + "_path": "lib/python3.12/uu.py", + "path_type": "hardlink", + "sha256": "dd1f5be33fb25a1b0832891ea07db4a4a2ae41b466e37e24e204604fdc6d18cf", + "sha256_in_prefix": "dd1f5be33fb25a1b0832891ea07db4a4a2ae41b466e37e24e204604fdc6d18cf", + "size_in_bytes": 7365 + }, + { + "_path": "lib/python3.12/uuid.py", + "path_type": "hardlink", + "sha256": "fe357bff7241e9fd6f86ee81567fd20aeec2e17460428ea9b7924bebf57301fc", + "sha256_in_prefix": "fe357bff7241e9fd6f86ee81567fd20aeec2e17460428ea9b7924bebf57301fc", + "size_in_bytes": 29656 + }, + { + "_path": "lib/python3.12/venv/__init__.py", + "path_type": "hardlink", + "sha256": "ce2e0f80e0b3fa49715e4263d95193dc2371a58c75bdc0f82b7d461bd7dc803b", + "sha256_in_prefix": "ce2e0f80e0b3fa49715e4263d95193dc2371a58c75bdc0f82b7d461bd7dc803b", + "size_in_bytes": 24618 + }, + { + "_path": "lib/python3.12/venv/__main__.py", + "path_type": "hardlink", + "sha256": "722537c68c0622f8293d39bb6ab1288f3637d8dc45d6f9aae96e49af8145ca36", + "sha256_in_prefix": "722537c68c0622f8293d39bb6ab1288f3637d8dc45d6f9aae96e49af8145ca36", + "size_in_bytes": 145 + }, + { + "_path": "lib/python3.12/venv/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e00b0e2c6677dbb1fb45e7d0178aa66ee1a016384cbca2582f70de35c9caaad1", + "sha256_in_prefix": "e00b0e2c6677dbb1fb45e7d0178aa66ee1a016384cbca2582f70de35c9caaad1", + "size_in_bytes": 28914 + }, + { + "_path": "lib/python3.12/venv/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "e8ca718632127eabc555e972223ee20e9a4b5c1604a56a84b091062f13234f80", + "sha256_in_prefix": "e8ca718632127eabc555e972223ee20e9a4b5c1604a56a84b091062f13234f80", + "size_in_bytes": 475 + }, + { + "_path": "lib/python3.12/venv/scripts/common/Activate.ps1", + "path_type": "hardlink", + "sha256": "3795a060dea7d621320d6d841deb37591fadf7f5592c5cb2286f9867af0e91df", + "sha256_in_prefix": "3795a060dea7d621320d6d841deb37591fadf7f5592c5cb2286f9867af0e91df", + "size_in_bytes": 9033 + }, + { + "_path": "lib/python3.12/venv/scripts/common/activate", + "path_type": "hardlink", + "sha256": "76b3d2a782a6b9871ba5b0fe6096a7e315b06c9095be1618ebf5087e9ba1f73b", + "sha256_in_prefix": "76b3d2a782a6b9871ba5b0fe6096a7e315b06c9095be1618ebf5087e9ba1f73b", + "size_in_bytes": 2042 + }, + { + "_path": "lib/python3.12/venv/scripts/posix/activate.csh", + "path_type": "hardlink", + "sha256": "cdd8a01bb9c221836bfa4470d52c9fb5acbce2de6454df71efdae3adc342441e", + "sha256_in_prefix": "cdd8a01bb9c221836bfa4470d52c9fb5acbce2de6454df71efdae3adc342441e", + "size_in_bytes": 936 + }, + { + "_path": "lib/python3.12/venv/scripts/posix/activate.fish", + "path_type": "hardlink", + "sha256": "a100a3f99289828886d7a4bfab657751aea2b4313ffcb5b95bc643d63469448d", + "sha256_in_prefix": "a100a3f99289828886d7a4bfab657751aea2b4313ffcb5b95bc643d63469448d", + "size_in_bytes": 2215 + }, + { + "_path": "lib/python3.12/warnings.py", + "path_type": "hardlink", + "sha256": "8eb1bb88d0beb82ebecfe7ee5cf54ed9b77b4a7acee1989e392a65de42017c49", + "sha256_in_prefix": "8eb1bb88d0beb82ebecfe7ee5cf54ed9b77b4a7acee1989e392a65de42017c49", + "size_in_bytes": 21760 + }, + { + "_path": "lib/python3.12/wave.py", + "path_type": "hardlink", + "sha256": "0330428ea9e45fee49acc4ae5bdca4c235f4236c51dab09f30442ccafa25c1f8", + "sha256_in_prefix": "0330428ea9e45fee49acc4ae5bdca4c235f4236c51dab09f30442ccafa25c1f8", + "size_in_bytes": 22769 + }, + { + "_path": "lib/python3.12/weakref.py", + "path_type": "hardlink", + "sha256": "56f8d313fb74019e53eb9287400702fbce788b7fe30e097b0b6e06296f3f080c", + "sha256_in_prefix": "56f8d313fb74019e53eb9287400702fbce788b7fe30e097b0b6e06296f3f080c", + "size_in_bytes": 21513 + }, + { + "_path": "lib/python3.12/webbrowser.py", + "path_type": "hardlink", + "sha256": "f83a36818ef51b0e2efbc3937187dc5f24062908a0e18c8ceb228139dad98348", + "sha256_in_prefix": "f83a36818ef51b0e2efbc3937187dc5f24062908a0e18c8ceb228139dad98348", + "size_in_bytes": 23628 + }, + { + "_path": "lib/python3.12/wsgiref/__init__.py", + "path_type": "hardlink", + "sha256": "c30e144025a63d267778d92f2f066fa592b476e789d888f79b96c059bf0bef60", + "sha256_in_prefix": "c30e144025a63d267778d92f2f066fa592b476e789d888f79b96c059bf0bef60", + "size_in_bytes": 657 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9c99c744d10fc70dbc37dceb00360d321cc26123f0697becf9c6087b2c5a23f8", + "sha256_in_prefix": "9c99c744d10fc70dbc37dceb00360d321cc26123f0697becf9c6087b2c5a23f8", + "size_in_bytes": 801 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/handlers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f4facb532fb1d67f6c64a4db9f0bb0699909093adcde1e7f4b9ad6ddda7fe9d4", + "sha256_in_prefix": "f4facb532fb1d67f6c64a4db9f0bb0699909093adcde1e7f4b9ad6ddda7fe9d4", + "size_in_bytes": 23601 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/headers.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "cc7728bdd23f57fe0d7c71f1bb38379d82b54ca82030f53f1f6bd3b33dc0baf9", + "sha256_in_prefix": "cc7728bdd23f57fe0d7c71f1bb38379d82b54ca82030f53f1f6bd3b33dc0baf9", + "size_in_bytes": 9613 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/simple_server.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "3e7f77cdccc5e5a2b7bd31b7714f903389e8806e2409a8d4185559a3fd963d21", + "sha256_in_prefix": "3e7f77cdccc5e5a2b7bd31b7714f903389e8806e2409a8d4185559a3fd963d21", + "size_in_bytes": 8170 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/types.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "378faea0ab82cb4e87b0605899f44379d8b4024bfc69b75973b1fa84b4af8543", + "sha256_in_prefix": "378faea0ab82cb4e87b0605899f44379d8b4024bfc69b75973b1fa84b4af8543", + "size_in_bytes": 3654 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/util.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d86098bdeac8daa3689c21c13654576dea584ebbe5399449cf9e916c1af24abb", + "sha256_in_prefix": "d86098bdeac8daa3689c21c13654576dea584ebbe5399449cf9e916c1af24abb", + "size_in_bytes": 6797 + }, + { + "_path": "lib/python3.12/wsgiref/__pycache__/validate.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "ce90e84ea826b522b0d74926a24fa55134f1098ebbf055bee15f892567d6d3e2", + "sha256_in_prefix": "ce90e84ea826b522b0d74926a24fa55134f1098ebbf055bee15f892567d6d3e2", + "size_in_bytes": 20180 + }, + { + "_path": "lib/python3.12/wsgiref/handlers.py", + "path_type": "hardlink", + "sha256": "b4ed08869ab79d7c17065993875cdc6eb1b2a0b3645b74325bc0aab44e97cfc5", + "sha256_in_prefix": "b4ed08869ab79d7c17065993875cdc6eb1b2a0b3645b74325bc0aab44e97cfc5", + "size_in_bytes": 21664 + }, + { + "_path": "lib/python3.12/wsgiref/headers.py", + "path_type": "hardlink", + "sha256": "0fbf95a47d8e4c0d831fd52312ec43076cbf503c190269876f170a5cf5585fb9", + "sha256_in_prefix": "0fbf95a47d8e4c0d831fd52312ec43076cbf503c190269876f170a5cf5585fb9", + "size_in_bytes": 6766 + }, + { + "_path": "lib/python3.12/wsgiref/simple_server.py", + "path_type": "hardlink", + "sha256": "d435cad48b5f63c0356e1ac70755e6e35eb94b02f9844b813e5762199110bc2b", + "sha256_in_prefix": "d435cad48b5f63c0356e1ac70755e6e35eb94b02f9844b813e5762199110bc2b", + "size_in_bytes": 5171 + }, + { + "_path": "lib/python3.12/wsgiref/types.py", + "path_type": "hardlink", + "sha256": "ba66d30ce511a88eba9b809616c51e12bf89c67972102e7d976b18557f7a6387", + "sha256_in_prefix": "ba66d30ce511a88eba9b809616c51e12bf89c67972102e7d976b18557f7a6387", + "size_in_bytes": 1717 + }, + { + "_path": "lib/python3.12/wsgiref/util.py", + "path_type": "hardlink", + "sha256": "93783cda348368538525f52a5e9a5a43a3de93caec26b6a030ecfb3aedf98b98", + "sha256_in_prefix": "93783cda348368538525f52a5e9a5a43a3de93caec26b6a030ecfb3aedf98b98", + "size_in_bytes": 5472 + }, + { + "_path": "lib/python3.12/wsgiref/validate.py", + "path_type": "hardlink", + "sha256": "4132f87dcf11a332f6ec5b051e68e59ff493dd6fdcc4f716ea72373734977a0a", + "sha256_in_prefix": "4132f87dcf11a332f6ec5b051e68e59ff493dd6fdcc4f716ea72373734977a0a", + "size_in_bytes": 15036 + }, + { + "_path": "lib/python3.12/xdrlib.py", + "path_type": "hardlink", + "sha256": "983c5e8e3090bdbeb94bf4faf841c1f8c916bcbca423863f6870a142d16a4fb8", + "sha256_in_prefix": "983c5e8e3090bdbeb94bf4faf841c1f8c916bcbca423863f6870a142d16a4fb8", + "size_in_bytes": 5942 + }, + { + "_path": "lib/python3.12/xml/__init__.py", + "path_type": "hardlink", + "sha256": "34296f728e7fe68cccb97a9f6edbf3bf3a686f44044c744fe85f207a92ed4811", + "sha256_in_prefix": "34296f728e7fe68cccb97a9f6edbf3bf3a686f44044c744fe85f207a92ed4811", + "size_in_bytes": 557 + }, + { + "_path": "lib/python3.12/xml/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b0d3b261da151318d2080019282f229cc3f994bc26fb7d1127de179f6179bde8", + "sha256_in_prefix": "b0d3b261da151318d2080019282f229cc3f994bc26fb7d1127de179f6179bde8", + "size_in_bytes": 702 + }, + { + "_path": "lib/python3.12/xml/dom/NodeFilter.py", + "path_type": "hardlink", + "sha256": "9bfacbbb64e239a75591a7260b3ed86748eeb4366e6c40f3542753e79bace9a7", + "sha256_in_prefix": "9bfacbbb64e239a75591a7260b3ed86748eeb4366e6c40f3542753e79bace9a7", + "size_in_bytes": 936 + }, + { + "_path": "lib/python3.12/xml/dom/__init__.py", + "path_type": "hardlink", + "sha256": "b415a6f3d3663c3ac332ee4a0f4213eadad9281508dc97410e258a03633b063a", + "sha256_in_prefix": "b415a6f3d3663c3ac332ee4a0f4213eadad9281508dc97410e258a03633b063a", + "size_in_bytes": 4019 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/NodeFilter.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "58ce9cd7bfac552e359b9fae5b0e4d475b6affc77f3418ca361e89364d85c6ec", + "sha256_in_prefix": "58ce9cd7bfac552e359b9fae5b0e4d475b6affc77f3418ca361e89364d85c6ec", + "size_in_bytes": 1057 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1f25a10a021f9b226801789545426fcdf99efc38abae230002213f502fcebcb9", + "sha256_in_prefix": "1f25a10a021f9b226801789545426fcdf99efc38abae230002213f502fcebcb9", + "size_in_bytes": 6187 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/domreg.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8fcdd9ea68c3a5f63fbbef4ab9e788d7283295e7738498fa9ce065f19a4aa0eb", + "sha256_in_prefix": "8fcdd9ea68c3a5f63fbbef4ab9e788d7283295e7738498fa9ce065f19a4aa0eb", + "size_in_bytes": 3825 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/expatbuilder.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "70820fcfffddb4246ed3e086cbc20a0fe29c72ac806162d19f1fd2048b5b536d", + "sha256_in_prefix": "70820fcfffddb4246ed3e086cbc20a0fe29c72ac806162d19f1fd2048b5b536d", + "size_in_bytes": 45426 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/minicompat.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "0a964fd3b134ded9b42b8f7636309a0474c95093f555c3d76986161f46daea5c", + "sha256_in_prefix": "0a964fd3b134ded9b42b8f7636309a0474c95093f555c3d76986161f46daea5c", + "size_in_bytes": 3376 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/minidom.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "51675368acfed730fb6088ef3fe7ad17d115862d473693eb8b7cd6ae311c6804", + "sha256_in_prefix": "51675368acfed730fb6088ef3fe7ad17d115862d473693eb8b7cd6ae311c6804", + "size_in_bytes": 92464 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/pulldom.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a7a0bef88a77e6efb1ecd7e42d0b0608b108eb3e8e473e88eb963fef722d2d85", + "sha256_in_prefix": "a7a0bef88a77e6efb1ecd7e42d0b0608b108eb3e8e473e88eb963fef722d2d85", + "size_in_bytes": 17454 + }, + { + "_path": "lib/python3.12/xml/dom/__pycache__/xmlbuilder.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "25f0a3c8c82a5b745acb75806b0901261c652394cda44226c9a393c03386ceff", + "sha256_in_prefix": "25f0a3c8c82a5b745acb75806b0901261c652394cda44226c9a393c03386ceff", + "size_in_bytes": 17003 + }, + { + "_path": "lib/python3.12/xml/dom/domreg.py", + "path_type": "hardlink", + "sha256": "826b02a803930834b96b1086cbee7db1d21c684f65dd3073706dc7bb5ba1a3e8", + "sha256_in_prefix": "826b02a803930834b96b1086cbee7db1d21c684f65dd3073706dc7bb5ba1a3e8", + "size_in_bytes": 3451 + }, + { + "_path": "lib/python3.12/xml/dom/expatbuilder.py", + "path_type": "hardlink", + "sha256": "80598dbc5970feaa36ea2b7549e3e76dd018fb80cf79e4a5e27e9e71af60c82c", + "sha256_in_prefix": "80598dbc5970feaa36ea2b7549e3e76dd018fb80cf79e4a5e27e9e71af60c82c", + "size_in_bytes": 35693 + }, + { + "_path": "lib/python3.12/xml/dom/minicompat.py", + "path_type": "hardlink", + "sha256": "42974c4c67803dfe80b016ff8aeea0d1e5c751703ab3aec5be765f4e534367be", + "sha256_in_prefix": "42974c4c67803dfe80b016ff8aeea0d1e5c751703ab3aec5be765f4e534367be", + "size_in_bytes": 3367 + }, + { + "_path": "lib/python3.12/xml/dom/minidom.py", + "path_type": "hardlink", + "sha256": "af4ee09b06efc54e7fe58032d8338c4bc8578094946d03a200740deab25d97cb", + "sha256_in_prefix": "af4ee09b06efc54e7fe58032d8338c4bc8578094946d03a200740deab25d97cb", + "size_in_bytes": 68140 + }, + { + "_path": "lib/python3.12/xml/dom/pulldom.py", + "path_type": "hardlink", + "sha256": "614b88673d496a360e6b10efe8d733c7c0826fb214470ff12f24a1e597699870", + "sha256_in_prefix": "614b88673d496a360e6b10efe8d733c7c0826fb214470ff12f24a1e597699870", + "size_in_bytes": 11637 + }, + { + "_path": "lib/python3.12/xml/dom/xmlbuilder.py", + "path_type": "hardlink", + "sha256": "d4f33a8f018755626b64557953a91c6bba21ff613da46f7558a2874aa5d08ebf", + "sha256_in_prefix": "d4f33a8f018755626b64557953a91c6bba21ff613da46f7558a2874aa5d08ebf", + "size_in_bytes": 12387 + }, + { + "_path": "lib/python3.12/xml/etree/ElementInclude.py", + "path_type": "hardlink", + "sha256": "97b513db52e9d8382d446e283583e3adf20aae86fb93d4764565ac08250399c0", + "sha256_in_prefix": "97b513db52e9d8382d446e283583e3adf20aae86fb93d4764565ac08250399c0", + "size_in_bytes": 6882 + }, + { + "_path": "lib/python3.12/xml/etree/ElementPath.py", + "path_type": "hardlink", + "sha256": "ae8a80a8b51567b4f0965481682705e70c73dd6bfa145283f630d6833f1b4975", + "sha256_in_prefix": "ae8a80a8b51567b4f0965481682705e70c73dd6bfa145283f630d6833f1b4975", + "size_in_bytes": 13997 + }, + { + "_path": "lib/python3.12/xml/etree/ElementTree.py", + "path_type": "hardlink", + "sha256": "ec5e469d55df6c219ed11005e00508a19e2068d12889a4cef3ac2e1f88b104bf", + "sha256_in_prefix": "ec5e469d55df6c219ed11005e00508a19e2068d12889a4cef3ac2e1f88b104bf", + "size_in_bytes": 74017 + }, + { + "_path": "lib/python3.12/xml/etree/__init__.py", + "path_type": "hardlink", + "sha256": "91950edfb196c105d93886f8af7ea3c0a79e06a6b63be3e5a4ea09804e8672a6", + "sha256_in_prefix": "91950edfb196c105d93886f8af7ea3c0a79e06a6b63be3e5a4ea09804e8672a6", + "size_in_bytes": 1605 + }, + { + "_path": "lib/python3.12/xml/etree/__pycache__/ElementInclude.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "abd97bcba8aaa43e0c790fb2afc1f7baf85a83e37de8e0df9bdd708740cd0ce8", + "sha256_in_prefix": "abd97bcba8aaa43e0c790fb2afc1f7baf85a83e37de8e0df9bdd708740cd0ce8", + "size_in_bytes": 3992 + }, + { + "_path": "lib/python3.12/xml/etree/__pycache__/ElementPath.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b09e726e15f72ba0f51f7e50c56ab1b14951be1caf4d36e7eed81115e7653c12", + "sha256_in_prefix": "b09e726e15f72ba0f51f7e50c56ab1b14951be1caf4d36e7eed81115e7653c12", + "size_in_bytes": 14924 + }, + { + "_path": "lib/python3.12/xml/etree/__pycache__/ElementTree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a1dd832a699aefb9851b81fff05ba829d7b74748a259b31244b31b48027cd874", + "sha256_in_prefix": "a1dd832a699aefb9851b81fff05ba829d7b74748a259b31244b31b48027cd874", + "size_in_bytes": 82384 + }, + { + "_path": "lib/python3.12/xml/etree/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "74cda49db8fdda9138361404298bb2e8ad9d5bc9165ebcd60c871c655646cad5", + "sha256_in_prefix": "74cda49db8fdda9138361404298bb2e8ad9d5bc9165ebcd60c871c655646cad5", + "size_in_bytes": 133 + }, + { + "_path": "lib/python3.12/xml/etree/__pycache__/cElementTree.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "9c146849a2bafc0ab6c6415acd2d11714df03200037ffe0818c9e7a9729a352d", + "sha256_in_prefix": "9c146849a2bafc0ab6c6415acd2d11714df03200037ffe0818c9e7a9729a352d", + "size_in_bytes": 182 + }, + { + "_path": "lib/python3.12/xml/etree/cElementTree.py", + "path_type": "hardlink", + "sha256": "d0f57acab07fe4f9c116c3392d85946bac8e78608f409cea70005f16ea019b57", + "sha256_in_prefix": "d0f57acab07fe4f9c116c3392d85946bac8e78608f409cea70005f16ea019b57", + "size_in_bytes": 82 + }, + { + "_path": "lib/python3.12/xml/parsers/__init__.py", + "path_type": "hardlink", + "sha256": "b88497adc30d5d5eda7789c25a2206ee9270c932d584d7ac42680325651da45c", + "sha256_in_prefix": "b88497adc30d5d5eda7789c25a2206ee9270c932d584d7ac42680325651da45c", + "size_in_bytes": 167 + }, + { + "_path": "lib/python3.12/xml/parsers/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b73087cc56bc9b304a4c298d43fe40a82cd86ab97f599ec79131faccc08d085b", + "sha256_in_prefix": "b73087cc56bc9b304a4c298d43fe40a82cd86ab97f599ec79131faccc08d085b", + "size_in_bytes": 312 + }, + { + "_path": "lib/python3.12/xml/parsers/__pycache__/expat.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "1d2d3fe1e67937a4783fab2ba29c1856da2d3aedd906d5c8554de2824dd0792a", + "sha256_in_prefix": "1d2d3fe1e67937a4783fab2ba29c1856da2d3aedd906d5c8554de2824dd0792a", + "size_in_bytes": 411 + }, + { + "_path": "lib/python3.12/xml/parsers/expat.py", + "path_type": "hardlink", + "sha256": "64e1947747c2874117a7458bba1f07c86620cc0ed9a4a4116d262878e4a2aa09", + "sha256_in_prefix": "64e1947747c2874117a7458bba1f07c86620cc0ed9a4a4116d262878e4a2aa09", + "size_in_bytes": 248 + }, + { + "_path": "lib/python3.12/xml/sax/__init__.py", + "path_type": "hardlink", + "sha256": "2f949d27b9eda6284482b43f4c202830fb35ea94f4101d70452119d3210bdbe0", + "sha256_in_prefix": "2f949d27b9eda6284482b43f4c202830fb35ea94f4101d70452119d3210bdbe0", + "size_in_bytes": 3238 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "a031fdc00f72832f52c655dbc4890b0b254311db696b739674c5e580d4b94a6e", + "sha256_in_prefix": "a031fdc00f72832f52c655dbc4890b0b254311db696b739674c5e580d4b94a6e", + "size_in_bytes": 3785 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/_exceptions.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bbda9e009267547038f09ef5e2bf0c629ed97741ca98b906eeef93632a805048", + "sha256_in_prefix": "bbda9e009267547038f09ef5e2bf0c629ed97741ca98b906eeef93632a805048", + "size_in_bytes": 6212 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/expatreader.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f52423b5621b5aadce7a58891a3924da07b1106559316025d7903a69971c10d0", + "sha256_in_prefix": "f52423b5621b5aadce7a58891a3924da07b1106559316025d7903a69971c10d0", + "size_in_bytes": 21581 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/handler.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "6c3a4018d5adcb4fe8f56eedfe345eeb16c4c7affdb098bbfd001d30ecb27802", + "sha256_in_prefix": "6c3a4018d5adcb4fe8f56eedfe345eeb16c4c7affdb098bbfd001d30ecb27802", + "size_in_bytes": 14884 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/saxutils.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "f97796354a11e2c56a375e9e608dab1d064d503f77e617523a6fe944aff721cd", + "sha256_in_prefix": "f97796354a11e2c56a375e9e608dab1d064d503f77e617523a6fe944aff721cd", + "size_in_bytes": 19604 + }, + { + "_path": "lib/python3.12/xml/sax/__pycache__/xmlreader.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "b18d4b1bf808c94726601d222c539153b04f8db1270e04c7f56bc155addb6c0b", + "sha256_in_prefix": "b18d4b1bf808c94726601d222c539153b04f8db1270e04c7f56bc155addb6c0b", + "size_in_bytes": 19550 + }, + { + "_path": "lib/python3.12/xml/sax/_exceptions.py", + "path_type": "hardlink", + "sha256": "26564d5742496196d17a4a0ee135d28f652ec81742cf2fa4bff83e64323578ac", + "sha256_in_prefix": "26564d5742496196d17a4a0ee135d28f652ec81742cf2fa4bff83e64323578ac", + "size_in_bytes": 4699 + }, + { + "_path": "lib/python3.12/xml/sax/expatreader.py", + "path_type": "hardlink", + "sha256": "5b6750ae591cffa303b20f092b13409a92df5ee1c403adac08dd5320eafee0be", + "sha256_in_prefix": "5b6750ae591cffa303b20f092b13409a92df5ee1c403adac08dd5320eafee0be", + "size_in_bytes": 16034 + }, + { + "_path": "lib/python3.12/xml/sax/handler.py", + "path_type": "hardlink", + "sha256": "64c7aae49f1dd382a7b9012610307bfa1d43a14a5dc09a5c8da30903f6805c3d", + "sha256_in_prefix": "64c7aae49f1dd382a7b9012610307bfa1d43a14a5dc09a5c8da30903f6805c3d", + "size_in_bytes": 15617 + }, + { + "_path": "lib/python3.12/xml/sax/saxutils.py", + "path_type": "hardlink", + "sha256": "3fe2cdb6386e0c4d42d37c657bbecb78b69c57aedb1610dbd8bf4043944130ab", + "sha256_in_prefix": "3fe2cdb6386e0c4d42d37c657bbecb78b69c57aedb1610dbd8bf4043944130ab", + "size_in_bytes": 12255 + }, + { + "_path": "lib/python3.12/xml/sax/xmlreader.py", + "path_type": "hardlink", + "sha256": "0962c8d64ac8b03148d4ae62a531f544c4fd1be2116c6f4a53b480cff463dbba", + "sha256_in_prefix": "0962c8d64ac8b03148d4ae62a531f544c4fd1be2116c6f4a53b480cff463dbba", + "size_in_bytes": 12624 + }, + { + "_path": "lib/python3.12/xmlrpc/__init__.py", + "path_type": "hardlink", + "sha256": "87ad5c8954dd56fbbca04517bf87477ff4dce575170c7dd1281d7ef1f4214ac8", + "sha256_in_prefix": "87ad5c8954dd56fbbca04517bf87477ff4dce575170c7dd1281d7ef1f4214ac8", + "size_in_bytes": 38 + }, + { + "_path": "lib/python3.12/xmlrpc/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "bc350be99ec6c2abef605b4963faa35cb3cec056d6144a4dc3d61010abd0f6ad", + "sha256_in_prefix": "bc350be99ec6c2abef605b4963faa35cb3cec056d6144a4dc3d61010abd0f6ad", + "size_in_bytes": 130 + }, + { + "_path": "lib/python3.12/xmlrpc/__pycache__/client.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "8a0dfcc3ad7c4bd419882eeaf2aa12b3f5ff496901111c890e125ec545d6f7ac", + "sha256_in_prefix": "8a0dfcc3ad7c4bd419882eeaf2aa12b3f5ff496901111c890e125ec545d6f7ac", + "size_in_bytes": 51585 + }, + { + "_path": "lib/python3.12/xmlrpc/__pycache__/server.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "98b74c8c9d256753158a2854abd2da394926f85362b89275cb32696b56da8ef5", + "sha256_in_prefix": "98b74c8c9d256753158a2854abd2da394926f85362b89275cb32696b56da8ef5", + "size_in_bytes": 42801 + }, + { + "_path": "lib/python3.12/xmlrpc/client.py", + "path_type": "hardlink", + "sha256": "c77e7072ab9aaab6c6f16f89f2e7d528183b816df5d9f80e490f773ab45fe238", + "sha256_in_prefix": "c77e7072ab9aaab6c6f16f89f2e7d528183b816df5d9f80e490f773ab45fe238", + "size_in_bytes": 49331 + }, + { + "_path": "lib/python3.12/xmlrpc/server.py", + "path_type": "hardlink", + "sha256": "6781c25a6224b8bafe13050d26456c8a8b480c96e7974bcf60d4deb0c4ad454c", + "sha256_in_prefix": "6781c25a6224b8bafe13050d26456c8a8b480c96e7974bcf60d4deb0c4ad454c", + "size_in_bytes": 36822 + }, + { + "_path": "lib/python3.12/zipapp.py", + "path_type": "hardlink", + "sha256": "56e098b62cef6c39944bb898326dd920b70be461fe644139e2b699977d2997a1", + "sha256_in_prefix": "56e098b62cef6c39944bb898326dd920b70be461fe644139e2b699977d2997a1", + "size_in_bytes": 7543 + }, + { + "_path": "lib/python3.12/zipfile/__init__.py", + "path_type": "hardlink", + "sha256": "eb37f9fb0bb23795bbb6a310530a99e5a99dff5acc78e6f2cc17fbefc8d7a311", + "sha256_in_prefix": "eb37f9fb0bb23795bbb6a310530a99e5a99dff5acc78e6f2cc17fbefc8d7a311", + "size_in_bytes": 87706 + }, + { + "_path": "lib/python3.12/zipfile/__main__.py", + "path_type": "hardlink", + "sha256": "e418cdbb27adf0063e3cec28179ac6b7bdb6ac743bb49d157f450551fcf38be2", + "sha256_in_prefix": "e418cdbb27adf0063e3cec28179ac6b7bdb6ac743bb49d157f450551fcf38be2", + "size_in_bytes": 58 + }, + { + "_path": "lib/python3.12/zipfile/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "971b5dcfc7e7b42f54d7363bd5a2871288ab588affb084133fe8342850f6d550", + "sha256_in_prefix": "971b5dcfc7e7b42f54d7363bd5a2871288ab588affb084133fe8342850f6d550", + "size_in_bytes": 99416 + }, + { + "_path": "lib/python3.12/zipfile/__pycache__/__main__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "186e43a9392342922c156069c72acb48017a316bd6f78170b6e78c046c627482", + "sha256_in_prefix": "186e43a9392342922c156069c72acb48017a316bd6f78170b6e78c046c627482", + "size_in_bytes": 227 + }, + { + "_path": "lib/python3.12/zipfile/_path/__init__.py", + "path_type": "hardlink", + "sha256": "3db24a524a31bbb4ce64f23a931dc47403058bbb90e54c4869a17b1245474165", + "sha256_in_prefix": "3db24a524a31bbb4ce64f23a931dc47403058bbb90e54c4869a17b1245474165", + "size_in_bytes": 10409 + }, + { + "_path": "lib/python3.12/zipfile/_path/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4ab601283b04e11eef605b1f36bd073653ac0a360d1311b2724a84ef857d908b", + "sha256_in_prefix": "4ab601283b04e11eef605b1f36bd073653ac0a360d1311b2724a84ef857d908b", + "size_in_bytes": 18442 + }, + { + "_path": "lib/python3.12/zipfile/_path/__pycache__/glob.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "53c27ac2dbc521db3e78f0a98f7e4f758ded3691764979b0cfd110fbc2894ed3", + "sha256_in_prefix": "53c27ac2dbc521db3e78f0a98f7e4f758ded3691764979b0cfd110fbc2894ed3", + "size_in_bytes": 1527 + }, + { + "_path": "lib/python3.12/zipfile/_path/glob.py", + "path_type": "hardlink", + "sha256": "7020d375669c257879b5b1278e7649ef51cbfe16e9aef967e5aca51cca11f893", + "sha256_in_prefix": "7020d375669c257879b5b1278e7649ef51cbfe16e9aef967e5aca51cca11f893", + "size_in_bytes": 893 + }, + { + "_path": "lib/python3.12/zipimport.py", + "path_type": "hardlink", + "sha256": "4ac94d92219c2e1c0d67ad3fff3753ec3a3756af62a36a2f696f02cd12d518f0", + "sha256_in_prefix": "4ac94d92219c2e1c0d67ad3fff3753ec3a3756af62a36a2f696f02cd12d518f0", + "size_in_bytes": 28132 + }, + { + "_path": "lib/python3.12/zoneinfo/__init__.py", + "path_type": "hardlink", + "sha256": "ac7fb403e4371d07482ef2fda81dbcf6879484e9fc41d4be42c156d7e54c68a8", + "sha256_in_prefix": "ac7fb403e4371d07482ef2fda81dbcf6879484e9fc41d4be42c156d7e54c68a8", + "size_in_bytes": 703 + }, + { + "_path": "lib/python3.12/zoneinfo/__pycache__/__init__.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "4ff797f5558a1c270d0d627789714926db363d4fce860ea577b96a2df04e79be", + "sha256_in_prefix": "4ff797f5558a1c270d0d627789714926db363d4fce860ea577b96a2df04e79be", + "size_in_bytes": 1097 + }, + { + "_path": "lib/python3.12/zoneinfo/__pycache__/_common.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "5ed2853c6481fc0e9a1f14c69487d31ef891a2c12d8944788d7eb5008890f724", + "sha256_in_prefix": "5ed2853c6481fc0e9a1f14c69487d31ef891a2c12d8944788d7eb5008890f724", + "size_in_bytes": 5318 + }, + { + "_path": "lib/python3.12/zoneinfo/__pycache__/_tzpath.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "71e0821c9805fbd420c0536c388f8079a5c025e9334f4bc684dabf35ccaa8fed", + "sha256_in_prefix": "71e0821c9805fbd420c0536c388f8079a5c025e9334f4bc684dabf35ccaa8fed", + "size_in_bytes": 7101 + }, + { + "_path": "lib/python3.12/zoneinfo/__pycache__/_zoneinfo.cpython-312.pyc", + "path_type": "hardlink", + "sha256": "d11e0553745e5fdc01a79e597710e8cd52bbdd951910aa315d36dce9219aadf2", + "sha256_in_prefix": "d11e0553745e5fdc01a79e597710e8cd52bbdd951910aa315d36dce9219aadf2", + "size_in_bytes": 26755 + }, + { + "_path": "lib/python3.12/zoneinfo/_common.py", + "path_type": "hardlink", + "sha256": "67deaf0ba41aa4865e007297677207485a89b75629eea0ee5c472be8a3e83bf6", + "sha256_in_prefix": "67deaf0ba41aa4865e007297677207485a89b75629eea0ee5c472be8a3e83bf6", + "size_in_bytes": 5294 + }, + { + "_path": "lib/python3.12/zoneinfo/_tzpath.py", + "path_type": "hardlink", + "sha256": "5dc473af6f6ae35e5531cc9705a1e4923aa07e7d35f6b4c275b90c6a3c2591c4", + "sha256_in_prefix": "5dc473af6f6ae35e5531cc9705a1e4923aa07e7d35f6b4c275b90c6a3c2591c4", + "size_in_bytes": 5388 + }, + { + "_path": "lib/python3.12/zoneinfo/_zoneinfo.py", + "path_type": "hardlink", + "sha256": "ebb9b679519a23252eb90541003a2fdbb3f2d7bc36713fd70672baa575dcdcb6", + "sha256_in_prefix": "ebb9b679519a23252eb90541003a2fdbb3f2d7bc36713fd70672baa575dcdcb6", + "size_in_bytes": 24674 + }, + { + "_path": "share/man/man1/python3.1", + "path_type": "softlink", + "sha256": "a873f4b72c962d4081f47ab3f4a992d9de7ab19a367795c95fedd5603cb293a7", + "sha256_in_prefix": "8c2916f94cbdbe012a5e336b296e368a77bc28cae844d04edabd94562f351856", + "size_in_bytes": 20092 + }, + { + "_path": "share/man/man1/python3.12.1", + "path_type": "hardlink", + "sha256": "a873f4b72c962d4081f47ab3f4a992d9de7ab19a367795c95fedd5603cb293a7", + "sha256_in_prefix": "a873f4b72c962d4081f47ab3f4a992d9de7ab19a367795c95fedd5603cb293a7", + "size_in_bytes": 20092 + } + ] + }, + "link": { + "source": "/home/rarts/.cache/rattler/cache/pkgs/python-3.12.3-hab00c5b_0_cpython", + "type": 1 + } +} diff --git a/src/global/test_data/lockfiles/ripgrep.lock b/src/global/test_data/lockfiles/ripgrep.lock new file mode 100644 index 000000000..58467b6cc --- /dev/null +++ b/src/global/test_data/lockfiles/ripgrep.lock @@ -0,0 +1,106 @@ +version: 5 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-14.1.0-he8a937b_0.conda +packages: +- kind: conda + name: _libgcc_mutex + version: '0.1' + build: conda_forge + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + size: 2562 + timestamp: 1578324546067 +- kind: conda + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- kind: conda + name: libgcc + version: 14.1.0 + build: h77fa898_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + sha256: 10fa74b69266a2be7b96db881e18fa62cfa03082b65231e8d652e897c4b335a3 + md5: 002ef4463dd1e2b44a94a4ace468f5d2 + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 14.1.0 h77fa898_1 + - libgcc-ng ==14.1.0=*_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 846380 + timestamp: 1724801836552 +- kind: conda + name: libgcc-ng + version: 14.1.0 + build: h69a702a_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + sha256: b91f7021e14c3d5c840fbf0dc75370d6e1f7c7ff4482220940eaafb9c64613b7 + md5: 1efc0ad219877a73ef977af7dbb51f17 + depends: + - libgcc 14.1.0 h77fa898_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 52170 + timestamp: 1724801842101 +- kind: conda + name: libgomp + version: 14.1.0 + build: h77fa898_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda + sha256: c96724c8ae4ee61af7674c5d9e5a3fbcf6cd887a40ad5a52c99aa36f1d4f9680 + md5: 23c255b008c4f2ae008f81edcabaca89 + depends: + - _libgcc_mutex 0.1 conda_forge + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 460218 + timestamp: 1724801743478 +- kind: conda + name: ripgrep + version: 14.1.0 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-14.1.0-he8a937b_0.conda + sha256: 4fcf37724b87440765cb3c6cf573e99d12fc631001426a0309d132f495c3d62a + md5: 5a476f7033a8a1b9175626b5ebf86d1d + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 1683808 + timestamp: 1705520837423 diff --git a/src/global/test_data/lockfiles/ripgrep_bat.lock b/src/global/test_data/lockfiles/ripgrep_bat.lock new file mode 100644 index 000000000..db8c94dbe --- /dev/null +++ b/src/global/test_data/lockfiles/ripgrep_bat.lock @@ -0,0 +1,121 @@ +version: 5 +environments: + default: + channels: + - url: https://conda.anaconda.org/conda-forge/ + packages: + linux-64: + - conda: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + - conda: https://conda.anaconda.org/conda-forge/linux-64/bat-0.24.0-he8a937b_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-14.1.0-he8a937b_0.conda +packages: +- kind: conda + name: _libgcc_mutex + version: '0.1' + build: conda_forge + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2 + sha256: fe51de6107f9edc7aa4f786a70f4a883943bc9d39b3bb7307c04c41410990726 + md5: d7c89558ba9fa0495403155b64376d81 + license: None + size: 2562 + timestamp: 1578324546067 +- kind: conda + name: _openmp_mutex + version: '4.5' + build: 2_gnu + build_number: 16 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-2_gnu.tar.bz2 + sha256: fbe2c5e56a653bebb982eda4876a9178aedfc2b545f25d0ce9c4c0b508253d22 + md5: 73aaf86a425cc6e73fcf236a5a46396d + depends: + - _libgcc_mutex 0.1 conda_forge + - libgomp >=7.5.0 + constrains: + - openmp_impl 9999 + license: BSD-3-Clause + license_family: BSD + size: 23621 + timestamp: 1650670423406 +- kind: conda + name: bat + version: 0.24.0 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/bat-0.24.0-he8a937b_0.conda + sha256: fd0a7aae7f4c52ddf2ac5098dcb9a8f4b7ab1ccdd88633390a73a9d1be3b7de2 + md5: 18da2a0103ba121e1425266e7ba51327 + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 2527297 + timestamp: 1697062695381 +- kind: conda + name: libgcc + version: 14.1.0 + build: h77fa898_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-14.1.0-h77fa898_1.conda + sha256: 10fa74b69266a2be7b96db881e18fa62cfa03082b65231e8d652e897c4b335a3 + md5: 002ef4463dd1e2b44a94a4ace468f5d2 + depends: + - _libgcc_mutex 0.1 conda_forge + - _openmp_mutex >=4.5 + constrains: + - libgomp 14.1.0 h77fa898_1 + - libgcc-ng ==14.1.0=*_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 846380 + timestamp: 1724801836552 +- kind: conda + name: libgcc-ng + version: 14.1.0 + build: h69a702a_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-14.1.0-h69a702a_1.conda + sha256: b91f7021e14c3d5c840fbf0dc75370d6e1f7c7ff4482220940eaafb9c64613b7 + md5: 1efc0ad219877a73ef977af7dbb51f17 + depends: + - libgcc 14.1.0 h77fa898_1 + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 52170 + timestamp: 1724801842101 +- kind: conda + name: libgomp + version: 14.1.0 + build: h77fa898_1 + build_number: 1 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libgomp-14.1.0-h77fa898_1.conda + sha256: c96724c8ae4ee61af7674c5d9e5a3fbcf6cd887a40ad5a52c99aa36f1d4f9680 + md5: 23c255b008c4f2ae008f81edcabaca89 + depends: + - _libgcc_mutex 0.1 conda_forge + license: GPL-3.0-only WITH GCC-exception-3.1 + license_family: GPL + size: 460218 + timestamp: 1724801743478 +- kind: conda + name: ripgrep + version: 14.1.0 + build: he8a937b_0 + subdir: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/ripgrep-14.1.0-he8a937b_0.conda + sha256: 4fcf37724b87440765cb3c6cf573e99d12fc631001426a0309d132f495c3d62a + md5: 5a476f7033a8a1b9175626b5ebf86d1d + depends: + - libgcc-ng >=12 + license: MIT + license_family: MIT + size: 1683808 + timestamp: 1705520837423 diff --git a/src/lib.rs b/src/lib.rs index a110f1e60..59592ea1c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,17 +2,18 @@ pub mod activation; pub mod cli; pub(crate) mod conda_pypi_clobber; pub mod environment; +mod global; mod install_pypi; mod install_wheel; mod lock_file; mod prefix; mod project; mod prompt; +pub(crate) mod repodata; pub mod task; mod uv_reporter; -mod repodata; mod rlimit; pub use lock_file::load_lock_file; diff --git a/src/lock_file/update.rs b/src/lock_file/update.rs index 49c2ae9e1..a7001347e 100644 --- a/src/lock_file/update.rs +++ b/src/lock_file/update.rs @@ -36,6 +36,7 @@ use tracing::Instrument; use url::Url; use uv_normalize::ExtraName; +use crate::repodata::Repodata; use crate::{ activation::CurrentEnvVarBehavior, environment::{ diff --git a/src/prefix.rs b/src/prefix.rs index f626d373f..392d1c8c2 100644 --- a/src/prefix.rs +++ b/src/prefix.rs @@ -1,11 +1,14 @@ use std::{ collections::HashMap, + ffi::OsStr, path::{Path, PathBuf}, }; use futures::{stream::FuturesUnordered, StreamExt}; +use itertools::Itertools; use miette::{Context, IntoDiagnostic}; -use rattler_conda_types::{Platform, PrefixRecord}; +use pixi_utils::strip_executable_extension; +use rattler_conda_types::{PackageName, Platform, PrefixRecord}; use rattler_shell::{ activation::{ActivationVariables, Activator}, shell::ShellEnum, @@ -105,4 +108,81 @@ impl Prefix { Ok(result) } + + /// Processes prefix records (that you can get by using `find_installed_packages`) + /// to filter and collect executable files. + pub fn find_executables(&self, prefix_packages: &[PrefixRecord]) -> Vec<(String, PathBuf)> { + let executables = prefix_packages + .iter() + .flat_map(|record| { + record + .files + .iter() + .filter(|relative_path| self.is_executable(relative_path)) + .filter_map(|path| { + path.iter().last().and_then(OsStr::to_str).map(|name| { + (strip_executable_extension(name.to_string()), path.clone()) + }) + }) + }) + .collect(); + tracing::debug!( + "In packages: {}, found executables: {:?} ", + prefix_packages + .iter() + .map(|rec| rec.repodata_record.package_record.name.as_normalized()) + .join(", "), + executables + ); + executables + } + + /// Checks if the given relative path points to an executable file. + pub(crate) fn is_executable(&self, relative_path: &Path) -> bool { + // Check if the file is in a known executable directory. + let binary_folders = if cfg!(windows) { + &([ + "", + "Library/mingw-w64/bin/", + "Library/usr/bin/", + "Library/bin/", + "Scripts/", + "bin/", + ][..]) + } else { + &(["bin"][..]) + }; + + let parent_folder = match relative_path.parent() { + Some(dir) => dir, + None => return false, + }; + + if !binary_folders + .iter() + .any(|bin_path| Path::new(bin_path) == parent_folder) + { + return false; + } + + // Check if the file is executable + let absolute_path = self.root().join(relative_path); + is_executable::is_executable(absolute_path) + } + + /// Find the designated package in the given [`Prefix`] + /// + /// # Returns + /// + /// The PrefixRecord of the designated package + pub async fn find_designated_package( + &self, + package_name: &PackageName, + ) -> miette::Result { + let prefix_records = self.find_installed_packages(None).await?; + prefix_records + .into_iter() + .find(|r| r.repodata_record.package_record.name == *package_name) + .ok_or_else(|| miette::miette!("could not find {} in prefix", package_name.as_source())) + } } diff --git a/src/project/repodata.rs b/src/project/repodata.rs index badd2deb8..472915642 100644 --- a/src/project/repodata.rs +++ b/src/project/repodata.rs @@ -1,24 +1,15 @@ use crate::project::Project; - +use crate::repodata::Repodata; use rattler_repodata_gateway::Gateway; -use std::path::PathBuf; -impl Project { +impl Repodata for Project { /// Returns the [`Gateway`] used by this project. - pub(crate) fn repodata_gateway(&self) -> &Gateway { + fn repodata_gateway(&self) -> &Gateway { self.repodata_gateway.get_or_init(|| { - // Determine the cache directory and fall back to sane defaults otherwise. - let cache_dir = pixi_config::get_cache_dir().unwrap_or_else(|e| { - tracing::error!("failed to determine repodata cache directory: {e}"); - std::env::current_dir().unwrap_or_else(|_| PathBuf::from("./")) - }); - - // Construct the gateway - Gateway::builder() - .with_client(self.authenticated_client().clone()) - .with_cache_dir(cache_dir.join(pixi_consts::consts::CONDA_REPODATA_CACHE_DIR)) - .with_channel_config(self.config().into()) - .finish() + Self::repodata_gateway_init( + self.authenticated_client().clone(), + self.config().clone().into(), + ) }) } } diff --git a/src/repodata.rs b/src/repodata.rs index d0d1786dc..9281e66dc 100644 --- a/src/repodata.rs +++ b/src/repodata.rs @@ -1,10 +1,26 @@ -use rattler_conda_types::Channel; +use rattler_repodata_gateway::{ChannelConfig, Gateway}; +use std::path::PathBuf; -/// Returns a friendly name for the specified channel. -pub(crate) fn friendly_channel_name(channel: &Channel) -> String { - channel - .name - .as_ref() - .map(String::from) - .unwrap_or_else(|| channel.canonical_name()) +pub(crate) trait Repodata { + /// Initialized the [`Gateway`] + fn repodata_gateway_init( + authenticated_client: reqwest_middleware::ClientWithMiddleware, + channel_config: ChannelConfig, + ) -> Gateway { + // Determine the cache directory and fall back to sane defaults otherwise. + let cache_dir = pixi_config::get_cache_dir().unwrap_or_else(|e| { + tracing::error!("failed to determine repodata cache directory: {e}"); + std::env::current_dir().unwrap_or_else(|_| PathBuf::from("./")) + }); + + // Construct the gateway + Gateway::builder() + .with_client(authenticated_client) + .with_cache_dir(cache_dir.join(pixi_consts::consts::CONDA_REPODATA_CACHE_DIR)) + .with_channel_config(channel_config) + .finish() + } + + /// Returns the [`Gateway`] used by this project. + fn repodata_gateway(&self) -> &Gateway; } diff --git a/tests/integration/common.py b/tests/integration/common.py index 0feaee48d..413493667 100644 --- a/tests/integration/common.py +++ b/tests/integration/common.py @@ -1,6 +1,7 @@ from enum import IntEnum from pathlib import Path import subprocess +import os PIXI_VERSION = "0.32.2" @@ -13,13 +14,23 @@ class ExitCode(IntEnum): def verify_cli_command( command: list[Path | str], - expected_exit_code: ExitCode, + expected_exit_code: ExitCode = ExitCode.SUCCESS, stdout_contains: str | list[str] | None = None, stdout_excludes: str | list[str] | None = None, stderr_contains: str | list[str] | None = None, stderr_excludes: str | list[str] | None = None, + env: dict[str, str] | None = None, ) -> None: - process = subprocess.run(command, capture_output=True, text=True) + # Setup the environment type safe. + base_env = dict(os.environ) + if env is not None: + complete_env = base_env | env + else: + complete_env = base_env + # Avoid to have miette splitting up lines + complete_env = complete_env | {"NO_GRAPHICS": "1"} + + process = subprocess.run(command, capture_output=True, text=True, env=complete_env) stdout, stderr, returncode = process.stdout, process.stderr, process.returncode print(f"command: {command}, stdout: {stdout}, stderr: {stderr}, code: {returncode}") if expected_exit_code is not None: diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 34799d8db..2f09457e3 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -6,3 +6,28 @@ @pytest.fixture def pixi() -> Path: return Path(__file__).parent.joinpath("../../.pixi/target/release/pixi") + + +@pytest.fixture +def test_data() -> Path: + return Path(__file__).parent.joinpath("test_data").resolve() + + +@pytest.fixture +def dummy_channel_1(test_data: Path) -> str: + return test_data.joinpath("dummy_channel_1/output").as_uri() + + +@pytest.fixture +def dummy_channel_2(test_data: Path) -> str: + return test_data.joinpath("dummy_channel_2/output").as_uri() + + +@pytest.fixture +def global_update_channel_1(test_data: Path) -> str: + return test_data.joinpath("global_update_channel_1/output").as_uri() + + +@pytest.fixture +def non_self_expose_channel(test_data: Path) -> str: + return test_data.joinpath("non_self_expose_channel/output").as_uri() diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-a-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-a-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..0d2bd28eb Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-a-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..694defadf Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-c-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-c-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..8e1facb17 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-c-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-d-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-d-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..d08c603e9 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy-d-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy_e-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy_e-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..04e2887df Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/linux-64/dummy_e-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/linux-64/repodata.json b/tests/integration/test_data/dummy_channel_1/output/linux-64/repodata.json new file mode 100644 index 000000000..5728aa3c9 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/output/linux-64/repodata.json @@ -0,0 +1,83 @@ +{ + "info": { + "subdir": "linux-64" + }, + "packages": {}, + "packages.conda": { + "dummy-a-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [ + "dummy-c" + ], + "md5": "597e9cb900b6959ac30f8e2deb387be5", + "name": "dummy-a", + "platform": "linux", + "sha256": "14a455ab09bc5f0aa45add672e03903b3506ec9cec1f3ed56d211e4c500a2c82", + "size": 196722, + "subdir": "linux-64", + "timestamp": 1728656618060, + "version": "0.1.0" + }, + "dummy-b-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "49bd2f4567a0ba51b4eb8792ed0c851b", + "name": "dummy-b", + "platform": "linux", + "sha256": "61dae106b7f44a74bcf89064ec25e3e76097deabfe8c2d4ea12d2c09abc6daef", + "size": 149020, + "subdir": "linux-64", + "timestamp": 1728656618060, + "version": "0.1.0" + }, + "dummy-c-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "b33c6761380ff086c99f96ed36fdcfe1", + "name": "dummy-c", + "platform": "linux", + "sha256": "0e6861e1b51d0b2471f1be0fc5b6e65cf3cf4cc2f7d4cf6a20400bae85b7b563", + "size": 159429, + "subdir": "linux-64", + "timestamp": 1728656618060, + "version": "0.1.0" + }, + "dummy-d-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [ + "dummy-x" + ], + "md5": "bf9a8314ff17815586f8a0277f2b0de8", + "name": "dummy-d", + "platform": "linux", + "sha256": "fff1786527dabae7ec1da256547b02046694411fd13b21af841df18743e53644", + "size": 171447, + "subdir": "linux-64", + "timestamp": 1728656618060, + "version": "0.1.0" + }, + "dummy_e-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "92d19184d86598cd12ca01c7540d2985", + "name": "dummy_e", + "platform": "linux", + "sha256": "a94c94f04912d5ca926d560c634857bacea847046ab80b5cd674f2624722807e", + "size": 183759, + "subdir": "linux-64", + "timestamp": 1728656618060, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_1/output/noarch/repodata.json b/tests/integration/test_data/dummy_channel_1/output/noarch/repodata.json new file mode 100644 index 000000000..7402d6d29 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/output/noarch/repodata.json @@ -0,0 +1,8 @@ +{ + "info": { + "subdir": "noarch" + }, + "packages": {}, + "packages.conda": {}, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-a-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-a-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..b7609a0b9 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-a-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..839593b83 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-c-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-c-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..b03083ed8 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-c-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-d-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-d-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..def2c890f Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy-d-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy_e-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy_e-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..935c7e9c2 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-64/dummy_e-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-64/repodata.json b/tests/integration/test_data/dummy_channel_1/output/osx-64/repodata.json new file mode 100644 index 000000000..4a1703ecd --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/output/osx-64/repodata.json @@ -0,0 +1,83 @@ +{ + "info": { + "subdir": "osx-64" + }, + "packages": {}, + "packages.conda": { + "dummy-a-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [ + "dummy-c" + ], + "md5": "08fbe58a444f0ece0089d419c7afd2b1", + "name": "dummy-a", + "platform": "osx", + "sha256": "c4840441825cf855f003d57facbaba274bcdf28743424c7a7b548ae974d737b0", + "size": 315563, + "subdir": "osx-64", + "timestamp": 1728656619048, + "version": "0.1.0" + }, + "dummy-b-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "5758178d2d15b3c4758e1c6286c1e714", + "name": "dummy-b", + "platform": "osx", + "sha256": "704f2af4e85ef4858e60e42ffe117ed4208f14c72f62f8192e4cbe3801943dc0", + "size": 334599, + "subdir": "osx-64", + "timestamp": 1728656619048, + "version": "0.1.0" + }, + "dummy-c-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "56cda8fe1b6f9979759094bd08b8c982", + "name": "dummy-c", + "platform": "osx", + "sha256": "e7afcdb7bc8a7bdd0724047acd5c32d3ecd5cea08b1e275222efa727d263a73c", + "size": 298829, + "subdir": "osx-64", + "timestamp": 1728656619048, + "version": "0.1.0" + }, + "dummy-d-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [ + "dummy-x" + ], + "md5": "2a15c9a07af764199be9f2c46f2bb82a", + "name": "dummy-d", + "platform": "osx", + "sha256": "2e2862a7b20d1e536f33be1f9bc6dfef13eab94363b2d73e355254a841fd1520", + "size": 283050, + "subdir": "osx-64", + "timestamp": 1728656619048, + "version": "0.1.0" + }, + "dummy_e-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "587cbef047629540ef0c618981ca6000", + "name": "dummy_e", + "platform": "osx", + "sha256": "637622288678a6adcf6ab71909acd80a356be4f94675f823745968d9755f97ee", + "size": 267020, + "subdir": "osx-64", + "timestamp": 1728656619048, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-a-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-a-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..ab2553eab Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-a-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..cd1987541 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-c-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-c-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..f606a9595 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-c-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-d-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-d-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..75b4a63af Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy-d-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy_e-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy_e-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..ef2fd2723 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/dummy_e-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/osx-arm64/repodata.json b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/repodata.json new file mode 100644 index 000000000..f2068e057 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/output/osx-arm64/repodata.json @@ -0,0 +1,83 @@ +{ + "info": { + "subdir": "osx-arm64" + }, + "packages": {}, + "packages.conda": { + "dummy-a-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [ + "dummy-c" + ], + "md5": "207186e8a7cf582b9a0dcbbd3b940a24", + "name": "dummy-a", + "platform": "osx", + "sha256": "88639105a6495d3dfeb316b1ed5b39c7a5444e49f68dd6f6e6e462170f8bf56e", + "size": 233247, + "subdir": "osx-arm64", + "timestamp": 1728656618428, + "version": "0.1.0" + }, + "dummy-b-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "7a51cdd64a06c00ad6dd9c7e5a215ccc", + "name": "dummy-b", + "platform": "osx", + "sha256": "62e38dd89eee4c0fd88ba268b1d70de40b4ac99c01e430c7345f7b2f527986a0", + "size": 258331, + "subdir": "osx-arm64", + "timestamp": 1728656618429, + "version": "0.1.0" + }, + "dummy-c-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "7d1c920bd362ce87fb60ec7dc022c70a", + "name": "dummy-c", + "platform": "osx", + "sha256": "e4fc8d68868c6a7811aa05ace230bb6ff35f32f2c84e8e800050603e470fd59d", + "size": 224415, + "subdir": "osx-arm64", + "timestamp": 1728656618429, + "version": "0.1.0" + }, + "dummy-d-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [ + "dummy-x" + ], + "md5": "0c511e248e8d9d9e1eee68ceb0a0b7ee", + "name": "dummy-d", + "platform": "osx", + "sha256": "31483bb2eefdb2c37c549b36200b847ff2db3ca0ed70ae027577fc3a2cd16f5b", + "size": 210149, + "subdir": "osx-arm64", + "timestamp": 1728656618428, + "version": "0.1.0" + }, + "dummy_e-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "f294953bfdad44eace2f6c7afd62767b", + "name": "dummy_e", + "platform": "osx", + "sha256": "f4649e11ddcd0a5fea4256c69fb02e047d1efdbd8de03d88b3c850b9824f0993", + "size": 246049, + "subdir": "osx-arm64", + "timestamp": 1728656618429, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-a-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-a-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..c41b93c91 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-a-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..5828e7686 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-c-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-c-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..0db9d6344 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-c-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-d-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-d-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..dcba94289 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy-d-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/dummy_e-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy_e-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..127dbf22f Binary files /dev/null and b/tests/integration/test_data/dummy_channel_1/output/win-64/dummy_e-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_1/output/win-64/repodata.json b/tests/integration/test_data/dummy_channel_1/output/win-64/repodata.json new file mode 100644 index 000000000..766a60792 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/output/win-64/repodata.json @@ -0,0 +1,83 @@ +{ + "info": { + "subdir": "win-64" + }, + "packages": {}, + "packages.conda": { + "dummy-a-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [ + "dummy-c" + ], + "md5": "f0d02cc7bad16e7c5c549118fcfaac3b", + "name": "dummy-a", + "platform": "win", + "sha256": "6103329bc03095464bfb421b02bccd36c7cd2e70ec5a8f45c6acae22a4627b72", + "size": 129862, + "subdir": "win-64", + "timestamp": 1728656617798, + "version": "0.1.0" + }, + "dummy-b-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "f2cdc4fe37dcdc53bc756182400c07ef", + "name": "dummy-b", + "platform": "win", + "sha256": "301cc1f47767d76e440dd9d33c8b7f04aefbcc283944f6e50d7e9fecb43993d2", + "size": 119245, + "subdir": "win-64", + "timestamp": 1728656617798, + "version": "0.1.0" + }, + "dummy-c-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "7eb77094d24bce94fbde43196fca26bf", + "name": "dummy-c", + "platform": "win", + "sha256": "76e49accd774dc4785b377356f5267d8539fff68d1d9fe27b702b140d18ddf69", + "size": 111514, + "subdir": "win-64", + "timestamp": 1728656617798, + "version": "0.1.0" + }, + "dummy-d-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [ + "dummy-x" + ], + "md5": "6cb27a4201ffc597ccafdcc2b80133c7", + "name": "dummy-d", + "platform": "win", + "sha256": "dbe72e74ada93d5edfed84bf369a564d17b0949f188dc8ec1f5f81e418d20e95", + "size": 140004, + "subdir": "win-64", + "timestamp": 1728656617798, + "version": "0.1.0" + }, + "dummy_e-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "42a198b645aaa487b2eec2ce5da0417d", + "name": "dummy_e", + "platform": "win", + "sha256": "862286175f4634fc02fd647dbc4438aca5f004c3913b06173efa21608e5fbc9a", + "size": 101456, + "subdir": "win-64", + "timestamp": 1728656617798, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_1/recipe.yaml b/tests/integration/test_data/dummy_channel_1/recipe.yaml new file mode 100644 index 000000000..d3dd905d4 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_1/recipe.yaml @@ -0,0 +1,86 @@ +recipe: + name: dummy + version: 1.0.0 + +outputs: + - package: + name: dummy-a + version: 0.1.0 + + requirements: + run: + - dummy-c + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-a on windows" > $PREFIX/bin/dummy-a.bat + - echo "dummy-aa on windows" > $PREFIX/bin/dummy-aa.bat + else: + - echo "dummy-a on unix" > $PREFIX/bin/dummy-a + - echo "dummy-aa on unix" > $PREFIX/bin/dummy-aa + - chmod +x $PREFIX/bin/dummy-a + - chmod +x $PREFIX/bin/dummy-aa + + - package: + name: dummy-b + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-b on windows" > $PREFIX/bin/dummy-b.bat + else: + - echo "dummy-b on unix" > $PREFIX/bin/dummy-b + - chmod +x $PREFIX/bin/dummy-b + + - package: + name: dummy-c + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-c on windows" > $PREFIX/bin/dummy-c.bat + else: + - echo "dummy-c on unix" > $PREFIX/bin/dummy-c + - chmod +x $PREFIX/bin/dummy-c + + - package: + name: dummy-d + version: 0.1.0 + + requirements: + run: + - dummy-x # This comes from dummy_channel_2 + + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-d on windows" > $PREFIX/bin/dummy-d.bat + else: + - echo "dummy-d on unix" > $PREFIX/bin/dummy-d + - chmod +x $PREFIX/bin/dummy-d + + - package: + name: dummy_e + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy_e on windows" > $PREFIX/bin/dummy_e.bat + else: + - echo "dummy_e on unix" > $PREFIX/bin/dummy_e + - chmod +x $PREFIX/bin/dummy_e diff --git a/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..0ec50d620 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-b-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-x-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-x-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..2755b2d76 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/linux-64/dummy-x-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/linux-64/repodata.json b/tests/integration/test_data/dummy_channel_2/output/linux-64/repodata.json new file mode 100644 index 000000000..127c2ebe0 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/output/linux-64/repodata.json @@ -0,0 +1,37 @@ +{ + "info": { + "subdir": "linux-64" + }, + "packages": {}, + "packages.conda": { + "dummy-b-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "f85960fbb020f325b1a881176f0af94a", + "name": "dummy-b", + "platform": "linux", + "sha256": "c1319a6e656c72410738cd99823a9c861e95568684e405d09c400bf2e400a904", + "size": 12212, + "subdir": "linux-64", + "timestamp": 1728983076380, + "version": "0.1.0" + }, + "dummy-x-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "2fde9a3b035cb6e898c28ab7a3cc6c6d", + "name": "dummy-x", + "platform": "linux", + "sha256": "e18f27d9ac595a8c30ca243223526d6b76e0a19ca186d950393243d2d209a79f", + "size": 15140, + "subdir": "linux-64", + "timestamp": 1728983076380, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_2/output/noarch/repodata.json b/tests/integration/test_data/dummy_channel_2/output/noarch/repodata.json new file mode 100644 index 000000000..7402d6d29 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/output/noarch/repodata.json @@ -0,0 +1,8 @@ +{ + "info": { + "subdir": "noarch" + }, + "packages": {}, + "packages.conda": {}, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..a53ea5c79 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-b-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-x-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-x-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..f71fa5317 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/osx-64/dummy-x-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-64/repodata.json b/tests/integration/test_data/dummy_channel_2/output/osx-64/repodata.json new file mode 100644 index 000000000..63dac534f --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/output/osx-64/repodata.json @@ -0,0 +1,37 @@ +{ + "info": { + "subdir": "osx-64" + }, + "packages": {}, + "packages.conda": { + "dummy-b-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "01e59c205e5868da1383de347188aff0", + "name": "dummy-b", + "platform": "osx", + "sha256": "5b9b58c26fe363325bf55d6a2e853f6dd24fb7f68eb6920d315bcb7452088328", + "size": 32249, + "subdir": "osx-64", + "timestamp": 1728983076503, + "version": "0.1.0" + }, + "dummy-x-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "6b53468a2a62b6fe93907a04fb69dd95", + "name": "dummy-x", + "platform": "osx", + "sha256": "76c5eb3ceb3a470e2a6400b87aad855c634f4ac08f33d880887ec3f1fd4f22e1", + "size": 26189, + "subdir": "osx-64", + "timestamp": 1728983076503, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..62b8c84d4 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-b-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-x-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-x-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..edc198b3b Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/dummy-x-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/osx-arm64/repodata.json b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/repodata.json new file mode 100644 index 000000000..4fbe3187c --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/output/osx-arm64/repodata.json @@ -0,0 +1,37 @@ +{ + "info": { + "subdir": "osx-arm64" + }, + "packages": {}, + "packages.conda": { + "dummy-b-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "edca682cc09a974b6453d9b19d32c351", + "name": "dummy-b", + "platform": "osx", + "sha256": "a90458015c443c443460064d14bbf1b6560ceb27b7d4eb204caf3e501e16865f", + "size": 18391, + "subdir": "osx-arm64", + "timestamp": 1728983076440, + "version": "0.1.0" + }, + "dummy-x-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "fe2b9de8fbcbd1a588ed41d04e850d2d", + "name": "dummy-x", + "platform": "osx", + "sha256": "70b985a0464aca5c82985a334c90f85cc6290683efabcb3d01139ae9108ed2e3", + "size": 22135, + "subdir": "osx-arm64", + "timestamp": 1728983076440, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..45a575b4c Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-b-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-x-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-x-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..3c44a5192 Binary files /dev/null and b/tests/integration/test_data/dummy_channel_2/output/win-64/dummy-x-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/dummy_channel_2/output/win-64/repodata.json b/tests/integration/test_data/dummy_channel_2/output/win-64/repodata.json new file mode 100644 index 000000000..f4b2236b7 --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/output/win-64/repodata.json @@ -0,0 +1,37 @@ +{ + "info": { + "subdir": "win-64" + }, + "packages": {}, + "packages.conda": { + "dummy-b-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "56b5a7a65150d4a2941515c9c3717c6f", + "name": "dummy-b", + "platform": "win", + "sha256": "e281921e34424985e680050bf1714289fdd4e20241b830410bfdfee55505dce6", + "size": 6195, + "subdir": "win-64", + "timestamp": 1728983076323, + "version": "0.1.0" + }, + "dummy-x-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "feeb05a11f1ee00a94ec168991c8a46f", + "name": "dummy-x", + "platform": "win", + "sha256": "90dfd8c70601d8efc60e91b48a928a40f48268a78829c457f88a40024cced32c", + "size": 3055, + "subdir": "win-64", + "timestamp": 1728983076323, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/dummy_channel_2/recipe.yaml b/tests/integration/test_data/dummy_channel_2/recipe.yaml new file mode 100644 index 000000000..1170efadc --- /dev/null +++ b/tests/integration/test_data/dummy_channel_2/recipe.yaml @@ -0,0 +1,32 @@ +recipe: + name: dummy + version: 1.0.0 + +outputs: + - package: + name: dummy-x + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-x on windows" > $PREFIX/bin/dummy-x.bat + else: + - echo "dummy-x on unix" > $PREFIX/bin/dummy-x + - chmod +x $PREFIX/bin/dummy-x + + - package: + name: dummy-b + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "dummy-b on windows" > $PREFIX/bin/dummy-b.bat + else: + - echo "dummy-b on unix" > $PREFIX/bin/dummy-b + - chmod +x $PREFIX/bin/dummy-b diff --git a/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..1dcdfbcdb Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.2.0-hb0f4dca_0.conda b/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.2.0-hb0f4dca_0.conda new file mode 100644 index 000000000..a618e103e Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/linux-64/package-0.2.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..fa39f7924 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.2.0-hb0f4dca_0.conda b/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.2.0-hb0f4dca_0.conda new file mode 100644 index 000000000..7478fd648 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/linux-64/package2-0.2.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/linux-64/repodata.json b/tests/integration/test_data/global_update_channel_1/output/linux-64/repodata.json new file mode 100644 index 000000000..c624a3f16 --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/output/linux-64/repodata.json @@ -0,0 +1,65 @@ +{ + "info": { + "subdir": "linux-64" + }, + "packages": {}, + "packages.conda": { + "package-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "24bcc1d7884b664e7dbe83bc57865cb2", + "name": "package", + "platform": "linux", + "sha256": "90628def4b54b08709e8cb6ab2a994c0868caaa5dbf6c1e3398ae6bf2b8ec28d", + "size": 734504, + "subdir": "linux-64", + "timestamp": 1728998858372, + "version": "0.1.0" + }, + "package-0.2.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "018031c969612a9abf5471d739f1609b", + "name": "package", + "platform": "linux", + "sha256": "cf85cad369945d55a8a79e7ea0af0f8c45e7dff4900c615a713cb52e7037c15c", + "size": 286438, + "subdir": "linux-64", + "timestamp": 1727946102143, + "version": "0.2.0" + }, + "package2-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "08703676fb6aac7ba1dc7cebe63d3afb", + "name": "package2", + "platform": "linux", + "sha256": "ccd6937a4eb5536c18e678358075309d7319328c52a5af60c181ea88f9abe5db", + "size": 811777, + "subdir": "linux-64", + "timestamp": 1728998858372, + "version": "0.1.0" + }, + "package2-0.2.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "c54786ed22b057b6f36774b0f1255320", + "name": "package2", + "platform": "linux", + "sha256": "196994cf91d4d65b29d41309a476e5f18614ef6f8aa9f77e490a7c623ce027b4", + "size": 272123, + "subdir": "linux-64", + "timestamp": 1727946102143, + "version": "0.2.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/global_update_channel_1/output/noarch/repodata.json b/tests/integration/test_data/global_update_channel_1/output/noarch/repodata.json new file mode 100644 index 000000000..7402d6d29 --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/output/noarch/repodata.json @@ -0,0 +1,8 @@ +{ + "info": { + "subdir": "noarch" + }, + "packages": {}, + "packages.conda": {}, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..0466688f1 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.2.0-h0dc7051_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.2.0-h0dc7051_0.conda new file mode 100644 index 000000000..c1360fa2f Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-64/package-0.2.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..28d84a72b Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.2.0-h0dc7051_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.2.0-h0dc7051_0.conda new file mode 100644 index 000000000..99f2b28cf Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-64/package2-0.2.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-64/repodata.json b/tests/integration/test_data/global_update_channel_1/output/osx-64/repodata.json new file mode 100644 index 000000000..e76b3d3ed --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/output/osx-64/repodata.json @@ -0,0 +1,65 @@ +{ + "info": { + "subdir": "osx-64" + }, + "packages": {}, + "packages.conda": { + "package-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "eeea5e741a765fc957c731b22fb9eb6d", + "name": "package", + "platform": "osx", + "sha256": "2887c0486aac48bab7a61a0b2d91c800c6e58be561e493155676f4448cbd7551", + "size": 920371, + "subdir": "osx-64", + "timestamp": 1728998859384, + "version": "0.1.0" + }, + "package-0.2.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "51cfedb404eccf9fa2319459d2c9711e", + "name": "package", + "platform": "osx", + "sha256": "90c1be8eda753f91cf87b2e835ff86990f3525a56685109408084ca4f98d8869", + "size": 343405, + "subdir": "osx-64", + "timestamp": 1727946102587, + "version": "0.2.0" + }, + "package2-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "436922cbd43aa11bd8337f85ad0e4f6e", + "name": "package2", + "platform": "osx", + "sha256": "abb149cb0262397302bb18b41a59bfcf1f7b2ec2bf9bf7de0c00f127bfe4a5ce", + "size": 854183, + "subdir": "osx-64", + "timestamp": 1728998859384, + "version": "0.1.0" + }, + "package2-0.2.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "da9072df7da83a0d2f472f096ad877e1", + "name": "package2", + "platform": "osx", + "sha256": "bcda093f187e893cd96385d77f4148466363742d2c28d763eea08f88d0a31f15", + "size": 332537, + "subdir": "osx-64", + "timestamp": 1727946102587, + "version": "0.2.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..a345516fb Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.2.0-h60d57d3_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.2.0-h60d57d3_0.conda new file mode 100644 index 000000000..9da6687b7 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package-0.2.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..2cdf8203a Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.2.0-h60d57d3_0.conda b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.2.0-h60d57d3_0.conda new file mode 100644 index 000000000..d6e37c3da Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/package2-0.2.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/osx-arm64/repodata.json b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/repodata.json new file mode 100644 index 000000000..a8bba5383 --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/output/osx-arm64/repodata.json @@ -0,0 +1,65 @@ +{ + "info": { + "subdir": "osx-arm64" + }, + "packages": {}, + "packages.conda": { + "package-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "39e26dea4b4b90adadbd86eadec1a8ff", + "name": "package", + "platform": "osx", + "sha256": "2ccd8656d1f6c856cda88972a44a9f190956a246521d92d9aa7705814e8d69bd", + "size": 800077, + "subdir": "osx-arm64", + "timestamp": 1728998858841, + "version": "0.1.0" + }, + "package-0.2.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "414311f16961ab666c1d8acabb1c13f0", + "name": "package", + "platform": "osx", + "sha256": "ba306d3b264ca6903a7810e40fddbe63d8d193dbf68e1493cd0bec32bd2414b7", + "size": 318777, + "subdir": "osx-arm64", + "timestamp": 1727946102363, + "version": "0.2.0" + }, + "package2-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "02fa5892feb2eb96ab733d7bb666197e", + "name": "package2", + "platform": "osx", + "sha256": "6fd98c3deb3da3f0ae4b63dba27b8b8a36678d977a2a6324ede2e1dc0c47496a", + "size": 812306, + "subdir": "osx-arm64", + "timestamp": 1728998858841, + "version": "0.1.0" + }, + "package2-0.2.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "d46b8f08d4ca7568138c565cdb5592f8", + "name": "package2", + "platform": "osx", + "sha256": "fe8ec2989c29ae103055723279e381c42cff9aca831c495400834f9eeaddef6f", + "size": 302406, + "subdir": "osx-arm64", + "timestamp": 1727946102363, + "version": "0.2.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..b438b173b Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.2.0-h9490d1a_0.conda b/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.2.0-h9490d1a_0.conda new file mode 100644 index 000000000..3d755f701 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/win-64/package-0.2.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..240054bc8 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.2.0-h9490d1a_0.conda b/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.2.0-h9490d1a_0.conda new file mode 100644 index 000000000..e71d82042 Binary files /dev/null and b/tests/integration/test_data/global_update_channel_1/output/win-64/package2-0.2.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/global_update_channel_1/output/win-64/repodata.json b/tests/integration/test_data/global_update_channel_1/output/win-64/repodata.json new file mode 100644 index 000000000..6e98a237b --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/output/win-64/repodata.json @@ -0,0 +1,65 @@ +{ + "info": { + "subdir": "win-64" + }, + "packages": {}, + "packages.conda": { + "package-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "1c091642ad375f7f014c15229ac21b74", + "name": "package", + "platform": "win", + "sha256": "91298bbae9b190eaac6dd0787b42fa0f75382b7e5fd3aa64348f6c924adabf1b", + "size": 716579, + "subdir": "win-64", + "timestamp": 1728998857890, + "version": "0.1.0" + }, + "package-0.2.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "0e7ecd1740065e1581bc0b202e8a8b0b", + "name": "package", + "platform": "win", + "sha256": "0070f96fd4d1e3b82a8e967161e7475fa58d6752affadd622bce2320308f3550", + "size": 258745, + "subdir": "win-64", + "timestamp": 1727946101940, + "version": "0.2.0" + }, + "package2-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "d8256c205d75820f7e2aa600cfc48649", + "name": "package2", + "platform": "win", + "sha256": "8f6b53eeae5cac3311883c9b3a172a7022610c74045a339a57860ba11aef0252", + "size": 696002, + "subdir": "win-64", + "timestamp": 1728998857890, + "version": "0.1.0" + }, + "package2-0.2.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "5c7e63c07b2de6f9c7387f0cafd4cf7e", + "name": "package2", + "platform": "win", + "sha256": "b2e3346389b5276207ddeae137c3f519cb07ee64d29cea43f22a695ba5749869", + "size": 244940, + "subdir": "win-64", + "timestamp": 1727946101940, + "version": "0.2.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/global_update_channel_1/recipe.yaml b/tests/integration/test_data/global_update_channel_1/recipe.yaml new file mode 100644 index 000000000..f0609e8aa --- /dev/null +++ b/tests/integration/test_data/global_update_channel_1/recipe.yaml @@ -0,0 +1,39 @@ +recipe: + name: global-update-channel + version: 1.0.0 + +context: + # Change this version to create the multiple versions of the package + version: 0.1.0 +outputs: + - package: + name: package + version: ${{ version }} + + build: + script: + - mkdir -p $PREFIX/bin + # Expose two binaries, with and without version number + - if: win + then: + - echo "package$PKG_VERSION on windows" > $PREFIX/bin/package$PKG_VERSION.bat + - echo "package on windows" > $PREFIX/bin/package.bat + else: + - echo "package$PKG_VERSION on unix" > "$PREFIX/bin/package$PKG_VERSION" + - chmod +x $PREFIX/bin/package$PKG_VERSION + - echo "package on unix" > $PREFIX/bin/package + - chmod +x $PREFIX/bin/package + + - package: + name: package2 + version: ${{ version }} + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "package2$PKG_VERSION on windows" > $PREFIX/bin/package2.bat + else: + - echo "package2$PKG_VERSION on unix" > $PREFIX/bin/package2 + - chmod +x $PREFIX/bin/package2 diff --git a/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..5028f9368 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-core-0.1.0-hb0f4dca_0.conda b/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-core-0.1.0-hb0f4dca_0.conda new file mode 100644 index 000000000..bf470bf57 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/linux-64/jupyter-core-0.1.0-hb0f4dca_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/linux-64/repodata.json b/tests/integration/test_data/non_self_expose_channel/output/linux-64/repodata.json new file mode 100644 index 000000000..15395db08 --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/output/linux-64/repodata.json @@ -0,0 +1,39 @@ +{ + "info": { + "subdir": "linux-64" + }, + "packages": {}, + "packages.conda": { + "jupyter-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [ + "jupyter-core" + ], + "md5": "8ac1a98504a4c4ad50eb079f79f94811", + "name": "jupyter", + "platform": "linux", + "sha256": "31a74defc278f2ee69509940038d6036bd0433b3741c61daae3d5b675128cff3", + "size": 14526, + "subdir": "linux-64", + "timestamp": 1727938184892, + "version": "0.1.0" + }, + "jupyter-core-0.1.0-hb0f4dca_0.conda": { + "arch": "x86_64", + "build": "hb0f4dca_0", + "build_number": 0, + "depends": [], + "md5": "9d3656534bd12b9645e7dd4754f7eec1", + "name": "jupyter-core", + "platform": "linux", + "sha256": "96f288dc39fa3e63d6ac7373adbcc8c3557a7f92f7d8339c6c102ff813dc29a3", + "size": 11844, + "subdir": "linux-64", + "timestamp": 1727938184892, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/non_self_expose_channel/output/noarch/repodata.json b/tests/integration/test_data/non_self_expose_channel/output/noarch/repodata.json new file mode 100644 index 000000000..7402d6d29 --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/output/noarch/repodata.json @@ -0,0 +1,8 @@ +{ + "info": { + "subdir": "noarch" + }, + "packages": {}, + "packages.conda": {}, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..96c391828 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-core-0.1.0-h0dc7051_0.conda b/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-core-0.1.0-h0dc7051_0.conda new file mode 100644 index 000000000..0c2327494 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/osx-64/jupyter-core-0.1.0-h0dc7051_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-64/repodata.json b/tests/integration/test_data/non_self_expose_channel/output/osx-64/repodata.json new file mode 100644 index 000000000..1ca9b3562 --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/output/osx-64/repodata.json @@ -0,0 +1,39 @@ +{ + "info": { + "subdir": "osx-64" + }, + "packages": {}, + "packages.conda": { + "jupyter-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [ + "jupyter-core" + ], + "md5": "6277ce66115b6a6a53edee58b82c45f1", + "name": "jupyter", + "platform": "osx", + "sha256": "1abc4bbd111c924aed30f3089672eaeb38023bf728f542cd886d09bb66b22bc2", + "size": 31679, + "subdir": "osx-64", + "timestamp": 1727938184989, + "version": "0.1.0" + }, + "jupyter-core-0.1.0-h0dc7051_0.conda": { + "arch": "x86_64", + "build": "h0dc7051_0", + "build_number": 0, + "depends": [], + "md5": "04d32e33638d92eb899e44946f6ec81f", + "name": "jupyter-core", + "platform": "osx", + "sha256": "3beef269ae93329d302e34c92b374e456552acc23d264e3c7e255ebdab41f467", + "size": 25691, + "subdir": "osx-64", + "timestamp": 1727938184989, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..c76e57f96 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-core-0.1.0-h60d57d3_0.conda b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-core-0.1.0-h60d57d3_0.conda new file mode 100644 index 000000000..dbffea2b7 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/jupyter-core-0.1.0-h60d57d3_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/repodata.json b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/repodata.json new file mode 100644 index 000000000..c55046acd --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/output/osx-arm64/repodata.json @@ -0,0 +1,39 @@ +{ + "info": { + "subdir": "osx-arm64" + }, + "packages": {}, + "packages.conda": { + "jupyter-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [ + "jupyter-core" + ], + "md5": "c99ef1add69dbd2f4f9ec238eed9699a", + "name": "jupyter", + "platform": "osx", + "sha256": "6f53f339754aed0955af6e9aaf6d06409808e19bc301f7bc9e933da6037f9fe5", + "size": 21429, + "subdir": "osx-arm64", + "timestamp": 1727938184936, + "version": "0.1.0" + }, + "jupyter-core-0.1.0-h60d57d3_0.conda": { + "arch": "arm64", + "build": "h60d57d3_0", + "build_number": 0, + "depends": [], + "md5": "bdccdd9dd27f6f453621d30655d1e3bd", + "name": "jupyter-core", + "platform": "osx", + "sha256": "c6fa67942056e5fc06687ebac0155902338687a31343f3ef9ce8d067c6496627", + "size": 17876, + "subdir": "osx-arm64", + "timestamp": 1727938184936, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..94136ecf9 Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-core-0.1.0-h9490d1a_0.conda b/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-core-0.1.0-h9490d1a_0.conda new file mode 100644 index 000000000..05d32479c Binary files /dev/null and b/tests/integration/test_data/non_self_expose_channel/output/win-64/jupyter-core-0.1.0-h9490d1a_0.conda differ diff --git a/tests/integration/test_data/non_self_expose_channel/output/win-64/repodata.json b/tests/integration/test_data/non_self_expose_channel/output/win-64/repodata.json new file mode 100644 index 000000000..aa3ec5dee --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/output/win-64/repodata.json @@ -0,0 +1,39 @@ +{ + "info": { + "subdir": "win-64" + }, + "packages": {}, + "packages.conda": { + "jupyter-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [ + "jupyter-core" + ], + "md5": "61e600ea701d4202b7a937e2dbcc2c84", + "name": "jupyter", + "platform": "win", + "sha256": "2a17735958829734ed4e6a18db17c20edd3992b5e2c8108b4c28cd7c1151fadf", + "size": 5870, + "subdir": "win-64", + "timestamp": 1727938184848, + "version": "0.1.0" + }, + "jupyter-core-0.1.0-h9490d1a_0.conda": { + "arch": "x86_64", + "build": "h9490d1a_0", + "build_number": 0, + "depends": [], + "md5": "e86723bf0ab5c38255d6faa638d1c753", + "name": "jupyter-core", + "platform": "win", + "sha256": "5fc30283def412ecf492f0f28e4cd8974e03846c0aeb2badef993a8d31dbc3d3", + "size": 3035, + "subdir": "win-64", + "timestamp": 1727938184848, + "version": "0.1.0" + } + }, + "repodata_version": 2 +} diff --git a/tests/integration/test_data/non_self_expose_channel/recipe.yaml b/tests/integration/test_data/non_self_expose_channel/recipe.yaml new file mode 100644 index 000000000..f578d1aa4 --- /dev/null +++ b/tests/integration/test_data/non_self_expose_channel/recipe.yaml @@ -0,0 +1,27 @@ +recipe: + name: self-expose-test + version: 1.0.0 + +outputs: + # jupyter-core exposes the jupyter tool, while jupyter only depends on jupyter-core + - package: + name: jupyter-core + version: 0.1.0 + + build: + script: + - mkdir -p $PREFIX/bin + - if: win + then: + - echo "jupyter on windows" > $PREFIX/bin/jupyter.bat + else: + - echo "jupyter on unix" > $PREFIX/bin/jupyter + - chmod +x $PREFIX/bin/jupyter + + - package: + name: jupyter + version: 0.1.0 + + requirements: + run: + - jupyter-core diff --git a/tests/integration/test_data/update_channel.nu b/tests/integration/test_data/update_channel.nu new file mode 100644 index 000000000..114a27363 --- /dev/null +++ b/tests/integration/test_data/update_channel.nu @@ -0,0 +1,10 @@ +# Run with e.g. : `nu update_channel.nu dummy_channel_1` +export def main [channel: string] { + let platforms = ["win-64", "linux-64", "osx-arm64", "osx-64"] + cd $channel + + for platform in $platforms { + rattler-build build --target-platform $platform + } + rm -rf output/bld +} diff --git a/tests/integration/test_global.py b/tests/integration/test_global.py new file mode 100644 index 000000000..4e6b08884 --- /dev/null +++ b/tests/integration/test_global.py @@ -0,0 +1,1361 @@ +from pathlib import Path +import tomllib + +import pytest +import tomli_w +from .common import verify_cli_command, ExitCode +import platform +import os +import stat + +MANIFEST_VERSION = 1 + + +def exec_extension(exe_name: str) -> str: + if platform.system() == "Windows": + return exe_name + ".bat" + else: + return exe_name + + +def test_sync_dependencies(pixi: Path, tmp_path: Path) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = """ + [envs.test] + channels = ["conda-forge"] + dependencies = { python = "3.12" } + exposed = { "python-injected" = "python" } + """ + parsed_toml = tomllib.loads(toml) + manifest.write_text(toml) + python_injected = tmp_path / "bin" / exec_extension("python-injected") + + # Test basic commands + verify_cli_command([pixi, "global", "sync"], env=env) + verify_cli_command([python_injected, "--version"], env=env, stdout_contains="3.12") + verify_cli_command([python_injected, "-c", "import numpy"], ExitCode.FAILURE, env=env) + + # Add numpy + parsed_toml["envs"]["test"]["dependencies"]["numpy"] = "*" + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command([pixi, "global", "sync"], env=env) + verify_cli_command([python_injected, "-c", "import numpy"], env=env) + + # Remove numpy again + del parsed_toml["envs"]["test"]["dependencies"]["numpy"] + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command([pixi, "global", "sync"], env=env) + verify_cli_command([python_injected, "-c", "import numpy"], ExitCode.FAILURE, env=env) + + # Remove python + del parsed_toml["envs"]["test"]["dependencies"]["python"] + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command( + [pixi, "global", "sync"], + ExitCode.FAILURE, + env=env, + stderr_contains=["Couldn't find executable", "Failed to add executables for environment"], + ) + + +def test_sync_platform(pixi: Path, tmp_path: Path) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = """ + [envs.test] + channels = ["conda-forge"] + platform = "win-64" + dependencies = { binutils = "2.40" }\ + """ + parsed_toml = tomllib.loads(toml) + manifest.write_text(toml) + + # Exists on win-64 + verify_cli_command([pixi, "global", "sync"], env=env) + + # Doesn't exist on osx-64 + parsed_toml["envs"]["test"]["platform"] = "osx-64" + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command( + [pixi, "global", "sync"], + ExitCode.FAILURE, + env=env, + stderr_contains="No candidates were found", + ) + + +def test_sync_change_expose(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" + [envs.test] + channels = ["{dummy_channel_1}"] + [envs.test.dependencies] + dummy-a = "*" + + [envs.test.exposed] + "dummy-a" = "dummy-a" + """ + parsed_toml = tomllib.loads(toml) + manifest.write_text(toml) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + + # Test basic commands + verify_cli_command([pixi, "global", "sync"], env=env) + assert dummy_a.is_file() + + # Add another expose + dummy_in_disguise = tmp_path / "bin" / exec_extension("dummy-in-disguise") + parsed_toml["envs"]["test"]["exposed"]["dummy-in-disguise"] = "dummy-a" + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command([pixi, "global", "sync"], env=env) + assert dummy_in_disguise.is_file() + + # Remove expose again + del parsed_toml["envs"]["test"]["exposed"]["dummy-in-disguise"] + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command([pixi, "global", "sync"], env=env) + assert not dummy_in_disguise.is_file() + + +def test_sync_manually_remove_binary(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" + [envs.test] + channels = ["{dummy_channel_1}"] + [envs.test.dependencies] + dummy-a = "*" + + [envs.test.exposed] + "dummy-a" = "dummy-a" + """ + manifest.write_text(toml) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + + # Test basic commands + verify_cli_command([pixi, "global", "sync"], env=env) + assert dummy_a.is_file() + + # Remove binary manually + dummy_a.unlink() + + # Binary is added again + verify_cli_command([pixi, "global", "sync"], env=env) + assert dummy_a.is_file() + + +def test_sync_migrate( + pixi: Path, tmp_path: Path, dummy_channel_1: str, dummy_channel_2: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f"""\ +version = {MANIFEST_VERSION} +# Test with special channel +[envs.test] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*", dummy-b = "*" }} +exposed = {{ dummy-1 = "dummy-a", dummy-2 = "dummy-a", dummy-3 = "dummy-b", dummy-4 = "dummy-b" }} + +# Test with multiple channels +[envs.test1] +channels = ["{dummy_channel_1}", "{dummy_channel_2}"] +dependencies = {{ dummy-d = "*" }} +exposed = {{ dummy-d = "dummy-d" }} + +# Test with conda-forge channel +[envs.test2] +channels = ["conda-forge"] +# Small package with binary for testing purposes +dependencies = {{ xz = "*" }} +exposed = {{ xz = "xz" }} +""" + manifest.write_text(toml) + verify_cli_command([pixi, "global", "sync"], env=env) + + # Test migration from existing environments + original_manifest = manifest.read_text() + manifest.unlink() + manifests.rmdir() + verify_cli_command([pixi, "global", "sync"], env=env) + migrated_manifest = manifest.read_text() + assert tomllib.loads(migrated_manifest) == tomllib.loads(original_manifest) + + +def test_sync_duplicated_expose_error(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" +version = {MANIFEST_VERSION} + +[envs.one] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*" }} +exposed = {{ dummy-1 = "dummy-a" }} + +[envs.two] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-b = "*" }} +exposed = {{ dummy-1 = "dummy-b" }} + """ + manifest.write_text(toml) + verify_cli_command( + [pixi, "global", "sync"], + ExitCode.FAILURE, + env=env, + stderr_contains="Duplicated exposed names found: dummy-1", + ) + + +def test_sync_clean_up_broken_exec(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" +version = {MANIFEST_VERSION} + +[envs.one] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*" }} +exposed = {{ dummy-1 = "dummy-a" }} + """ + manifest.write_text(toml) + + bin_dir = manifests = tmp_path.joinpath("bin") + bin_dir.mkdir() + broken_exec = bin_dir.joinpath("broken.com") + broken_exec.write_text("Hello world") + if platform.system() != "Windows": + os.chmod(broken_exec, os.stat(broken_exec).st_mode | stat.S_IEXEC) + + verify_cli_command( + [pixi, "global", "sync"], + env=env, + ) + assert not broken_exec.is_file() + + +def test_expose_basic(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" + [envs.test] + channels = ["{dummy_channel_1}"] + dependencies = {{ dummy-a = "*" }} + """ + manifest.write_text(toml) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy1 = tmp_path / "bin" / exec_extension("dummy1") + dummy3 = tmp_path / "bin" / exec_extension("dummy3") + + # Add dummy-a with simple syntax + verify_cli_command( + [pixi, "global", "expose", "add", "--environment=test", "dummy-a"], + ExitCode.SUCCESS, + env=env, + ) + assert dummy_a.is_file() + + # Add dummy1 and dummy3 + verify_cli_command( + [pixi, "global", "expose", "add", "--environment=test", "dummy1=dummy-a", "dummy3=dummy-a"], + env=env, + ) + assert dummy1.is_file() + assert dummy3.is_file() + + # Remove dummy-a + verify_cli_command( + [pixi, "global", "expose", "remove", "dummy-a"], + env=env, + ) + assert not dummy_a.is_file() + + # Remove dummy1 and dummy3 and attempt to remove dummy2 + verify_cli_command( + [pixi, "global", "expose", "remove", "dummy1", "dummy3", "dummy2"], + ExitCode.FAILURE, + env=env, + stderr_contains="Exposed name dummy2 not found in any environment", + ) + assert not dummy1.is_file() + assert not dummy3.is_file() + + +def test_expose_revert_working(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + original_toml = f""" + [envs.test] + channels = ["{dummy_channel_1}"] + dependencies = {{ dummy-a = "*" }} + """ + manifest.write_text(original_toml) + + # Attempt to add executable dummy-b that is not in our dependencies + verify_cli_command( + [pixi, "global", "expose", "add", "--environment=test", "dummy-b=dummy-b"], + ExitCode.FAILURE, + env=env, + stderr_contains=["Couldn't find executable dummy-b in", "test", "executables"], + ) + + # The TOML has been reverted to the original state + assert manifest.read_text() == original_toml + + +def test_expose_preserves_table_format(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + original_toml = f""" +version = {MANIFEST_VERSION} + +[envs.test] +channels = ["{dummy_channel_1}"] +[envs.test.dependencies] +dummy-a = "*" +[envs.test.exposed] +dummy-a = "dummy-a" +""" + manifest.write_text(original_toml) + + verify_cli_command( + [pixi, "global", "expose", "add", "--environment=test", "dummy-aa=dummy-a"], + ExitCode.SUCCESS, + env=env, + ) + print(manifest.read_text()) + # The tables in the manifest have been preserved + assert manifest.read_text() == original_toml + 'dummy-aa = "dummy-a"\n' + + +def test_expose_duplicated_expose_allow_for_same_env( + pixi: Path, tmp_path: Path, dummy_channel_1: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + toml = f""" +version = {MANIFEST_VERSION} + +[envs.one] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*", dummy-b = "*" }} +exposed = {{ dummy-1 = "dummy-a" }} + +[envs.two] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*", dummy-b = "*" }} +exposed = {{ dummy-2 = "dummy-a" }} +""" + manifest.write_text(toml) + + verify_cli_command( + [pixi, "global", "sync"], + env=env, + ) + + # This will not work sinced there would be two times `dummy-2` after this command + verify_cli_command( + [pixi, "global", "expose", "add", "--environment", "one", "dummy-2=dummy-b"], + ExitCode.FAILURE, + env=env, + stderr_contains="Exposed name dummy-2 already exists", + ) + + # This should work, since it just overwrites the existing `dummy-2` mapping + verify_cli_command( + [pixi, "global", "expose", "add", "--environment", "two", "dummy-2=dummy-b"], + env=env, + ) + parsed_toml = tomllib.loads(manifest.read_text()) + assert parsed_toml["envs"]["two"]["exposed"]["dummy-2"] == "dummy-b" + + +def test_install_duplicated_expose_allow_for_same_env( + pixi: Path, tmp_path: Path, dummy_channel_1: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + + verify_cli_command( + [ + pixi, + "global", + "install", + "dummy-a", + "--expose", + "dummy=dummy-a", + "--channel", + dummy_channel_1, + ], + env=env, + ) + + # This will not work sinced there would be two times `dummy` after this command + verify_cli_command( + [ + pixi, + "global", + "install", + "dummy-b", + "--expose", + "dummy=dummy-b", + "--channel", + dummy_channel_1, + ], + ExitCode.FAILURE, + env=env, + stderr_contains="Exposed name dummy already exists", + ) + + # This should work, since it just overwrites the existing properties of environment `dummy-a` + verify_cli_command( + [ + pixi, + "global", + "install", + "dummy-a", + "--expose", + "dummy=dummy-aa", + "--channel", + dummy_channel_1, + "-vvvv", + ], + env=env, + ) + parsed_toml = tomllib.loads(manifest.read_text()) + assert parsed_toml["envs"]["dummy-a"]["exposed"]["dummy"] == "dummy-aa" + + +def test_install_adapts_manifest(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + original_toml = f""" + [envs.test] + channels = ["{dummy_channel_1}"] + dependencies= {{ dummy-b = "*" }} + exposed = {{ dummy-b = "dummy-b" }} + """ + manifest.write_text(original_toml) + + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-a", + ], + env=env, + ) + + assert f"version = {MANIFEST_VERSION}" in manifest.read_text() + + +def test_existing_manifest_gets_version(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifest = manifests.joinpath("pixi-global.toml") + + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-a", + ], + env=env, + ) + + expected_manifest = f"""\ +version = {MANIFEST_VERSION} + +[envs.dummy-a] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*" }} +exposed = {{ dummy-a = "dummy-a", dummy-aa = "dummy-aa" }} +""" + actual_manifest = manifest.read_text() + + # Ensure that the manifest is correctly adapted + assert actual_manifest == expected_manifest + + +def test_install_twice(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + + # Install dummy-b + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b", + ], + env=env, + ) + assert dummy_b.is_file() + + # Install dummy-b again, there should be nothing to do + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b", + ], + env=env, + stderr_contains="The environment dummy-b was already up-to-date", + ) + assert dummy_b.is_file() + + +def test_install_twice_with_force_reinstall( + pixi: Path, tmp_path: Path, dummy_channel_1: str, dummy_channel_2: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + + # Install dummy-b + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b", + ], + env=env, + ) + assert dummy_b.is_file() + + # Modify dummy-b channel and try to install it again + # Even though we changed the channels, it will claim the environment is up-to-date + + manifests = tmp_path / "manifests" / "pixi-global.toml" + parsed_toml = tomllib.loads(manifests.read_text()) + + parsed_toml["envs"]["dummy-b"]["channels"] = [dummy_channel_2] + + manifests.write_text(tomli_w.dumps(parsed_toml)) + + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_2, + "dummy-b", + ], + env=env, + stderr_contains="The environment dummy-b was already up-to-date", + ) + + # Install dummy-b again, but with force-reinstall + # It should install it again + verify_cli_command( + [ + pixi, + "global", + "install", + "--force-reinstall", + "--channel", + dummy_channel_2, + "dummy-b", + ], + env=env, + stderr_contains="Added package dummy-b=0.1.0 to environment dummy-b", + ) + + +def test_install_underscore(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_e = tmp_path / "bin" / exec_extension("dummy_e") + + # Install package `dummy_e` + # It should be installed in environment `dummy-e` + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy_e", + ], + env=env, + ) + assert dummy_e.is_file() + + # Uninstall `dummy_e` + # The `_` will again automatically be converted into an `-` + verify_cli_command( + [ + pixi, + "global", + "uninstall", + "dummy_e", + ], + env=env, + ) + assert not dummy_e.is_file() + + +def test_install_multiple_packages(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_aa = tmp_path / "bin" / exec_extension("dummy-aa") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + dummy_c = tmp_path / "bin" / exec_extension("dummy-c") + + # Install dummy-a and dummy-b, even though dummy-c is a dependency of dummy-b, it should not be exposed + # All of dummy-a's and dummy-b's executables should be exposed though: 'dummy-a', 'dummy-aa' and 'dummy-b' + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-a", + "dummy-b", + ], + env=env, + ) + assert dummy_a.is_file() + assert dummy_aa.is_file() + assert dummy_b.is_file() + assert not dummy_c.is_file() + + +def test_install_expose_single_package(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_aa = tmp_path / "bin" / exec_extension("dummy-aa") + dummy_c = tmp_path / "bin" / exec_extension("dummy-c") + + # Install dummy-a, even though dummy-c is a dependency, it should not be exposed + # All of dummy-a's executables should be exposed though: 'dummy-a' and 'dummy-aa' + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-a", + ], + env=env, + ) + assert dummy_a.is_file() + assert dummy_aa.is_file() + assert not dummy_c.is_file() + + # Install dummy-a, and expose dummy-c explicitly + # Only dummy-c should now be exposed + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--expose", + "dummy-c", + "dummy-a", + ], + env=env, + ) + assert not dummy_a.is_file() + assert not dummy_aa.is_file() + assert dummy_c.is_file() + + # Multiple mappings works as well + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--expose", + "dummy-a", + "--expose", + "dummy-aa", + "--expose", + "dummy-c", + "dummy-a", + ], + env=env, + ) + assert dummy_a.is_file() + assert dummy_aa.is_file() + assert dummy_c.is_file() + + +def test_install_expose_multiple_packages(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + + # Expose doesn't work with multiple environments + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--expose", + "dummy-a", + "dummy-a", + "dummy-b", + ], + ExitCode.FAILURE, + env=env, + stderr_contains="Can't add exposed mappings for more than one environment", + ) + + # But it does work with multiple packages and a single environment + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--environment", + "common-env", + "--expose", + "dummy-a", + "dummy-a", + "dummy-b", + ], + env=env, + ) + + assert dummy_a.is_file() + assert not dummy_b.is_file() + + +def test_install_only_reverts_failing(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + dummy_x = tmp_path / "bin" / exec_extension("dummy-x") + + # dummy-x is not part of dummy_channel_1 + verify_cli_command( + [pixi, "global", "install", "--channel", dummy_channel_1, "dummy-a", "dummy-b", "dummy-x"], + ExitCode.FAILURE, + env=env, + stderr_contains="No candidates were found for dummy-x", + ) + + # dummy-a, dummy-b should be installed, but not dummy-x + assert dummy_a.is_file() + assert dummy_b.is_file() + assert not dummy_x.is_file() + + +def test_install_platform(pixi: Path, tmp_path: Path) -> None: + env = {"PIXI_HOME": str(tmp_path)} + # Exists on win-64 + verify_cli_command( + [pixi, "global", "install", "--platform", "win-64", "binutils=2.40"], + env=env, + ) + + # Doesn't exist on osx-64 + verify_cli_command( + [pixi, "global", "install", "--platform", "osx-64", "binutils=2.40"], + ExitCode.FAILURE, + env=env, + stderr_contains="No candidates were found", + ) + + +def test_install_channels( + pixi: Path, tmp_path: Path, dummy_channel_1: str, dummy_channel_2: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + dummy_x = tmp_path / "bin" / exec_extension("dummy-x") + + # Install dummy-b from dummy-channel-1 + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b", + ], + env=env, + ) + assert dummy_b.is_file() + + # Install dummy-x from dummy-channel-2 + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_2, + "dummy-x", + ], + env=env, + ) + assert dummy_x.is_file() + + # Install dummy-b and dummy-x from dummy-channel-1 and dummy-channel-2 + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--channel", + dummy_channel_2, + "dummy-b", + "dummy-x", + ], + env=env, + ) + assert dummy_b.is_file() + assert dummy_x.is_file() + + +def test_install_multi_env_install(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + # Install dummy-a and dummy-b from dummy-channel-1 this will fail if both environment contains the same package as spec. + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-a", + "dummy-b", + ], + env=env, + ) + + +@pytest.mark.skipif(platform.system() == "Windows", reason="Not reliable on Windows") +def test_pixi_install_cleanup(pixi: Path, tmp_path: Path, global_update_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + package0_1_0 = tmp_path / "bin" / exec_extension("package0.1.0") + package0_2_0 = tmp_path / "bin" / exec_extension("package0.2.0") + + verify_cli_command( + [pixi, "global", "install", "--channel", global_update_channel_1, "package==0.1.0"], + env=env, + ) + assert package0_1_0.is_file() + assert not package0_2_0.is_file() + + # Install the same package but with a different version + # The old version should be removed and the new version should be installed without error. + verify_cli_command( + [pixi, "global", "install", "--channel", global_update_channel_1, "package==0.2.0"], + env=env, + ) + assert not package0_1_0.is_file() + assert package0_2_0.is_file() + + +def test_list(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + + # Verify empty list + verify_cli_command( + [pixi, "global", "list"], + env=env, + stdout_contains="No global environments found.", + ) + + # Install dummy-b from dummy-channel-1 + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b==0.1.0", + "dummy-a==0.1.0", + ], + env=env, + ) + + # Verify list with dummy-b + verify_cli_command( + [pixi, "global", "list"], + env=env, + stdout_contains=["dummy-b: 0.1.0", "dummy-a: 0.1.0", "dummy-a", "dummy-aa"], + ) + + +def test_list_with_filter(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + + # Install dummy-a and dummy-b from dummy-channel-1 + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "dummy-b==0.1.0", + "dummy-a==0.1.0", + ], + env=env, + ) + + # Verify list with dummy-a + verify_cli_command( + [pixi, "global", "list", "dummy-a"], + env=env, + stdout_contains=["dummy-a: 0.1.0", "dummy-a", "dummy-aa"], + stdout_excludes=["dummy-b"], + ) + + # Verify list filter for environment dummy-a. + # It should not contains dummy-b, but should contain dummy-a + verify_cli_command( + [pixi, "global", "list", "--environment", "dummy-a", "dummy"], + env=env, + stdout_contains=["The dummy-a environment", "dummy-a 0.1.0"], + stdout_excludes=["dummy-b"], + ) + + +# Test that we correctly uninstall the required packages +# - Checking that the binaries are removed +# - Checking that the non-requested to remove binaries are still there +def test_uninstall(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + manifests = tmp_path.joinpath("manifests") + manifests.mkdir() + manifest = manifests.joinpath("pixi-global.toml") + original_toml = f""" +version = {MANIFEST_VERSION} +[envs.dummy-a] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-a = "*" }} +exposed = {{ dummy-a = "dummy-a", dummy-aa = "dummy-aa" }} + +[envs.dummy-b] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-b = "*" }} +exposed = {{ dummy-b = "dummy-b" }} + +[envs.dummy-c] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-c = "*" }} +exposed = {{ dummy-c = "dummy-c" }} +""" + manifest.write_text(original_toml) + + verify_cli_command( + [ + pixi, + "global", + "sync", + ], + env=env, + ) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_aa = tmp_path / "bin" / exec_extension("dummy-aa") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + dummy_c = tmp_path / "bin" / exec_extension("dummy-c") + assert dummy_a.is_file() + assert dummy_aa.is_file() + assert dummy_b.is_file() + assert dummy_c.is_file() + + # Uninstall dummy-a + verify_cli_command( + [pixi, "global", "uninstall", "dummy-a"], + env=env, + stderr_contains="Removed environment dummy-a", + ) + assert not dummy_a.is_file() + assert not dummy_aa.is_file() + assert dummy_b.is_file() + assert dummy_c.is_file() + # Verify only the dummy-a environment is removed + assert tmp_path.joinpath("envs", "dummy-b").is_dir() + assert tmp_path.joinpath("envs", "dummy-c").is_dir() + assert not tmp_path.joinpath("envs", "dummy-a").is_dir() + + # Remove dummy-b manually from manifest + modified_toml = f""" +version = {MANIFEST_VERSION} + +[envs.dummy-c] +channels = ["{dummy_channel_1}"] +dependencies = {{ dummy-c = "*" }} +exposed = {{ dummy-c = "dummy-c" }} +""" + manifest.write_text(modified_toml) + + # Uninstall dummy-c + verify_cli_command( + [pixi, "global", "uninstall", "dummy-c"], + env=env, + ) + assert not dummy_a.is_file() + assert not dummy_aa.is_file() + assert not dummy_c.is_file() + # Verify only the dummy-c environment is removed, dummy-b is still there as no sync is run. + assert dummy_b.is_file() + + # Verify empty list + verify_cli_command( + [pixi, "global", "list"], + env=env, + stdout_contains="No global environments found.", + ) + + # Uninstall non-existing package + verify_cli_command( + [pixi, "global", "uninstall", "dummy-a"], + ExitCode.FAILURE, + env=env, + stderr_contains="Couldn't remove dummy-a", + ) + + # Uninstall multiple packages + manifest.write_text(original_toml) + + verify_cli_command( + [ + pixi, + "global", + "sync", + ], + env=env, + ) + assert dummy_a.is_file() + assert dummy_aa.is_file() + assert dummy_b.is_file() + assert dummy_c.is_file() + + verify_cli_command( + [pixi, "global", "uninstall", "dummy-a", "dummy-b"], + env=env, + ) + assert not dummy_a.is_file() + assert not dummy_aa.is_file() + assert not dummy_b.is_file() + assert dummy_c.is_file() + + +def test_uninstall_only_reverts_failing(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + + verify_cli_command( + [pixi, "global", "install", "--channel", dummy_channel_1, "dummy-a", "dummy-b"], + env=env, + ) + + # We did not install dummy-c + verify_cli_command( + [pixi, "global", "uninstall", "dummy-a", "dummy-c"], + ExitCode.FAILURE, + env=env, + stderr_contains="Environment dummy-c doesn't exist", + ) + + # dummy-a has been removed but dummy-b is still there + assert not dummy_a.is_file() + assert not tmp_path.joinpath("envs", "dummy-a").is_dir() + assert dummy_b.is_file() + assert tmp_path.joinpath("envs", "dummy-b").is_dir() + + +def test_global_update_single_package( + pixi: Path, tmp_path: Path, global_update_channel_1: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + # Test update with no environments + verify_cli_command( + [pixi, "global", "update"], + env=env, + ) + + # Test update of a single package + verify_cli_command( + [pixi, "global", "install", "--channel", global_update_channel_1, "package 0.1.0"], + env=env, + ) + # Replace the version with a "*" + manifest = tmp_path.joinpath("manifests", "pixi-global.toml") + manifest.write_text(manifest.read_text().replace("==0.1.0", "*")) + verify_cli_command( + [pixi, "global", "update", "package"], + env=env, + ) + package = tmp_path / "bin" / exec_extension("package") + package0_1_0 = tmp_path / "bin" / exec_extension("package0.1.0") + package0_2_0 = tmp_path / "bin" / exec_extension("package0.2.0") + + # After update be left with only the binary that was in both versions. + assert package.is_file() + assert not package0_1_0.is_file() + # pixi global update doesn't add new exposed mappings + assert not package0_2_0.is_file() + + +def test_global_update_all_packages( + pixi: Path, tmp_path: Path, global_update_channel_1: str +) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + global_update_channel_1, + "package2==0.1.0", + "package==0.1.0", + ], + env=env, + ) + + package = tmp_path / "bin" / exec_extension("package") + package0_1_0 = tmp_path / "bin" / exec_extension("package0.1.0") + package0_2_0 = tmp_path / "bin" / exec_extension("package0.2.0") + package2 = tmp_path / "bin" / exec_extension("package2") + assert package2.is_file() + assert package.is_file() + assert package0_1_0.is_file() + assert not package0_2_0.is_file() + + # Replace the version with a "*" + manifest = tmp_path.joinpath("manifests", "pixi-global.toml") + manifest.write_text(manifest.read_text().replace("==0.1.0", "*")) + + verify_cli_command( + [pixi, "global", "update"], + env=env, + ) + assert package2.is_file() + assert package.is_file() + assert not package0_1_0.is_file() + # After update be left with only the binary that was in both versions. + assert not package0_2_0.is_file() + + # Check the manifest for removed binaries + manifest_content = manifest.read_text() + assert "package0.1.0" not in manifest_content + assert "package0.2.0" not in manifest_content + assert "package2" in manifest_content + assert "package" in manifest_content + + # Check content of package2 file to be updated + bin_file_package2 = tmp_path / "envs" / "package2" / "bin" / exec_extension("package2") + assert "0.2.0" in bin_file_package2.read_text() + + +def test_pixi_update_cleanup(pixi: Path, tmp_path: Path, global_update_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + package0_1_0 = tmp_path / "bin" / exec_extension("package0.1.0") + package0_2_0 = tmp_path / "bin" / exec_extension("package0.2.0") + + verify_cli_command( + [pixi, "global", "install", "--channel", global_update_channel_1, "package==0.1.0"], + env=env, + ) + assert package0_1_0.is_file() + assert not package0_2_0.is_file() + + manifest = tmp_path.joinpath("manifests", "pixi-global.toml") + + # We change the matchspec to '*' + # Syncing shouldn't do anything + parsed_toml = tomllib.loads(manifest.read_text()) + parsed_toml["envs"]["package"]["dependencies"]["package"] = "*" + manifest.write_text(tomli_w.dumps(parsed_toml)) + verify_cli_command([pixi, "global", "sync"], env=env) + assert package0_1_0.is_file() + assert not package0_2_0.is_file() + + # Update the environment + # The package should now have the version `0.2.0` and expose a different executable + # The old executable should be removed + # The new executable will also not be there, since `pixi global update` doesn't add new exposed mappings to the manifest. + verify_cli_command( + [pixi, "global", "update", "package"], + env=env, + ) + assert not package0_1_0.is_file() + assert not package0_2_0.is_file() + + +def test_auto_self_expose(pixi: Path, tmp_path: Path, non_self_expose_channel: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + # Install jupyter and expose it as 'jupyter' + verify_cli_command( + [pixi, "global", "install", "--channel", non_self_expose_channel, "jupyter"], + env=env, + ) + jupyter = tmp_path / "bin" / exec_extension("jupyter") + assert jupyter.is_file() + + +def test_add(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + # Can't add package to environment that doesn't exist + verify_cli_command( + [pixi, "global", "add", "--environment", "dummy-a", "dummy-b"], + ExitCode.FAILURE, + env=env, + stderr_contains="Environment dummy-a doesn't exist", + ) + + verify_cli_command( + [pixi, "global", "install", "--channel", dummy_channel_1, "dummy-a"], + env=env, + ) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + assert dummy_a.is_file() + + verify_cli_command( + [pixi, "global", "add", "--environment", "dummy-a", "dummy-b"], + env=env, + stderr_contains="Added package dummy-b", + ) + # Make sure it doesn't expose a binary from this package + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + assert not dummy_b.is_file() + + verify_cli_command( + [ + pixi, + "global", + "add", + "--environment", + "dummy-a", + "dummy-b", + "--expose", + "dummy-b", + ], + env=env, + stderr_contains="Exposed executable dummy-b from environment dummy-a", + ) + # Make sure it now exposes the binary + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + assert dummy_b.is_file() + + +def test_remove_dependency(pixi: Path, tmp_path: Path, dummy_channel_1: str) -> None: + env = {"PIXI_HOME": str(tmp_path)} + + verify_cli_command( + [ + pixi, + "global", + "install", + "--channel", + dummy_channel_1, + "--environment", + "my-env", + "dummy-a", + "dummy-b", + ], + env=env, + ) + dummy_a = tmp_path / "bin" / exec_extension("dummy-a") + dummy_b = tmp_path / "bin" / exec_extension("dummy-b") + assert dummy_a.is_file() + assert dummy_b.is_file() + + # Remove dummy-a + verify_cli_command( + [pixi, "global", "remove", "--environment", "my-env", "dummy-a"], + env=env, + ) + assert not dummy_a.is_file() + + # Remove non-existing package + verify_cli_command( + [pixi, "global", "remove", "--environment", "my-env", "dummy-a"], + ExitCode.FAILURE, + env=env, + stderr_contains=["Dependency", "dummy-a", "not", "my-env"], + ) + + # Remove package from non-existing environment + verify_cli_command( + [pixi, "global", "remove", "--environment", "dummy-a", "dummy-a"], + ExitCode.FAILURE, + env=env, + stderr_contains="Environment dummy-a doesn't exist", + ) diff --git a/tests/integration/test_main_cli.py b/tests/integration/test_main_cli.py index 64d8174b8..1bb657e50 100644 --- a/tests/integration/test_main_cli.py +++ b/tests/integration/test_main_cli.py @@ -1,5 +1,4 @@ from pathlib import Path - from .common import verify_cli_command, ExitCode, PIXI_VERSION @@ -10,7 +9,7 @@ def test_pixi(pixi: Path) -> None: verify_cli_command([pixi, "--version"], ExitCode.SUCCESS, stdout_contains=PIXI_VERSION) -def test_project_commands(tmp_path: Path, pixi: Path) -> None: +def test_project_commands(pixi: Path, tmp_path: Path) -> None: manifest_path = tmp_path / "pixi.toml" # Create a new project verify_cli_command([pixi, "init", tmp_path], ExitCode.SUCCESS) @@ -164,48 +163,6 @@ def test_project_commands(tmp_path: Path, pixi: Path) -> None: ) -def test_global_install(pixi: Path) -> None: - # Install - verify_cli_command( - [pixi, "global", "install", "rattler-build"], - ExitCode.SUCCESS, - stdout_excludes="rattler-build", - ) - - verify_cli_command( - [ - pixi, - "global", - "install", - "rattler-build", - "-c", - "https://fast.prefix.dev/conda-forge", - ], - ExitCode.SUCCESS, - stdout_excludes="rattler-build", - ) - - # Install with --no-activation - verify_cli_command( - [pixi, "global", "install", "rattler-build", "--no-activation"], - ExitCode.SUCCESS, - stdout_excludes="rattler-build", - ) - - # Upgrade - verify_cli_command([pixi, "global", "upgrade", "rattler-build"], ExitCode.SUCCESS) - - # Upgrade all - verify_cli_command([pixi, "global", "upgrade-all"], ExitCode.SUCCESS) - - # List - verify_cli_command([pixi, "global", "list"], ExitCode.SUCCESS, stderr_contains="rattler-build") - - # Remove - verify_cli_command([pixi, "global", "remove", "rattler-build"], ExitCode.SUCCESS) - verify_cli_command([pixi, "global", "remove", "rattler-build"], ExitCode.FAILURE) - - def test_search(pixi: Path) -> None: verify_cli_command( [pixi, "search", "rattler-build", "-c", "conda-forge"], @@ -219,7 +176,7 @@ def test_search(pixi: Path) -> None: ) -def test_simple_project_setup(tmp_path: Path, pixi: Path) -> None: +def test_simple_project_setup(pixi: Path, tmp_path: Path) -> None: manifest_path = tmp_path / "pixi.toml" # Create a new project verify_cli_command([pixi, "init", tmp_path], ExitCode.SUCCESS) @@ -321,7 +278,7 @@ def test_simple_project_setup(tmp_path: Path, pixi: Path) -> None: ) -def test_pixi_init_pyproject(tmp_path: Path, pixi: Path) -> None: +def test_pixi_init_pyproject(pixi: Path, tmp_path: Path) -> None: manifest_path = tmp_path / "pyproject.toml" # Create a new project verify_cli_command([pixi, "init", tmp_path, "--format", "pyproject"], ExitCode.SUCCESS)