mirror of https://github.com/astral-sh/uv
Collect and upload PEP 740 attestations during `uv publish` (#16731)
Co-authored-by: konsti <konstin@mailbox.org>
This commit is contained in:
parent
4b92f4fde4
commit
7b3199f07c
|
|
@ -6432,6 +6432,7 @@ dependencies = [
|
||||||
"astral-tokio-tar",
|
"astral-tokio-tar",
|
||||||
"async-compression",
|
"async-compression",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
|
"fastrand",
|
||||||
"fs-err",
|
"fs-err",
|
||||||
"futures",
|
"futures",
|
||||||
"glob",
|
"glob",
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ dunce = { version = "1.0.5" }
|
||||||
either = { version = "1.13.0" }
|
either = { version = "1.13.0" }
|
||||||
encoding_rs_io = { version = "0.1.7" }
|
encoding_rs_io = { version = "0.1.7" }
|
||||||
etcetera = { version = "0.11.0" }
|
etcetera = { version = "0.11.0" }
|
||||||
|
fastrand = { version = "2.3.0" }
|
||||||
flate2 = { version = "1.0.33", default-features = false, features = ["zlib-rs"] }
|
flate2 = { version = "1.0.33", default-features = false, features = ["zlib-rs"] }
|
||||||
fs-err = { version = "3.0.0", features = ["tokio"] }
|
fs-err = { version = "3.0.0", features = ["tokio"] }
|
||||||
futures = { version = "0.3.30" }
|
futures = { version = "0.3.30" }
|
||||||
|
|
|
||||||
|
|
@ -7040,8 +7040,8 @@ pub struct DisplayTreeArgs {
|
||||||
pub struct PublishArgs {
|
pub struct PublishArgs {
|
||||||
/// Paths to the files to upload. Accepts glob expressions.
|
/// Paths to the files to upload. Accepts glob expressions.
|
||||||
///
|
///
|
||||||
/// Defaults to the `dist` directory. Selects only wheels and source distributions, while
|
/// Defaults to the `dist` directory. Selects only wheels and source distributions
|
||||||
/// ignoring other files.
|
/// and their attestations, while ignoring other files.
|
||||||
#[arg(default_value = "dist/*")]
|
#[arg(default_value = "dist/*")]
|
||||||
pub files: Vec<String>,
|
pub files: Vec<String>,
|
||||||
|
|
||||||
|
|
@ -7147,6 +7147,13 @@ pub struct PublishArgs {
|
||||||
/// and will perform validation against the index if supported, but will not upload any files.
|
/// and will perform validation against the index if supported, but will not upload any files.
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub dry_run: bool,
|
pub dry_run: bool,
|
||||||
|
|
||||||
|
/// Do not upload attestations for the published files.
|
||||||
|
///
|
||||||
|
/// By default, uv attempts to upload matching PEP 740 attestations with each distribution
|
||||||
|
/// that is published.
|
||||||
|
#[arg(long, env = EnvVars::UV_PUBLISH_NO_ATTESTATIONS)]
|
||||||
|
pub no_attestations: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ zeroize = { workspace = true }
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
doc-comment = "0.3"
|
doc-comment = "0.3"
|
||||||
env_logger = "0.11.5"
|
env_logger = "0.11.5"
|
||||||
fastrand = "2"
|
fastrand = { workspace = true }
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
default-target = "x86_64-unknown-linux-gnu"
|
default-target = "x86_64-unknown-linux-gnu"
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ url = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = { workspace = true }
|
insta = { workspace = true }
|
||||||
|
fastrand = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# Test only feature to enable non-HTTPS URL handling
|
# Test only feature to enable non-HTTPS URL handling
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
mod trusted_publishing;
|
mod trusted_publishing;
|
||||||
|
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
@ -14,7 +15,7 @@ use reqwest::multipart::Part;
|
||||||
use reqwest::{Body, Response, StatusCode};
|
use reqwest::{Body, Response, StatusCode};
|
||||||
use reqwest_retry::policies::ExponentialBackoff;
|
use reqwest_retry::policies::ExponentialBackoff;
|
||||||
use reqwest_retry::{RetryPolicy, Retryable, RetryableStrategy};
|
use reqwest_retry::{RetryPolicy, Retryable, RetryableStrategy};
|
||||||
use rustc_hash::FxHashSet;
|
use rustc_hash::FxHashMap;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::io::{AsyncReadExt, BufReader};
|
use tokio::io::{AsyncReadExt, BufReader};
|
||||||
|
|
@ -57,11 +58,19 @@ pub enum PublishError {
|
||||||
#[error("Failed to publish: `{}`", _0.user_display())]
|
#[error("Failed to publish: `{}`", _0.user_display())]
|
||||||
PublishPrepare(PathBuf, #[source] Box<PublishPrepareError>),
|
PublishPrepare(PathBuf, #[source] Box<PublishPrepareError>),
|
||||||
#[error("Failed to publish `{}` to {}", _0.user_display(), _1)]
|
#[error("Failed to publish `{}` to {}", _0.user_display(), _1)]
|
||||||
PublishSend(PathBuf, DisplaySafeUrl, #[source] PublishSendError),
|
PublishSend(
|
||||||
|
PathBuf,
|
||||||
|
Box<DisplaySafeUrl>,
|
||||||
|
#[source] Box<PublishSendError>,
|
||||||
|
),
|
||||||
#[error("Unable to publish `{}` to {}", _0.user_display(), _1)]
|
#[error("Unable to publish `{}` to {}", _0.user_display(), _1)]
|
||||||
Validate(PathBuf, DisplaySafeUrl, #[source] PublishSendError),
|
Validate(
|
||||||
|
PathBuf,
|
||||||
|
Box<DisplaySafeUrl>,
|
||||||
|
#[source] Box<PublishSendError>,
|
||||||
|
),
|
||||||
#[error("Failed to obtain token for trusted publishing")]
|
#[error("Failed to obtain token for trusted publishing")]
|
||||||
TrustedPublishing(#[from] TrustedPublishingError),
|
TrustedPublishing(#[from] Box<TrustedPublishingError>),
|
||||||
#[error("{0} are not allowed when using trusted publishing")]
|
#[error("{0} are not allowed when using trusted publishing")]
|
||||||
MixedCredentials(String),
|
MixedCredentials(String),
|
||||||
#[error("Failed to query check URL")]
|
#[error("Failed to query check URL")]
|
||||||
|
|
@ -99,6 +108,8 @@ pub enum PublishPrepareError {
|
||||||
MultiplePkgInfo(String),
|
MultiplePkgInfo(String),
|
||||||
#[error("Failed to read: `{0}`")]
|
#[error("Failed to read: `{0}`")]
|
||||||
Read(String, #[source] io::Error),
|
Read(String, #[source] io::Error),
|
||||||
|
#[error("Invalid PEP 740 attestation (not JSON): `{0}`")]
|
||||||
|
InvalidAttestation(PathBuf, #[source] serde_json::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Failure in or after (HTTP) transport for a specific file.
|
/// Failure in or after (HTTP) transport for a specific file.
|
||||||
|
|
@ -239,34 +250,72 @@ impl PublishSendError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Collect the source distributions and wheels for publishing.
|
/// Represents a single "to-be-uploaded" distribution, along with zero
|
||||||
///
|
/// or more attestations that will be uploaded alongside it.
|
||||||
/// Returns the path, the raw filename and the parsed filename. The raw filename is a fixup for
|
#[derive(Debug)]
|
||||||
/// <https://github.com/astral-sh/uv/issues/8030> caused by
|
pub struct UploadDistribution {
|
||||||
/// <https://github.com/pypa/setuptools/issues/3777> in combination with
|
/// The path to the main distribution file to upload.
|
||||||
/// <https://github.com/pypi/warehouse/blob/50a58f3081e693a3772c0283050a275e350004bf/warehouse/forklift/legacy.py#L1133-L1155>
|
pub file: PathBuf,
|
||||||
#[allow(clippy::result_large_err)]
|
/// The raw filename of the main distribution file.
|
||||||
pub fn files_for_publishing(
|
pub raw_filename: String,
|
||||||
paths: Vec<String>,
|
/// The parsed filename of the main distribution file.
|
||||||
) -> Result<Vec<(PathBuf, String, DistFilename)>, PublishError> {
|
pub filename: DistFilename,
|
||||||
let mut seen = FxHashSet::default();
|
/// Zero or more paths to PEP 740 attestations for the distribution.
|
||||||
let mut files = Vec::new();
|
pub attestations: Vec<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a list of paths (which may contain globs), unroll them into
|
||||||
|
/// a flat, unique list of files. Files are returned in a stable
|
||||||
|
/// but unspecified order.
|
||||||
|
fn unroll_paths(paths: Vec<String>) -> Result<Vec<PathBuf>, PublishError> {
|
||||||
|
let mut files = BTreeSet::default();
|
||||||
for path in paths {
|
for path in paths {
|
||||||
for dist in glob(&path).map_err(|err| PublishError::Pattern(path, err))? {
|
for file in glob(&path).map_err(|err| PublishError::Pattern(path.clone(), err))? {
|
||||||
let dist = dist?;
|
let file = file?;
|
||||||
if !dist.is_file() {
|
if !file.is_file() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !seen.insert(dist.clone()) {
|
|
||||||
continue;
|
files.insert(file);
|
||||||
}
|
}
|
||||||
let Some(filename) = dist
|
}
|
||||||
|
|
||||||
|
Ok(files.into_iter().collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a flat list of input files, merge them into a list of [`UploadDistribution`]s.
|
||||||
|
fn group_files(files: Vec<PathBuf>, no_attestations: bool) -> Vec<UploadDistribution> {
|
||||||
|
let mut groups = FxHashMap::default();
|
||||||
|
let mut attestations_by_dist = FxHashMap::default();
|
||||||
|
for file in files {
|
||||||
|
let Some(filename) = file
|
||||||
.file_name()
|
.file_name()
|
||||||
.and_then(|filename| filename.to_str())
|
.and_then(|filename| filename.to_str())
|
||||||
.map(ToString::to_string)
|
.map(ToString::to_string)
|
||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Attestations are named as `<dist>.<type>.attestation`, e.g.
|
||||||
|
// `foo-1.2.3.tar.gz.publish.attestation`.
|
||||||
|
// We use this to build up a map of `dist -> [attestations]`
|
||||||
|
// for subsequent merging.
|
||||||
|
let mut filename_parts = filename.rsplitn(3, '.');
|
||||||
|
if filename_parts.next() == Some("attestation")
|
||||||
|
&& let Some(_) = filename_parts.next()
|
||||||
|
&& let Some(dist_name) = filename_parts.next()
|
||||||
|
{
|
||||||
|
debug!(
|
||||||
|
"Found attestation for distribution: `{}` -> `{}`",
|
||||||
|
file.user_display(),
|
||||||
|
dist_name
|
||||||
|
);
|
||||||
|
|
||||||
|
attestations_by_dist
|
||||||
|
.entry(dist_name.to_string())
|
||||||
|
.or_insert_with(Vec::new)
|
||||||
|
.push(file);
|
||||||
|
} else {
|
||||||
let Some(dist_filename) = DistFilename::try_from_normalized_filename(&filename) else {
|
let Some(dist_filename) = DistFilename::try_from_normalized_filename(&filename) else {
|
||||||
debug!("Not a distribution filename: `{filename}`");
|
debug!("Not a distribution filename: `{filename}`");
|
||||||
// I've never seen these in upper case
|
// I've never seen these in upper case
|
||||||
|
|
@ -281,18 +330,51 @@ pub fn files_for_publishing(
|
||||||
warn_user!(
|
warn_user!(
|
||||||
"Skipping file that looks like a distribution, \
|
"Skipping file that looks like a distribution, \
|
||||||
but is not a valid distribution filename: `{}`",
|
but is not a valid distribution filename: `{}`",
|
||||||
dist.user_display()
|
file.user_display()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
files.push((dist, filename, dist_filename));
|
|
||||||
|
groups.insert(
|
||||||
|
filename.clone(),
|
||||||
|
UploadDistribution {
|
||||||
|
file,
|
||||||
|
raw_filename: filename,
|
||||||
|
filename: dist_filename,
|
||||||
|
attestations: Vec::new(),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO(konsti): Should we sort those files, e.g. wheels before sdists because they are more
|
|
||||||
// certain to have reliable metadata, even though the metadata in the upload API is unreliable
|
if no_attestations {
|
||||||
// in general?
|
debug!("Not merging attestations with distributions per user request");
|
||||||
Ok(files)
|
} else {
|
||||||
|
// Merge attestations into their respective upload groups.
|
||||||
|
for (dist_name, attestations) in attestations_by_dist {
|
||||||
|
if let Some(group) = groups.get_mut(&dist_name) {
|
||||||
|
group.attestations = attestations;
|
||||||
|
group.attestations.sort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.into_values().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Collect the source distributions and wheels for publishing.
|
||||||
|
///
|
||||||
|
/// Returns an [`UploadGroup`] for each distribution to be published.
|
||||||
|
/// This group contains the path, the raw filename and the parsed filename. The raw filename is a fixup for
|
||||||
|
/// <https://github.com/astral-sh/uv/issues/8030> caused by
|
||||||
|
/// <https://github.com/pypa/setuptools/issues/3777> in combination with
|
||||||
|
/// <https://github.com/pypi/warehouse/blob/50a58f3081e693a3772c0283050a275e350004bf/warehouse/forklift/legacy.py#L1133-L1155>
|
||||||
|
pub fn group_files_for_publishing(
|
||||||
|
paths: Vec<String>,
|
||||||
|
no_attestations: bool,
|
||||||
|
) -> Result<Vec<UploadDistribution>, PublishError> {
|
||||||
|
Ok(group_files(unroll_paths(paths)?, no_attestations))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum TrustedPublishResult {
|
pub enum TrustedPublishResult {
|
||||||
|
|
@ -357,10 +439,11 @@ pub async fn check_trusted_publishing(
|
||||||
|
|
||||||
let Some(token) =
|
let Some(token) =
|
||||||
trusted_publishing::get_token(registry, client.for_host(registry).raw_client())
|
trusted_publishing::get_token(registry, client.for_host(registry).raw_client())
|
||||||
.await?
|
.await
|
||||||
|
.map_err(Box::new)?
|
||||||
else {
|
else {
|
||||||
return Err(PublishError::TrustedPublishing(
|
return Err(PublishError::TrustedPublishing(
|
||||||
TrustedPublishingError::NoToken,
|
TrustedPublishingError::NoToken.into(),
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -376,10 +459,8 @@ pub async fn check_trusted_publishing(
|
||||||
///
|
///
|
||||||
/// Implements a custom retry flow since the request isn't cloneable.
|
/// Implements a custom retry flow since the request isn't cloneable.
|
||||||
pub async fn upload(
|
pub async fn upload(
|
||||||
file: &Path,
|
group: &UploadDistribution,
|
||||||
form_metadata: &FormMetadata,
|
form_metadata: &FormMetadata,
|
||||||
raw_filename: &str,
|
|
||||||
filename: &DistFilename,
|
|
||||||
registry: &DisplaySafeUrl,
|
registry: &DisplaySafeUrl,
|
||||||
client: &BaseClient,
|
client: &BaseClient,
|
||||||
retry_policy: ExponentialBackoff,
|
retry_policy: ExponentialBackoff,
|
||||||
|
|
@ -392,9 +473,7 @@ pub async fn upload(
|
||||||
let start_time = SystemTime::now();
|
let start_time = SystemTime::now();
|
||||||
loop {
|
loop {
|
||||||
let (request, idx) = build_upload_request(
|
let (request, idx) = build_upload_request(
|
||||||
file,
|
group,
|
||||||
raw_filename,
|
|
||||||
filename,
|
|
||||||
registry,
|
registry,
|
||||||
client,
|
client,
|
||||||
credentials,
|
credentials,
|
||||||
|
|
@ -402,7 +481,7 @@ pub async fn upload(
|
||||||
reporter.clone(),
|
reporter.clone(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PublishError::PublishPrepare(file.to_path_buf(), Box::new(err)))?;
|
.map_err(|err| PublishError::PublishPrepare(group.file.clone(), Box::new(err)))?;
|
||||||
|
|
||||||
let result = request.send().await;
|
let result = request.send().await;
|
||||||
if UvRetryableStrategy.handle(&result) == Some(Retryable::Transient) {
|
if UvRetryableStrategy.handle(&result) == Some(Retryable::Transient) {
|
||||||
|
|
@ -425,9 +504,9 @@ pub async fn upload(
|
||||||
|
|
||||||
let response = result.map_err(|err| {
|
let response = result.map_err(|err| {
|
||||||
PublishError::PublishSend(
|
PublishError::PublishSend(
|
||||||
file.to_path_buf(),
|
group.file.clone(),
|
||||||
registry.clone(),
|
registry.clone().into(),
|
||||||
PublishSendError::ReqwestMiddleware(err),
|
PublishSendError::ReqwestMiddleware(err).into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
|
@ -443,7 +522,13 @@ pub async fn upload(
|
||||||
PublishSendError::Status(..) | PublishSendError::StatusNoBody(..)
|
PublishSendError::Status(..) | PublishSendError::StatusNoBody(..)
|
||||||
) {
|
) {
|
||||||
if let Some(check_url_client) = &check_url_client {
|
if let Some(check_url_client) = &check_url_client {
|
||||||
if check_url(check_url_client, file, filename, download_concurrency).await?
|
if check_url(
|
||||||
|
check_url_client,
|
||||||
|
&group.file,
|
||||||
|
&group.filename,
|
||||||
|
download_concurrency,
|
||||||
|
)
|
||||||
|
.await?
|
||||||
{
|
{
|
||||||
// There was a raced upload of the same file, so even though our upload failed,
|
// There was a raced upload of the same file, so even though our upload failed,
|
||||||
// the right file now exists in the registry.
|
// the right file now exists in the registry.
|
||||||
|
|
@ -452,9 +537,9 @@ pub async fn upload(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(PublishError::PublishSend(
|
Err(PublishError::PublishSend(
|
||||||
file.to_path_buf(),
|
group.file.clone(),
|
||||||
registry.clone(),
|
registry.clone().into(),
|
||||||
err,
|
err.into(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -491,14 +576,16 @@ pub async fn validate(
|
||||||
let response = request.send().await.map_err(|err| {
|
let response = request.send().await.map_err(|err| {
|
||||||
PublishError::Validate(
|
PublishError::Validate(
|
||||||
file.to_path_buf(),
|
file.to_path_buf(),
|
||||||
registry.clone(),
|
registry.clone().into(),
|
||||||
PublishSendError::ReqwestMiddleware(err),
|
PublishSendError::ReqwestMiddleware(err).into(),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
handle_response(&validation_url, response)
|
handle_response(&validation_url, response)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PublishError::Validate(file.to_path_buf(), registry.clone(), err))?;
|
.map_err(|err| {
|
||||||
|
PublishError::Validate(file.to_path_buf(), registry.clone().into(), err.into())
|
||||||
|
})?;
|
||||||
} else {
|
} else {
|
||||||
debug!("Skipping validation request for unsupported publish URL: {registry}");
|
debug!("Skipping validation request for unsupported publish URL: {registry}");
|
||||||
}
|
}
|
||||||
|
|
@ -836,9 +923,7 @@ impl<'a> IntoIterator for &'a FormMetadata {
|
||||||
///
|
///
|
||||||
/// Returns the [`RequestBuilder`] and the reporter progress bar ID.
|
/// Returns the [`RequestBuilder`] and the reporter progress bar ID.
|
||||||
async fn build_upload_request<'a>(
|
async fn build_upload_request<'a>(
|
||||||
file: &Path,
|
group: &UploadDistribution,
|
||||||
raw_filename: &str,
|
|
||||||
filename: &DistFilename,
|
|
||||||
registry: &DisplaySafeUrl,
|
registry: &DisplaySafeUrl,
|
||||||
client: &'a BaseClient,
|
client: &'a BaseClient,
|
||||||
credentials: &Credentials,
|
credentials: &Credentials,
|
||||||
|
|
@ -850,9 +935,9 @@ async fn build_upload_request<'a>(
|
||||||
form = form.text(*key, value.clone());
|
form = form.text(*key, value.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let file = File::open(file).await?;
|
let file = File::open(&group.file).await?;
|
||||||
let file_size = file.metadata().await?.len();
|
let file_size = file.metadata().await?.len();
|
||||||
let idx = reporter.on_upload_start(&filename.to_string(), Some(file_size));
|
let idx = reporter.on_upload_start(&group.filename.to_string(), Some(file_size));
|
||||||
let reader = ProgressReader::new(file, move |read| {
|
let reader = ProgressReader::new(file, move |read| {
|
||||||
reporter.on_upload_progress(idx, read as u64);
|
reporter.on_upload_progress(idx, read as u64);
|
||||||
});
|
});
|
||||||
|
|
@ -860,9 +945,27 @@ async fn build_upload_request<'a>(
|
||||||
// a lifetime) -> callback needs to be static -> reporter reference needs to be Arc'd.
|
// a lifetime) -> callback needs to be static -> reporter reference needs to be Arc'd.
|
||||||
let file_reader = Body::wrap_stream(ReaderStream::new(reader));
|
let file_reader = Body::wrap_stream(ReaderStream::new(reader));
|
||||||
// See [`files_for_publishing`] on `raw_filename`
|
// See [`files_for_publishing`] on `raw_filename`
|
||||||
let part = Part::stream_with_length(file_reader, file_size).file_name(raw_filename.to_string());
|
let part =
|
||||||
|
Part::stream_with_length(file_reader, file_size).file_name(group.raw_filename.clone());
|
||||||
form = form.part("content", part);
|
form = form.part("content", part);
|
||||||
|
|
||||||
|
let mut attestations = vec![];
|
||||||
|
for attestation_path in &group.attestations {
|
||||||
|
let contents = fs_err::read_to_string(attestation_path)?;
|
||||||
|
// NOTE: We don't currently validate the interior structure of an attestation beyond being
|
||||||
|
// valid JSON. We could validate it pretty easily in the future.
|
||||||
|
let raw_attestation = serde_json::from_str::<serde_json::Value>(&contents)
|
||||||
|
.map_err(|err| PublishPrepareError::InvalidAttestation(attestation_path.into(), err))?;
|
||||||
|
attestations.push(raw_attestation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !attestations.is_empty() {
|
||||||
|
// PEP 740 specifies the `attestations` field as a JSON array of attestation objects.
|
||||||
|
let attestations_json =
|
||||||
|
serde_json::to_string(&attestations).expect("Round-trip of PEP 740 attestation failed");
|
||||||
|
form = form.text("attestations", attestations_json);
|
||||||
|
}
|
||||||
|
|
||||||
// If we have a username but no password, attach the username to the URL so the authentication
|
// If we have a username but no password, attach the username to the URL so the authentication
|
||||||
// middleware can find the matching password.
|
// middleware can find the matching password.
|
||||||
let url = if let Some(username) = credentials
|
let url = if let Some(username) = credentials
|
||||||
|
|
@ -1032,7 +1135,7 @@ mod tests {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use insta::{assert_debug_snapshot, assert_snapshot};
|
use insta::{allow_duplicates, assert_debug_snapshot, assert_snapshot};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use uv_auth::Credentials;
|
use uv_auth::Credentials;
|
||||||
|
|
@ -1040,7 +1143,7 @@ mod tests {
|
||||||
use uv_distribution_filename::DistFilename;
|
use uv_distribution_filename::DistFilename;
|
||||||
use uv_redacted::DisplaySafeUrl;
|
use uv_redacted::DisplaySafeUrl;
|
||||||
|
|
||||||
use crate::{FormMetadata, Reporter, build_upload_request};
|
use crate::{FormMetadata, Reporter, UploadDistribution, build_upload_request, group_files};
|
||||||
|
|
||||||
struct DummyReporter;
|
struct DummyReporter;
|
||||||
|
|
||||||
|
|
@ -1053,14 +1156,303 @@ mod tests {
|
||||||
fn on_upload_complete(&self, _id: usize) {}
|
fn on_upload_complete(&self, _id: usize) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_group_files() {
|
||||||
|
// Fisher-Yates shuffle.
|
||||||
|
fn shuffle<T>(vec: &mut [T]) {
|
||||||
|
let n: usize = vec.len();
|
||||||
|
for i in 0..(n - 1) {
|
||||||
|
#[allow(clippy::cast_possible_truncation)]
|
||||||
|
let j = (fastrand::usize(..)) % (n - i) + i;
|
||||||
|
vec.swap(i, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let valid_sdist = "dist/acme-1.2.3.tar.gz";
|
||||||
|
let valid_sdist_publish_attestation = format!("{valid_sdist}.publish.attestation");
|
||||||
|
let valid_sdist_build_attestation = format!("{valid_sdist}.build.attestation");
|
||||||
|
let valid_sdist_frob_attestation = format!("{valid_sdist}.frob.attestation");
|
||||||
|
|
||||||
|
let valid_wheel = "dist/acme-1.2.3-py3-none-any.whl";
|
||||||
|
let valid_wheel_publish_attestation = format!("{valid_wheel}.publish.attestation");
|
||||||
|
let valid_wheel_build_attestation = format!("{valid_wheel}.build.attestation");
|
||||||
|
let valid_wheel_frob_attestation = format!("{valid_wheel}.frob.attestation");
|
||||||
|
|
||||||
|
let invalid_sdist = "dist/nudnik.tar.gz";
|
||||||
|
let invalid_wheel = "dist/nudnik.whl";
|
||||||
|
let valid_sdist_invalid_attestation = format!("{valid_sdist}.attestation");
|
||||||
|
let invalid_attestation = "dist/nudnik.attestation";
|
||||||
|
|
||||||
|
// Valid sdists/wheels without attestations
|
||||||
|
{
|
||||||
|
let dists = [valid_sdist, valid_wheel];
|
||||||
|
|
||||||
|
let mut groups = group_files(dists.iter().map(PathBuf::from).collect(), false);
|
||||||
|
groups.sort_by_key(|group| group.raw_filename.clone());
|
||||||
|
|
||||||
|
assert_debug_snapshot!(groups, @r#"
|
||||||
|
[
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3-py3-none-any.whl",
|
||||||
|
raw_filename: "acme-1.2.3-py3-none-any.whl",
|
||||||
|
filename: WheelFilename(
|
||||||
|
WheelFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
tags: Small {
|
||||||
|
small: WheelTagSmall {
|
||||||
|
python_tag: Python {
|
||||||
|
major: 3,
|
||||||
|
minor: None,
|
||||||
|
},
|
||||||
|
abi_tag: None,
|
||||||
|
platform_tag: Any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3.tar.gz",
|
||||||
|
raw_filename: "acme-1.2.3.tar.gz",
|
||||||
|
filename: SourceDistFilename(
|
||||||
|
SourceDistFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
extension: TarGz,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid sdists/wheels with attestations in various orders.
|
||||||
|
{
|
||||||
|
let mut dists = vec![
|
||||||
|
valid_sdist,
|
||||||
|
&valid_sdist_publish_attestation,
|
||||||
|
&valid_sdist_build_attestation,
|
||||||
|
&valid_sdist_frob_attestation,
|
||||||
|
valid_wheel,
|
||||||
|
&valid_wheel_build_attestation,
|
||||||
|
&valid_wheel_publish_attestation,
|
||||||
|
&valid_wheel_frob_attestation,
|
||||||
|
];
|
||||||
|
|
||||||
|
allow_duplicates! {
|
||||||
|
for _ in 0..5 {
|
||||||
|
shuffle(&mut dists);
|
||||||
|
|
||||||
|
let mut groups =
|
||||||
|
group_files(dists.iter().map(PathBuf::from).collect(), false);
|
||||||
|
groups.sort_by_key(|group| group.raw_filename.clone());
|
||||||
|
|
||||||
|
assert_debug_snapshot!(groups, @r#"
|
||||||
|
[
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3-py3-none-any.whl",
|
||||||
|
raw_filename: "acme-1.2.3-py3-none-any.whl",
|
||||||
|
filename: WheelFilename(
|
||||||
|
WheelFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
tags: Small {
|
||||||
|
small: WheelTagSmall {
|
||||||
|
python_tag: Python {
|
||||||
|
major: 3,
|
||||||
|
minor: None,
|
||||||
|
},
|
||||||
|
abi_tag: None,
|
||||||
|
platform_tag: Any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [
|
||||||
|
"dist/acme-1.2.3-py3-none-any.whl.build.attestation",
|
||||||
|
"dist/acme-1.2.3-py3-none-any.whl.frob.attestation",
|
||||||
|
"dist/acme-1.2.3-py3-none-any.whl.publish.attestation",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3.tar.gz",
|
||||||
|
raw_filename: "acme-1.2.3.tar.gz",
|
||||||
|
filename: SourceDistFilename(
|
||||||
|
SourceDistFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
extension: TarGz,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [
|
||||||
|
"dist/acme-1.2.3.tar.gz.build.attestation",
|
||||||
|
"dist/acme-1.2.3.tar.gz.frob.attestation",
|
||||||
|
"dist/acme-1.2.3.tar.gz.publish.attestation",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid sdists/wheels with attestations in various orders, but
|
||||||
|
// attestations are disabled while grouping.
|
||||||
|
{
|
||||||
|
let mut dists = vec![
|
||||||
|
valid_sdist,
|
||||||
|
&valid_sdist_publish_attestation,
|
||||||
|
&valid_sdist_build_attestation,
|
||||||
|
&valid_sdist_frob_attestation,
|
||||||
|
valid_wheel,
|
||||||
|
&valid_wheel_build_attestation,
|
||||||
|
&valid_wheel_publish_attestation,
|
||||||
|
&valid_wheel_frob_attestation,
|
||||||
|
];
|
||||||
|
|
||||||
|
allow_duplicates! {
|
||||||
|
for _ in 0..5 {
|
||||||
|
shuffle(&mut dists);
|
||||||
|
|
||||||
|
let mut groups =
|
||||||
|
group_files(dists.iter().map(PathBuf::from).collect(), true);
|
||||||
|
groups.sort_by_key(|group| group.raw_filename.clone());
|
||||||
|
|
||||||
|
assert_debug_snapshot!(groups, @r#"
|
||||||
|
[
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3-py3-none-any.whl",
|
||||||
|
raw_filename: "acme-1.2.3-py3-none-any.whl",
|
||||||
|
filename: WheelFilename(
|
||||||
|
WheelFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
tags: Small {
|
||||||
|
small: WheelTagSmall {
|
||||||
|
python_tag: Python {
|
||||||
|
major: 3,
|
||||||
|
minor: None,
|
||||||
|
},
|
||||||
|
abi_tag: None,
|
||||||
|
platform_tag: Any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3.tar.gz",
|
||||||
|
raw_filename: "acme-1.2.3.tar.gz",
|
||||||
|
filename: SourceDistFilename(
|
||||||
|
SourceDistFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
extension: TarGz,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid dist/attestation filenames get ignored.
|
||||||
|
{
|
||||||
|
let dists = [
|
||||||
|
valid_sdist,
|
||||||
|
&valid_sdist_frob_attestation,
|
||||||
|
valid_wheel,
|
||||||
|
&valid_wheel_build_attestation,
|
||||||
|
invalid_sdist,
|
||||||
|
invalid_wheel,
|
||||||
|
&valid_sdist_invalid_attestation,
|
||||||
|
invalid_attestation,
|
||||||
|
];
|
||||||
|
|
||||||
|
let groups = group_files(dists.iter().map(PathBuf::from).collect(), false);
|
||||||
|
assert_debug_snapshot!(groups, @r#"
|
||||||
|
[
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3-py3-none-any.whl",
|
||||||
|
raw_filename: "acme-1.2.3-py3-none-any.whl",
|
||||||
|
filename: WheelFilename(
|
||||||
|
WheelFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
tags: Small {
|
||||||
|
small: WheelTagSmall {
|
||||||
|
python_tag: Python {
|
||||||
|
major: 3,
|
||||||
|
minor: None,
|
||||||
|
},
|
||||||
|
abi_tag: None,
|
||||||
|
platform_tag: Any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [
|
||||||
|
"dist/acme-1.2.3-py3-none-any.whl.build.attestation",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3.tar.gz",
|
||||||
|
raw_filename: "acme-1.2.3.tar.gz",
|
||||||
|
filename: SourceDistFilename(
|
||||||
|
SourceDistFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
extension: TarGz,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [
|
||||||
|
"dist/acme-1.2.3.tar.gz.frob.attestation",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
"#);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Snapshot the data we send for an upload request for a source distribution.
|
/// Snapshot the data we send for an upload request for a source distribution.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn upload_request_source_dist() {
|
async fn upload_request_source_dist() {
|
||||||
|
let group = {
|
||||||
let raw_filename = "tqdm-999.0.0.tar.gz";
|
let raw_filename = "tqdm-999.0.0.tar.gz";
|
||||||
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
|
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
|
||||||
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();
|
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();
|
||||||
|
|
||||||
let form_metadata = FormMetadata::read_from_file(&file, &filename)
|
UploadDistribution {
|
||||||
|
file,
|
||||||
|
raw_filename: raw_filename.to_string(),
|
||||||
|
filename,
|
||||||
|
attestations: vec![],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let form_metadata = FormMetadata::read_from_file(&group.file, &group.filename)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
@ -1121,9 +1513,7 @@ mod tests {
|
||||||
|
|
||||||
let client = BaseClientBuilder::default().build();
|
let client = BaseClientBuilder::default().build();
|
||||||
let (request, _) = build_upload_request(
|
let (request, _) = build_upload_request(
|
||||||
&file,
|
&group,
|
||||||
raw_filename,
|
|
||||||
&filename,
|
|
||||||
&DisplaySafeUrl::parse("https://example.org/upload").unwrap(),
|
&DisplaySafeUrl::parse("https://example.org/upload").unwrap(),
|
||||||
&client,
|
&client,
|
||||||
&Credentials::basic(Some("ferris".to_string()), Some("F3RR!S".to_string())),
|
&Credentials::basic(Some("ferris".to_string()), Some("F3RR!S".to_string())),
|
||||||
|
|
@ -1171,11 +1561,20 @@ mod tests {
|
||||||
/// Snapshot the data we send for an upload request for a wheel.
|
/// Snapshot the data we send for an upload request for a wheel.
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn upload_request_wheel() {
|
async fn upload_request_wheel() {
|
||||||
|
let group = {
|
||||||
let raw_filename = "tqdm-4.66.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl";
|
let raw_filename = "tqdm-4.66.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl";
|
||||||
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
|
let file = PathBuf::from("../../scripts/links/").join(raw_filename);
|
||||||
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();
|
let filename = DistFilename::try_from_normalized_filename(raw_filename).unwrap();
|
||||||
|
|
||||||
let form_metadata = FormMetadata::read_from_file(&file, &filename)
|
UploadDistribution {
|
||||||
|
file,
|
||||||
|
raw_filename: raw_filename.to_string(),
|
||||||
|
filename,
|
||||||
|
attestations: vec![],
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let form_metadata = FormMetadata::read_from_file(&group.file, &group.filename)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
@ -1274,9 +1673,7 @@ mod tests {
|
||||||
|
|
||||||
let client = BaseClientBuilder::default().build();
|
let client = BaseClientBuilder::default().build();
|
||||||
let (request, _) = build_upload_request(
|
let (request, _) = build_upload_request(
|
||||||
&file,
|
&group,
|
||||||
raw_filename,
|
|
||||||
&filename,
|
|
||||||
&DisplaySafeUrl::parse("https://example.org/upload").unwrap(),
|
&DisplaySafeUrl::parse("https://example.org/upload").unwrap(),
|
||||||
&client,
|
&client,
|
||||||
&Credentials::basic(Some("ferris".to_string()), Some("F3RR!S".to_string())),
|
&Credentials::basic(Some("ferris".to_string()), Some("F3RR!S".to_string())),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
---
|
||||||
|
source: crates/uv-publish/src/lib.rs
|
||||||
|
expression: groups
|
||||||
|
---
|
||||||
|
[
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3-py3-none-any.whl",
|
||||||
|
raw_filename: "acme-1.2.3-py3-none-any.whl",
|
||||||
|
filename: WheelFilename(
|
||||||
|
WheelFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
tags: Small {
|
||||||
|
small: WheelTagSmall {
|
||||||
|
python_tag: Python {
|
||||||
|
major: 3,
|
||||||
|
minor: None,
|
||||||
|
},
|
||||||
|
abi_tag: None,
|
||||||
|
platform_tag: Any,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
UploadDistribution {
|
||||||
|
file: "dist/acme-1.2.3.tar.gz",
|
||||||
|
raw_filename: "acme-1.2.3.tar.gz",
|
||||||
|
filename: SourceDistFilename(
|
||||||
|
SourceDistFilename {
|
||||||
|
name: PackageName(
|
||||||
|
"acme",
|
||||||
|
),
|
||||||
|
version: "1.2.3",
|
||||||
|
extension: TarGz,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
attestations: [],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
@ -297,6 +297,11 @@ impl EnvVars {
|
||||||
#[attr_added_in("0.4.30")]
|
#[attr_added_in("0.4.30")]
|
||||||
pub const UV_PUBLISH_CHECK_URL: &'static str = "UV_PUBLISH_CHECK_URL";
|
pub const UV_PUBLISH_CHECK_URL: &'static str = "UV_PUBLISH_CHECK_URL";
|
||||||
|
|
||||||
|
/// Equivalent to the `--no-attestations` command-line argument in `uv publish`. If set,
|
||||||
|
/// uv will skip uploading any collected attestations for the published distributions.
|
||||||
|
#[attr_added_in("next release")]
|
||||||
|
pub const UV_PUBLISH_NO_ATTESTATIONS: &'static str = "UV_PUBLISH_NO_ATTESTATIONS";
|
||||||
|
|
||||||
/// Equivalent to the `--no-sync` command-line argument. If set, uv will skip updating
|
/// Equivalent to the `--no-sync` command-line argument. If set, uv will skip updating
|
||||||
/// the environment.
|
/// the environment.
|
||||||
#[attr_added_in("0.4.18")]
|
#[attr_added_in("0.4.18")]
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use uv_configuration::{KeyringProviderType, TrustedPublishing};
|
||||||
use uv_distribution_types::{IndexCapabilities, IndexLocations, IndexUrl};
|
use uv_distribution_types::{IndexCapabilities, IndexLocations, IndexUrl};
|
||||||
use uv_publish::{
|
use uv_publish::{
|
||||||
CheckUrlClient, FormMetadata, PublishError, TrustedPublishResult, check_trusted_publishing,
|
CheckUrlClient, FormMetadata, PublishError, TrustedPublishResult, check_trusted_publishing,
|
||||||
files_for_publishing, upload,
|
group_files_for_publishing, upload,
|
||||||
};
|
};
|
||||||
use uv_redacted::DisplaySafeUrl;
|
use uv_redacted::DisplaySafeUrl;
|
||||||
use uv_settings::EnvironmentOptions;
|
use uv_settings::EnvironmentOptions;
|
||||||
|
|
@ -36,6 +36,7 @@ pub(crate) async fn publish(
|
||||||
index: Option<String>,
|
index: Option<String>,
|
||||||
index_locations: IndexLocations,
|
index_locations: IndexLocations,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
|
no_attestations: bool,
|
||||||
cache: &Cache,
|
cache: &Cache,
|
||||||
printer: Printer,
|
printer: Printer,
|
||||||
) -> Result<ExitStatus> {
|
) -> Result<ExitStatus> {
|
||||||
|
|
@ -87,8 +88,8 @@ pub(crate) async fn publish(
|
||||||
(publish_url, check_url)
|
(publish_url, check_url)
|
||||||
};
|
};
|
||||||
|
|
||||||
let files = files_for_publishing(paths)?;
|
let groups = group_files_for_publishing(paths, no_attestations)?;
|
||||||
match files.len() {
|
match groups.len() {
|
||||||
0 => bail!("No files found to publish"),
|
0 => bail!("No files found to publish"),
|
||||||
1 => {
|
1 => {
|
||||||
if dry_run {
|
if dry_run {
|
||||||
|
|
@ -166,44 +167,55 @@ pub(crate) async fn publish(
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
for (file, raw_filename, filename) in files {
|
for group in groups {
|
||||||
if let Some(check_url_client) = &check_url_client {
|
if let Some(check_url_client) = &check_url_client {
|
||||||
if uv_publish::check_url(check_url_client, &file, &filename, &download_concurrency)
|
if uv_publish::check_url(
|
||||||
|
check_url_client,
|
||||||
|
&group.file,
|
||||||
|
&group.filename,
|
||||||
|
&download_concurrency,
|
||||||
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
writeln!(printer.stderr(), "File {filename} already exists, skipping")?;
|
writeln!(
|
||||||
|
printer.stderr(),
|
||||||
|
"File {} already exists, skipping",
|
||||||
|
group.filename
|
||||||
|
)?;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let size = fs_err::metadata(&file)?.len();
|
let size = fs_err::metadata(&group.file)?.len();
|
||||||
let (bytes, unit) = human_readable_bytes(size);
|
let (bytes, unit) = human_readable_bytes(size);
|
||||||
if dry_run {
|
if dry_run {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{} {filename} {}",
|
"{} {} {}",
|
||||||
"Checking".bold().cyan(),
|
"Checking".bold().cyan(),
|
||||||
|
group.filename,
|
||||||
format!("({bytes:.1}{unit})").dimmed()
|
format!("({bytes:.1}{unit})").dimmed()
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
writeln!(
|
writeln!(
|
||||||
printer.stderr(),
|
printer.stderr(),
|
||||||
"{} {filename} {}",
|
"{} {} {}",
|
||||||
"Uploading".bold().green(),
|
"Uploading".bold().green(),
|
||||||
|
group.filename,
|
||||||
format!("({bytes:.1}{unit})").dimmed()
|
format!("({bytes:.1}{unit})").dimmed()
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the metadata for the file.
|
// Collect the metadata for the file.
|
||||||
let form_metadata = FormMetadata::read_from_file(&file, &filename)
|
let form_metadata = FormMetadata::read_from_file(&group.file, &group.filename)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| PublishError::PublishPrepare(file.clone(), Box::new(err)))?;
|
.map_err(|err| PublishError::PublishPrepare(group.file.clone(), Box::new(err)))?;
|
||||||
|
|
||||||
// Run validation checks on the file, but don't upload it (if possible).
|
// Run validation checks on the file, but don't upload it (if possible).
|
||||||
uv_publish::validate(
|
uv_publish::validate(
|
||||||
&file,
|
&group.file,
|
||||||
&form_metadata,
|
&form_metadata,
|
||||||
&raw_filename,
|
&group.raw_filename,
|
||||||
&publish_url,
|
&publish_url,
|
||||||
&token_store,
|
&token_store,
|
||||||
&upload_client,
|
&upload_client,
|
||||||
|
|
@ -217,10 +229,8 @@ pub(crate) async fn publish(
|
||||||
|
|
||||||
let reporter = PublishReporter::single(printer);
|
let reporter = PublishReporter::single(printer);
|
||||||
let uploaded = upload(
|
let uploaded = upload(
|
||||||
&file,
|
&group,
|
||||||
&form_metadata,
|
&form_metadata,
|
||||||
&raw_filename,
|
|
||||||
&filename,
|
|
||||||
&publish_url,
|
&publish_url,
|
||||||
&upload_client,
|
&upload_client,
|
||||||
retry_policy,
|
retry_policy,
|
||||||
|
|
|
||||||
|
|
@ -1713,6 +1713,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
dry_run,
|
dry_run,
|
||||||
|
no_attestations,
|
||||||
publish_url,
|
publish_url,
|
||||||
trusted_publishing,
|
trusted_publishing,
|
||||||
keyring_provider,
|
keyring_provider,
|
||||||
|
|
@ -1734,6 +1735,7 @@ async fn run(mut cli: Cli) -> Result<ExitStatus> {
|
||||||
index,
|
index,
|
||||||
index_locations,
|
index_locations,
|
||||||
dry_run,
|
dry_run,
|
||||||
|
no_attestations,
|
||||||
&cache,
|
&cache,
|
||||||
printer,
|
printer,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3774,6 +3774,7 @@ pub(crate) struct PublishSettings {
|
||||||
pub(crate) password: Option<String>,
|
pub(crate) password: Option<String>,
|
||||||
pub(crate) index: Option<String>,
|
pub(crate) index: Option<String>,
|
||||||
pub(crate) dry_run: bool,
|
pub(crate) dry_run: bool,
|
||||||
|
pub(crate) no_attestations: bool,
|
||||||
|
|
||||||
// Both CLI and configuration.
|
// Both CLI and configuration.
|
||||||
pub(crate) publish_url: DisplaySafeUrl,
|
pub(crate) publish_url: DisplaySafeUrl,
|
||||||
|
|
@ -3819,6 +3820,7 @@ impl PublishSettings {
|
||||||
username,
|
username,
|
||||||
password,
|
password,
|
||||||
dry_run: args.dry_run,
|
dry_run: args.dry_run,
|
||||||
|
no_attestations: args.no_attestations,
|
||||||
publish_url: args
|
publish_url: args
|
||||||
.publish_url
|
.publish_url
|
||||||
.combine(publish_url)
|
.combine(publish_url)
|
||||||
|
|
|
||||||
|
|
@ -186,7 +186,7 @@ fn dubious_filenames() {
|
||||||
.arg("dummy")
|
.arg("dummy")
|
||||||
.arg("--publish-url")
|
.arg("--publish-url")
|
||||||
.arg("https://test.pypi.org/legacy/")
|
.arg("https://test.pypi.org/legacy/")
|
||||||
.arg(context.temp_dir.join("*")), @r###"
|
.arg(context.temp_dir.join("*")), @r"
|
||||||
success: false
|
success: false
|
||||||
exit_code: 2
|
exit_code: 2
|
||||||
----- stdout -----
|
----- stdout -----
|
||||||
|
|
@ -196,7 +196,7 @@ fn dubious_filenames() {
|
||||||
warning: Skipping file that looks like a distribution, but is not a valid distribution filename: `[TEMP_DIR]/not-a-wheel.whl`
|
warning: Skipping file that looks like a distribution, but is not a valid distribution filename: `[TEMP_DIR]/not-a-wheel.whl`
|
||||||
warning: Skipping file that looks like a distribution, but is not a valid distribution filename: `[TEMP_DIR]/not-sdist-1-2-3-asdf.zip`
|
warning: Skipping file that looks like a distribution, but is not a valid distribution filename: `[TEMP_DIR]/not-sdist-1-2-3-asdf.zip`
|
||||||
error: No files found to publish
|
error: No files found to publish
|
||||||
"###
|
"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,34 @@ to files in the registry, and it will also handle raced parallel uploads. Note t
|
||||||
need to match exactly with those previously uploaded to the registry, this avoids accidentally
|
need to match exactly with those previously uploaded to the registry, this avoids accidentally
|
||||||
publishing source distribution and wheels with different contents for the same version.
|
publishing source distribution and wheels with different contents for the same version.
|
||||||
|
|
||||||
|
### Uploading attestations with your package
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
|
||||||
|
Some third-party package indexes may not support attestations, and may
|
||||||
|
reject uploads that include them (rather than silently ignoring them).
|
||||||
|
If you encounter issues when uploading, you can use `--no-attestations` or
|
||||||
|
`UV_PUBLISH_NO_ATTESTATIONS` to disable uv's default behavior.
|
||||||
|
|
||||||
|
!!! tip
|
||||||
|
|
||||||
|
`uv publish` does not currently generate attestations; attestations must
|
||||||
|
be created separately before publishing.
|
||||||
|
|
||||||
|
`uv publish` supports uploading [attestations](https://peps.python.org/pep-0740/) to registries that
|
||||||
|
support them, like PyPI.
|
||||||
|
|
||||||
|
uv will automatically discover and match attestations. For example, given the following `dist/`
|
||||||
|
directory, `uv publish` will upload the attestations along with their corresponding distributions:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ls dist/
|
||||||
|
hello_world-1.0.0-py3-none-any.whl
|
||||||
|
hello_world-1.0.0-py3-none-any.whl.publish.attestation
|
||||||
|
hello_world-1.0.0.tar.gz
|
||||||
|
hello_world-1.0.0.tar.gz.publish.attestation
|
||||||
|
```
|
||||||
|
|
||||||
## Installing your package
|
## Installing your package
|
||||||
|
|
||||||
Test that the package can be installed and imported with `uv run`:
|
Test that the package can be installed and imported with `uv run`:
|
||||||
|
|
|
||||||
|
|
@ -5833,7 +5833,7 @@ uv publish [OPTIONS] [FILES]...
|
||||||
<h3 class="cli-reference">Arguments</h3>
|
<h3 class="cli-reference">Arguments</h3>
|
||||||
|
|
||||||
<dl class="cli-reference"><dt id="uv-publish--files"><a href="#uv-publish--files"<code>FILES</code></a></dt><dd><p>Paths to the files to upload. Accepts glob expressions.</p>
|
<dl class="cli-reference"><dt id="uv-publish--files"><a href="#uv-publish--files"<code>FILES</code></a></dt><dd><p>Paths to the files to upload. Accepts glob expressions.</p>
|
||||||
<p>Defaults to the <code>dist</code> directory. Selects only wheels and source distributions, while ignoring other files.</p>
|
<p>Defaults to the <code>dist</code> directory. Selects only wheels and source distributions and their attestations, while ignoring other files.</p>
|
||||||
</dd></dl>
|
</dd></dl>
|
||||||
|
|
||||||
<h3 class="cli-reference">Options</h3>
|
<h3 class="cli-reference">Options</h3>
|
||||||
|
|
@ -5889,7 +5889,9 @@ uv publish --publish-url https://upload.pypi.org/legacy/ --check-url https://pyp
|
||||||
<p>May also be set with the <code>UV_MANAGED_PYTHON</code> environment variable.</p></dd><dt id="uv-publish--native-tls"><a href="#uv-publish--native-tls"><code>--native-tls</code></a></dt><dd><p>Whether to load TLS certificates from the platform's native certificate store.</p>
|
<p>May also be set with the <code>UV_MANAGED_PYTHON</code> environment variable.</p></dd><dt id="uv-publish--native-tls"><a href="#uv-publish--native-tls"><code>--native-tls</code></a></dt><dd><p>Whether to load TLS certificates from the platform's native certificate store.</p>
|
||||||
<p>By default, uv loads certificates from the bundled <code>webpki-roots</code> crate. The <code>webpki-roots</code> are a reliable set of trust roots from Mozilla, and including them in uv improves portability and performance (especially on macOS).</p>
|
<p>By default, uv loads certificates from the bundled <code>webpki-roots</code> crate. The <code>webpki-roots</code> are a reliable set of trust roots from Mozilla, and including them in uv improves portability and performance (especially on macOS).</p>
|
||||||
<p>However, in some cases, you may want to use the platform's native certificate store, especially if you're relying on a corporate trust root (e.g., for a mandatory proxy) that's included in your system's certificate store.</p>
|
<p>However, in some cases, you may want to use the platform's native certificate store, especially if you're relying on a corporate trust root (e.g., for a mandatory proxy) that's included in your system's certificate store.</p>
|
||||||
<p>May also be set with the <code>UV_NATIVE_TLS</code> environment variable.</p></dd><dt id="uv-publish--no-cache"><a href="#uv-publish--no-cache"><code>--no-cache</code></a>, <code>--no-cache-dir</code>, <code>-n</code></dt><dd><p>Avoid reading from or writing to the cache, instead using a temporary directory for the duration of the operation</p>
|
<p>May also be set with the <code>UV_NATIVE_TLS</code> environment variable.</p></dd><dt id="uv-publish--no-attestations"><a href="#uv-publish--no-attestations"><code>--no-attestations</code></a></dt><dd><p>Do not upload attestations for the published files.</p>
|
||||||
|
<p>By default, uv attempts to upload matching PEP 740 attestations with each distribution that is published.</p>
|
||||||
|
<p>May also be set with the <code>UV_PUBLISH_NO_ATTESTATIONS</code> environment variable.</p></dd><dt id="uv-publish--no-cache"><a href="#uv-publish--no-cache"><code>--no-cache</code></a>, <code>--no-cache-dir</code>, <code>-n</code></dt><dd><p>Avoid reading from or writing to the cache, instead using a temporary directory for the duration of the operation</p>
|
||||||
<p>May also be set with the <code>UV_NO_CACHE</code> environment variable.</p></dd><dt id="uv-publish--no-config"><a href="#uv-publish--no-config"><code>--no-config</code></a></dt><dd><p>Avoid discovering configuration files (<code>pyproject.toml</code>, <code>uv.toml</code>).</p>
|
<p>May also be set with the <code>UV_NO_CACHE</code> environment variable.</p></dd><dt id="uv-publish--no-config"><a href="#uv-publish--no-config"><code>--no-config</code></a></dt><dd><p>Avoid discovering configuration files (<code>pyproject.toml</code>, <code>uv.toml</code>).</p>
|
||||||
<p>Normally, configuration files are discovered in the current directory, parent directories, or user configuration directories.</p>
|
<p>Normally, configuration files are discovered in the current directory, parent directories, or user configuration directories.</p>
|
||||||
<p>May also be set with the <code>UV_NO_CONFIG</code> environment variable.</p></dd><dt id="uv-publish--no-managed-python"><a href="#uv-publish--no-managed-python"><code>--no-managed-python</code></a></dt><dd><p>Disable use of uv-managed Python versions.</p>
|
<p>May also be set with the <code>UV_NO_CONFIG</code> environment variable.</p></dd><dt id="uv-publish--no-managed-python"><a href="#uv-publish--no-managed-python"><code>--no-managed-python</code></a></dt><dd><p>Disable use of uv-managed Python versions.</p>
|
||||||
|
|
|
||||||
|
|
@ -466,6 +466,12 @@ Don't upload a file if it already exists on the index. The value is the URL of t
|
||||||
Equivalent to the `--index` command-line argument in `uv publish`. If
|
Equivalent to the `--index` command-line argument in `uv publish`. If
|
||||||
set, uv the index with this name in the configuration for publishing.
|
set, uv the index with this name in the configuration for publishing.
|
||||||
|
|
||||||
|
### `UV_PUBLISH_NO_ATTESTATIONS`
|
||||||
|
<small class="added-in">added in `next release`</small>
|
||||||
|
|
||||||
|
Equivalent to the `--no-attestations` command-line argument in `uv publish`. If set,
|
||||||
|
uv will skip uploading any collected attestations for the published distributions.
|
||||||
|
|
||||||
### `UV_PUBLISH_PASSWORD`
|
### `UV_PUBLISH_PASSWORD`
|
||||||
<small class="added-in">added in `0.4.16`</small>
|
<small class="added-in">added in `0.4.16`</small>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
# dependencies = [
|
# dependencies = [
|
||||||
# "httpx>=0.28.1,<0.29",
|
# "httpx>=0.28.1,<0.29",
|
||||||
# "packaging>=24.1,<25",
|
# "packaging>=24.1,<25",
|
||||||
|
# "pypi-attestations==0.0.28",
|
||||||
|
# "sigstore==4.1.0",
|
||||||
# ]
|
# ]
|
||||||
# ///
|
# ///
|
||||||
|
|
||||||
|
|
@ -78,6 +80,10 @@ from packaging.utils import (
|
||||||
parse_wheel_filename,
|
parse_wheel_filename,
|
||||||
)
|
)
|
||||||
from packaging.version import Version
|
from packaging.version import Version
|
||||||
|
from pypi_attestations import Attestation, Distribution
|
||||||
|
from sigstore import oidc
|
||||||
|
from sigstore.models import ClientTrustConfig
|
||||||
|
from sigstore.sign import SigningContext
|
||||||
|
|
||||||
TEST_PYPI_PUBLISH_URL = "https://test.pypi.org/legacy/"
|
TEST_PYPI_PUBLISH_URL = "https://test.pypi.org/legacy/"
|
||||||
PYTHON_VERSION = os.environ.get("UV_TEST_PUBLISH_PYTHON_VERSION", "3.12")
|
PYTHON_VERSION = os.environ.get("UV_TEST_PUBLISH_PYTHON_VERSION", "3.12")
|
||||||
|
|
@ -115,6 +121,7 @@ class TargetConfiguration:
|
||||||
publish_url: str
|
publish_url: str
|
||||||
index_url: str
|
index_url: str
|
||||||
index: str | None = None
|
index: str | None = None
|
||||||
|
attestations: bool = False
|
||||||
|
|
||||||
def index_declaration(self) -> str | None:
|
def index_declaration(self) -> str | None:
|
||||||
if not self.index:
|
if not self.index:
|
||||||
|
|
@ -179,6 +186,8 @@ all_targets: dict[str, TargetConfiguration] = local_targets | {
|
||||||
"astral-test-trusted-publishing",
|
"astral-test-trusted-publishing",
|
||||||
TEST_PYPI_PUBLISH_URL,
|
TEST_PYPI_PUBLISH_URL,
|
||||||
"https://test.pypi.org/simple/",
|
"https://test.pypi.org/simple/",
|
||||||
|
index=None,
|
||||||
|
attestations=True,
|
||||||
),
|
),
|
||||||
# TODO: Not enabled until we have a native Trusted Publishing flow for pyx in uv.
|
# TODO: Not enabled until we have a native Trusted Publishing flow for pyx in uv.
|
||||||
# "pyx-trusted-publishing": TargetConfiguration(
|
# "pyx-trusted-publishing": TargetConfiguration(
|
||||||
|
|
@ -259,6 +268,36 @@ def get_filenames(url: str, client: httpx.Client) -> list[str]:
|
||||||
return [m.group(1) for m in re.finditer(href_text, data)]
|
return [m.group(1) for m in re.finditer(href_text, data)]
|
||||||
|
|
||||||
|
|
||||||
|
def check_index_for_provenance(
|
||||||
|
index_url: str,
|
||||||
|
project_name: str,
|
||||||
|
version: Version,
|
||||||
|
client: httpx.Client,
|
||||||
|
):
|
||||||
|
"""Check that the index serves a provenance attribute on each of the
|
||||||
|
distributions for the given project and version.
|
||||||
|
|
||||||
|
This uses the PEP 691 JSON API for convenience. There shouldn't be
|
||||||
|
any PEP 740 implementations out there that don't also implement PEP 691.
|
||||||
|
"""
|
||||||
|
|
||||||
|
url = index_url + project_name + "/"
|
||||||
|
response = client.get(
|
||||||
|
url,
|
||||||
|
follow_redirects=True,
|
||||||
|
headers={"Accept": "application/vnd.pypi.simple.v1+json"},
|
||||||
|
)
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
|
data = response.json()
|
||||||
|
for file in data["files"]:
|
||||||
|
if str(version) in file["filename"] and not file.get("provenance"):
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Missing provenance for {project_name} {version} "
|
||||||
|
f"file {file['filename']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_project_at_version(
|
def build_project_at_version(
|
||||||
target: str, version: Version, uv: Path, modified: bool = False
|
target: str, version: Version, uv: Path, modified: bool = False
|
||||||
) -> Path:
|
) -> Path:
|
||||||
|
|
@ -383,9 +422,11 @@ def wait_for_index(
|
||||||
def publish_project(target: str, uv: Path, client: httpx.Client):
|
def publish_project(target: str, uv: Path, client: httpx.Client):
|
||||||
"""Test that:
|
"""Test that:
|
||||||
|
|
||||||
1. An upload with a fresh version succeeds.
|
1. An upload with a fresh version succeeds. If the upload includes attestations,
|
||||||
|
we confirm that the index accepts and serves them.
|
||||||
2. If we're using PyPI, uploading the same files again succeeds.
|
2. If we're using PyPI, uploading the same files again succeeds.
|
||||||
3. Check URL works and reports the files as skipped.
|
3. Check URL works and reports the files as skipped.
|
||||||
|
4. Uploading modified files at the same version fails.
|
||||||
"""
|
"""
|
||||||
# If we're publishing to pyx, we need to give the httpx client
|
# If we're publishing to pyx, we need to give the httpx client
|
||||||
# access to an appropriate credential.
|
# access to an appropriate credential.
|
||||||
|
|
@ -421,6 +462,33 @@ def publish_project(target: str, uv: Path, client: httpx.Client):
|
||||||
# Ignore our test file
|
# Ignore our test file
|
||||||
expected_filenames.remove(".DS_Store")
|
expected_filenames.remove(".DS_Store")
|
||||||
|
|
||||||
|
if all_targets[target].attestations:
|
||||||
|
trust = ClientTrustConfig.production()
|
||||||
|
identity = oidc.detect_credential()
|
||||||
|
|
||||||
|
if not identity:
|
||||||
|
raise RuntimeError("Failed to detect OIDC credential for signing")
|
||||||
|
|
||||||
|
identity_token = oidc.IdentityToken(identity)
|
||||||
|
context = SigningContext.from_trust_config(trust)
|
||||||
|
|
||||||
|
with context.signer(identity_token=identity_token) as signer:
|
||||||
|
for dist_name in expected_filenames:
|
||||||
|
if not (
|
||||||
|
dist_name.endswith(".tar.gz") or dist_name.endswith(".whl")
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
|
||||||
|
dist_path = project_dir / "dist" / dist_name
|
||||||
|
|
||||||
|
dist = Distribution.from_file(dist_path)
|
||||||
|
attestation = Attestation.sign(signer, dist)
|
||||||
|
|
||||||
|
attestation_path = dist_path.with_suffix(
|
||||||
|
dist_path.suffix + ".publish.attestation"
|
||||||
|
)
|
||||||
|
attestation_path.write_text(attestation.model_dump_json())
|
||||||
|
|
||||||
print(
|
print(
|
||||||
f"\n=== 1. Publishing a new version: {project_name} {version} {publish_url} ===",
|
f"\n=== 1. Publishing a new version: {project_name} {version} {publish_url} ===",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
|
|
@ -443,6 +511,10 @@ def publish_project(target: str, uv: Path, client: httpx.Client):
|
||||||
# Raise the error after three failures
|
# Raise the error after three failures
|
||||||
result.check_returncode()
|
result.check_returncode()
|
||||||
|
|
||||||
|
if all_targets[target].attestations:
|
||||||
|
wait_for_index(index_url, project_name, version, uv, env)
|
||||||
|
check_index_for_provenance(index_url, project_name, version, client)
|
||||||
|
|
||||||
if publish_url == TEST_PYPI_PUBLISH_URL:
|
if publish_url == TEST_PYPI_PUBLISH_URL:
|
||||||
# Confirm pypi behaviour: Uploading the same file again is fine.
|
# Confirm pypi behaviour: Uploading the same file again is fine.
|
||||||
print(
|
print(
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,17 @@ requires-python = ">=3.12"
|
||||||
requirements = [
|
requirements = [
|
||||||
{ name = "httpx", specifier = ">=0.28.1,<0.29" },
|
{ name = "httpx", specifier = ">=0.28.1,<0.29" },
|
||||||
{ name = "packaging", specifier = ">=24.1,<25" },
|
{ name = "packaging", specifier = ">=24.1,<25" },
|
||||||
|
{ name = "pypi-attestations", specifier = "==0.0.28" },
|
||||||
|
{ name = "sigstore", specifier = "==4.1.0" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "annotated-types"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -31,6 +42,198 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" },
|
{ url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cffi"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pycparser", marker = "implementation_name != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "charset-normalizer"
|
||||||
|
version = "3.4.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cryptography"
|
||||||
|
version = "46.0.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9f/33/c00162f49c0e2fe8064a62cb92b93e50c74a72bc370ab92f86112b33ff62/cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1", size = 749258, upload-time = "2025-10-15T23:18:31.74Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1d/42/9c391dd801d6cf0d561b5890549d4b27bafcc53b39c31a817e69d87c625b/cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a", size = 7225004, upload-time = "2025-10-15T23:16:52.239Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1c/67/38769ca6b65f07461eb200e85fc1639b438bdc667be02cf7f2cd6a64601c/cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc", size = 4296667, upload-time = "2025-10-15T23:16:54.369Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5c/49/498c86566a1d80e978b42f0d702795f69887005548c041636df6ae1ca64c/cryptography-46.0.3-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:01ca9ff2885f3acc98c29f1860552e37f6d7c7d013d7334ff2a9de43a449315d", size = 4450807, upload-time = "2025-10-15T23:16:56.414Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4b/0a/863a3604112174c8624a2ac3c038662d9e59970c7f926acdcfaed8d61142/cryptography-46.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6eae65d4c3d33da080cff9c4ab1f711b15c1d9760809dad6ea763f3812d254cb", size = 4299615, upload-time = "2025-10-15T23:16:58.442Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/64/02/b73a533f6b64a69f3cd3872acb6ebc12aef924d8d103133bb3ea750dc703/cryptography-46.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5bf0ed4490068a2e72ac03d786693adeb909981cc596425d09032d372bcc849", size = 4016800, upload-time = "2025-10-15T23:17:00.378Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/d5/16e41afbfa450cde85a3b7ec599bebefaef16b5c6ba4ec49a3532336ed72/cryptography-46.0.3-cp311-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:5ecfccd2329e37e9b7112a888e76d9feca2347f12f37918facbb893d7bb88ee8", size = 4984707, upload-time = "2025-10-15T23:17:01.98Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/56/e7e69b427c3878352c2fb9b450bd0e19ed552753491d39d7d0a2f5226d41/cryptography-46.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a2c0cd47381a3229c403062f764160d57d4d175e022c1df84e168c6251a22eec", size = 4482541, upload-time = "2025-10-15T23:17:04.078Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/f6/50736d40d97e8483172f1bb6e698895b92a223dba513b0ca6f06b2365339/cryptography-46.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:549e234ff32571b1f4076ac269fcce7a808d3bf98b76c8dd560e42dbc66d7d91", size = 4299464, upload-time = "2025-10-15T23:17:05.483Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/00/de/d8e26b1a855f19d9994a19c702fa2e93b0456beccbcfe437eda00e0701f2/cryptography-46.0.3-cp311-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:c0a7bb1a68a5d3471880e264621346c48665b3bf1c3759d682fc0864c540bd9e", size = 4950838, upload-time = "2025-10-15T23:17:07.425Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8f/29/798fc4ec461a1c9e9f735f2fc58741b0daae30688f41b2497dcbc9ed1355/cryptography-46.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:10b01676fc208c3e6feeb25a8b83d81767e8059e1fe86e1dc62d10a3018fa926", size = 4481596, upload-time = "2025-10-15T23:17:09.343Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/15/8d/03cd48b20a573adfff7652b76271078e3045b9f49387920e7f1f631d125e/cryptography-46.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0abf1ffd6e57c67e92af68330d05760b7b7efb243aab8377e583284dbab72c71", size = 4426782, upload-time = "2025-10-15T23:17:11.22Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fa/b1/ebacbfe53317d55cf33165bda24c86523497a6881f339f9aae5c2e13e57b/cryptography-46.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a04bee9ab6a4da801eb9b51f1b708a1b5b5c9eb48c03f74198464c66f0d344ac", size = 4698381, upload-time = "2025-10-15T23:17:12.829Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/96/92/8a6a9525893325fc057a01f654d7efc2c64b9de90413adcf605a85744ff4/cryptography-46.0.3-cp311-abi3-win32.whl", hash = "sha256:f260d0d41e9b4da1ed1e0f1ce571f97fe370b152ab18778e9e8f67d6af432018", size = 3055988, upload-time = "2025-10-15T23:17:14.65Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/7e/bf/80fbf45253ea585a1e492a6a17efcb93467701fa79e71550a430c5e60df0/cryptography-46.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:a9a3008438615669153eb86b26b61e09993921ebdd75385ddd748702c5adfddb", size = 3514451, upload-time = "2025-10-15T23:17:16.142Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/af/9b302da4c87b0beb9db4e756386a7c6c5b8003cd0e742277888d352ae91d/cryptography-46.0.3-cp311-abi3-win_arm64.whl", hash = "sha256:5d7f93296ee28f68447397bf5198428c9aeeab45705a55d53a6343455dcb2c3c", size = 2928007, upload-time = "2025-10-15T23:17:18.04Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f5/e2/a510aa736755bffa9d2f75029c229111a1d02f8ecd5de03078f4c18d91a3/cryptography-46.0.3-cp314-cp314t-macosx_10_9_universal2.whl", hash = "sha256:00a5e7e87938e5ff9ff5447ab086a5706a957137e6e433841e9d24f38a065217", size = 7158012, upload-time = "2025-10-15T23:17:19.982Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/dc/9aa866fbdbb95b02e7f9d086f1fccfeebf8953509b87e3f28fff927ff8a0/cryptography-46.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c8daeb2d2174beb4575b77482320303f3d39b8e81153da4f0fb08eb5fe86a6c5", size = 4288728, upload-time = "2025-10-15T23:17:21.527Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c5/fd/bc1daf8230eaa075184cbbf5f8cd00ba9db4fd32d63fb83da4671b72ed8a/cryptography-46.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:39b6755623145ad5eff1dab323f4eae2a32a77a7abef2c5089a04a3d04366715", size = 4435078, upload-time = "2025-10-15T23:17:23.042Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/98/d3bd5407ce4c60017f8ff9e63ffee4200ab3e23fe05b765cab805a7db008/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:db391fa7c66df6762ee3f00c95a89e6d428f4d60e7abc8328f4fe155b5ac6e54", size = 4293460, upload-time = "2025-10-15T23:17:24.885Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/26/e9/e23e7900983c2b8af7a08098db406cf989d7f09caea7897e347598d4cd5b/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:78a97cf6a8839a48c49271cdcbd5cf37ca2c1d6b7fdd86cc864f302b5e9bf459", size = 3995237, upload-time = "2025-10-15T23:17:26.449Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/91/15/af68c509d4a138cfe299d0d7ddb14afba15233223ebd933b4bbdbc7155d3/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_ppc64le.whl", hash = "sha256:dfb781ff7eaa91a6f7fd41776ec37c5853c795d3b358d4896fdbb5df168af422", size = 4967344, upload-time = "2025-10-15T23:17:28.06Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ca/e3/8643d077c53868b681af077edf6b3cb58288b5423610f21c62aadcbe99f4/cryptography-46.0.3-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:6f61efb26e76c45c4a227835ddeae96d83624fb0d29eb5df5b96e14ed1a0afb7", size = 4466564, upload-time = "2025-10-15T23:17:29.665Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0e/43/c1e8726fa59c236ff477ff2b5dc071e54b21e5a1e51aa2cee1676f1c986f/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:23b1a8f26e43f47ceb6d6a43115f33a5a37d57df4ea0ca295b780ae8546e8044", size = 4292415, upload-time = "2025-10-15T23:17:31.686Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/42/f9/2f8fefdb1aee8a8e3256a0568cffc4e6d517b256a2fe97a029b3f1b9fe7e/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_ppc64le.whl", hash = "sha256:b419ae593c86b87014b9be7396b385491ad7f320bde96826d0dd174459e54665", size = 4931457, upload-time = "2025-10-15T23:17:33.478Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/79/30/9b54127a9a778ccd6d27c3da7563e9f2d341826075ceab89ae3b41bf5be2/cryptography-46.0.3-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:50fc3343ac490c6b08c0cf0d704e881d0d660be923fd3076db3e932007e726e3", size = 4466074, upload-time = "2025-10-15T23:17:35.158Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ac/68/b4f4a10928e26c941b1b6a179143af9f4d27d88fe84a6a3c53592d2e76bf/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22d7e97932f511d6b0b04f2bfd818d73dcd5928db509460aaf48384778eb6d20", size = 4420569, upload-time = "2025-10-15T23:17:37.188Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a3/49/3746dab4c0d1979888f125226357d3262a6dd40e114ac29e3d2abdf1ec55/cryptography-46.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d55f3dffadd674514ad19451161118fd010988540cee43d8bc20675e775925de", size = 4681941, upload-time = "2025-10-15T23:17:39.236Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/30/27654c1dbaf7e4a3531fa1fc77986d04aefa4d6d78259a62c9dc13d7ad36/cryptography-46.0.3-cp314-cp314t-win32.whl", hash = "sha256:8a6e050cb6164d3f830453754094c086ff2d0b2f3a897a1d9820f6139a1f0914", size = 3022339, upload-time = "2025-10-15T23:17:40.888Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f6/30/640f34ccd4d2a1bc88367b54b926b781b5a018d65f404d409aba76a84b1c/cryptography-46.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:760f83faa07f8b64e9c33fc963d790a2edb24efb479e3520c14a45741cd9b2db", size = 3494315, upload-time = "2025-10-15T23:17:42.769Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ba/8b/88cc7e3bd0a8e7b861f26981f7b820e1f46aa9d26cc482d0feba0ecb4919/cryptography-46.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:516ea134e703e9fe26bcd1277a4b59ad30586ea90c365a87781d7887a646fe21", size = 2919331, upload-time = "2025-10-15T23:17:44.468Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/23/45fe7f376a7df8daf6da3556603b36f53475a99ce4faacb6ba2cf3d82021/cryptography-46.0.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:cb3d760a6117f621261d662bccc8ef5bc32ca673e037c83fbe565324f5c46936", size = 7218248, upload-time = "2025-10-15T23:17:46.294Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/32/b68d27471372737054cbd34c84981f9edbc24fe67ca225d389799614e27f/cryptography-46.0.3-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:4b7387121ac7d15e550f5cb4a43aef2559ed759c35df7336c402bb8275ac9683", size = 4294089, upload-time = "2025-10-15T23:17:48.269Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/26/42/fa8389d4478368743e24e61eea78846a0006caffaf72ea24a15159215a14/cryptography-46.0.3-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15ab9b093e8f09daab0f2159bb7e47532596075139dd74365da52ecc9cb46c5d", size = 4440029, upload-time = "2025-10-15T23:17:49.837Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5f/eb/f483db0ec5ac040824f269e93dd2bd8a21ecd1027e77ad7bdf6914f2fd80/cryptography-46.0.3-cp38-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:46acf53b40ea38f9c6c229599a4a13f0d46a6c3fa9ef19fc1a124d62e338dfa0", size = 4297222, upload-time = "2025-10-15T23:17:51.357Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/cf/da9502c4e1912cb1da3807ea3618a6829bee8207456fbbeebc361ec38ba3/cryptography-46.0.3-cp38-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10ca84c4668d066a9878890047f03546f3ae0a6b8b39b697457b7757aaf18dbc", size = 4012280, upload-time = "2025-10-15T23:17:52.964Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/8f/9adb86b93330e0df8b3dcf03eae67c33ba89958fc2e03862ef1ac2b42465/cryptography-46.0.3-cp38-abi3-manylinux_2_28_ppc64le.whl", hash = "sha256:36e627112085bb3b81b19fed209c05ce2a52ee8b15d161b7c643a7d5a88491f3", size = 4978958, upload-time = "2025-10-15T23:17:54.965Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/a0/5fa77988289c34bdb9f913f5606ecc9ada1adb5ae870bd0d1054a7021cc4/cryptography-46.0.3-cp38-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:1000713389b75c449a6e979ffc7dcc8ac90b437048766cef052d4d30b8220971", size = 4473714, upload-time = "2025-10-15T23:17:56.754Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/14/e5/fc82d72a58d41c393697aa18c9abe5ae1214ff6f2a5c18ac470f92777895/cryptography-46.0.3-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:b02cf04496f6576afffef5ddd04a0cb7d49cf6be16a9059d793a30b035f6b6ac", size = 4296970, upload-time = "2025-10-15T23:17:58.588Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/06/5663ed35438d0b09056973994f1aec467492b33bd31da36e468b01ec1097/cryptography-46.0.3-cp38-abi3-manylinux_2_34_ppc64le.whl", hash = "sha256:71e842ec9bc7abf543b47cf86b9a743baa95f4677d22baa4c7d5c69e49e9bc04", size = 4940236, upload-time = "2025-10-15T23:18:00.897Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fc/59/873633f3f2dcd8a053b8dd1d38f783043b5fce589c0f6988bf55ef57e43e/cryptography-46.0.3-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:402b58fc32614f00980b66d6e56a5b4118e6cb362ae8f3fda141ba4689bd4506", size = 4472642, upload-time = "2025-10-15T23:18:02.749Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3d/39/8e71f3930e40f6877737d6f69248cf74d4e34b886a3967d32f919cc50d3b/cryptography-46.0.3-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ef639cb3372f69ec44915fafcd6698b6cc78fbe0c2ea41be867f6ed612811963", size = 4423126, upload-time = "2025-10-15T23:18:04.85Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/c7/f65027c2810e14c3e7268353b1681932b87e5a48e65505d8cc17c99e36ae/cryptography-46.0.3-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b51b8ca4f1c6453d8829e1eb7299499ca7f313900dd4d89a24b8b87c0a780d4", size = 4686573, upload-time = "2025-10-15T23:18:06.908Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0a/6e/1c8331ddf91ca4730ab3086a0f1be19c65510a33b5a441cb334e7a2d2560/cryptography-46.0.3-cp38-abi3-win32.whl", hash = "sha256:6276eb85ef938dc035d59b87c8a7dc559a232f954962520137529d77b18ff1df", size = 3036695, upload-time = "2025-10-15T23:18:08.672Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/90/45/b0d691df20633eff80955a0fc7695ff9051ffce8b69741444bd9ed7bd0db/cryptography-46.0.3-cp38-abi3-win_amd64.whl", hash = "sha256:416260257577718c05135c55958b674000baef9a1c7d9e8f306ec60d71db850f", size = 3501720, upload-time = "2025-10-15T23:18:10.632Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e8/cb/2da4cc83f5edb9c3257d09e1e7ab7b23f049c7962cae8d842bbef0a9cec9/cryptography-46.0.3-cp38-abi3-win_arm64.whl", hash = "sha256:d89c3468de4cdc4f08a57e214384d0471911a3830fcdaf7a8cc587e42a866372", size = 2918740, upload-time = "2025-10-15T23:18:12.277Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dnspython"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "email-validator"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "dnspython" },
|
||||||
|
{ name = "idna" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h11"
|
name = "h11"
|
||||||
version = "0.16.0"
|
version = "0.16.0"
|
||||||
|
|
@ -68,6 +271,18 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "id"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "requests" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/22/11/102da08f88412d875fa2f1a9a469ff7ad4c874b0ca6fed0048fe385bdb3d/id-1.5.0.tar.gz", hash = "sha256:292cb8a49eacbbdbce97244f47a97b4c62540169c976552e497fd57df0734c1d", size = 15237, upload-time = "2024-12-04T19:53:05.575Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/cb/18326d2d89ad3b0dd143da971e77afd1e6ca6674f1b1c3df4b6bec6279fc/id-1.5.0-py3-none-any.whl", hash = "sha256:f1434e1cef91f2cbb8a4ec64663d5a23b9ed43ef44c4c957d02583d61714c658", size = 13611, upload-time = "2024-12-04T19:53:03.02Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.11"
|
version = "3.11"
|
||||||
|
|
@ -77,6 +292,27 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
{ url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "mdurl" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "24.2"
|
version = "24.2"
|
||||||
|
|
@ -86,6 +322,302 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" },
|
{ url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "4.5.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/61/33/9611380c2bdb1225fdef633e2a9610622310fed35ab11dac9620972ee088/platformdirs-4.5.0.tar.gz", hash = "sha256:70ddccdd7c99fc5942e9fc25636a8b34d04c24b335100223152c2803e4063312", size = 21632, upload-time = "2025-10-08T17:44:48.791Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/cb/ac7874b3e5d58441674fb70742e6c374b28b0c7cb988d37d991cde47166c/platformdirs-4.5.0-py3-none-any.whl", hash = "sha256:e578a81bb873cbb89a41fcc904c7ef523cc18284b7e3b3ccf06aca1403b7ebd3", size = 18651, upload-time = "2025-10-08T17:44:47.223Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyasn1"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ba/e9/01f1a64245b89f039897cb0130016d79f77d52669aae6ee7b159a6c4c018/pyasn1-0.6.1.tar.gz", hash = "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034", size = 145322, upload-time = "2024-09-10T22:41:42.55Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl", hash = "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", size = 83135, upload-time = "2024-09-11T16:00:36.122Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pycparser"
|
||||||
|
version = "2.23"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fe/cf/d2d3b9f5699fb1e4615c8e32ff220203e43b248e1dfcc6736ad9057731ca/pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2", size = 173734, upload-time = "2025-09-09T13:23:47.91Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a0/e3/59cd50310fc9b59512193629e1984c1f95e5c8ae6e5d8c69532ccc65a7fe/pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934", size = 118140, upload-time = "2025-09-09T13:23:46.651Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic"
|
||||||
|
version = "2.12.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "annotated-types" },
|
||||||
|
{ name = "pydantic-core" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
{ name = "typing-inspection" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/96/ad/a17bc283d7d81837c061c49e3eaa27a45991759a1b7eae1031921c6bd924/pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac", size = 821038, upload-time = "2025-11-05T10:50:08.59Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/82/2f/e68750da9b04856e2a7ec56fc6f034a5a79775e9b9a81882252789873798/pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e", size = 463400, upload-time = "2025-11-05T10:50:06.732Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.optional-dependencies]
|
||||||
|
email = [
|
||||||
|
{ name = "email-validator" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pydantic-core"
|
||||||
|
version = "2.41.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.19.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyjwt"
|
||||||
|
version = "2.10.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/e7/46/bd74733ff231675599650d3e47f361794b22ef3e3770998dda30d3b63726/pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953", size = 87785, upload-time = "2024-11-28T03:43:29.933Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/ad/689f02752eeec26aed679477e80e632ef1b682313be70793d798c1d5fc8f/PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb", size = 22997, upload-time = "2024-11-28T03:43:27.893Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyopenssl"
|
||||||
|
version = "25.3.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/80/be/97b83a464498a79103036bc74d1038df4a7ef0e402cfaf4d5e113fb14759/pyopenssl-25.3.0.tar.gz", hash = "sha256:c981cb0a3fd84e8602d7afc209522773b94c1c2446a3c710a75b06fe1beae329", size = 184073, upload-time = "2025-09-17T00:32:21.037Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d1/81/ef2b1dfd1862567d573a4fdbc9f969067621764fbb74338496840a1d2977/pyopenssl-25.3.0-py3-none-any.whl", hash = "sha256:1fda6fc034d5e3d179d39e59c1895c9faeaf40a79de5fc4cbbfbe0d36f4a77b6", size = 57268, upload-time = "2025-09-17T00:32:19.474Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pypi-attestations"
|
||||||
|
version = "0.0.28"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
{ name = "packaging" },
|
||||||
|
{ name = "pyasn1" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "requests" },
|
||||||
|
{ name = "rfc3986" },
|
||||||
|
{ name = "sigstore" },
|
||||||
|
{ name = "sigstore-models" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/1e/c0/95f6d792189b89a77eedc2da300578e3415a5950cdedeafe7ae3d02fd6a6/pypi_attestations-0.0.28.tar.gz", hash = "sha256:e5e75beaddbb674c390ed1a43cb32b7274990da6be7190c812a530b18db6137f", size = 124805, upload-time = "2025-10-16T16:58:07.637Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f7/0a/9b400d188f2b4983accabca5a9c9ce534d68dbe1b79c45ce87cf36f787c6/pypi_attestations-0.0.28-py3-none-any.whl", hash = "sha256:a7eebfb55f3b9848bb99e15a6c7ff462e0e7d9a1395690426e4d069fa0dd0158", size = 21910, upload-time = "2025-10-16T16:58:06.106Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "requests"
|
||||||
|
version = "2.32.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "certifi" },
|
||||||
|
{ name = "charset-normalizer" },
|
||||||
|
{ name = "idna" },
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc3161-client"
|
||||||
|
version = "1.0.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/85/19/c04a07f9926943b6a6945ae6972dc2c3c79b7f02e2be6346e3010a48d5f5/rfc3161_client-1.0.5.tar.gz", hash = "sha256:f1a2e32e2a053455cee1ff9b325b88dbc7c66c8882dde60962add92f572df5c5", size = 60966, upload-time = "2025-09-23T10:47:15.906Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/f3/11/96bc76086113b8d24291f7f72826739d4fc8d8e83683e27125b8966d0cea/rfc3161_client-1.0.5-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:8a54fdb2f9e64481272b89137a7b71403cf1d30f5505c2e0c15a47a1cc100264", size = 473872, upload-time = "2025-09-23T10:46:56.987Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/80/45/19224e046d76f214d056c40a2086d9147afb0bcadc0c823c2c8bd54d62aa/rfc3161_client-1.0.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:d9ed8e597d0ee7387da1945e1583c4516b26f133770b3956e079606e2d90b69c", size = 458218, upload-time = "2025-09-23T10:46:58.485Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/27/d7/0511f1423f1658b708cfa27043a21b06699ba7c2aef37ba465379b81c24d/rfc3161_client-1.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:61c04b4953453e5c26a1949c20adac415b65cd062dab0960574d6c36240222d2", size = 2396335, upload-time = "2025-09-23T10:47:00.111Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bc/d3/f93d1af5d9a1fed348ef543d39418aff02b0badf019b772f128c3483321c/rfc3161_client-1.0.5-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31b6ee79f15b93d90952efd0395bb3f5ebf07941469c5c6eb32f9b64312cda6e", size = 1805162, upload-time = "2025-09-23T10:47:01.912Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/69/51/0b30e3542fdf7adeb9f6afac1f095c543328a1a28c9d220f4e2207c6b845/rfc3161_client-1.0.5-cp39-abi3-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c53a6711bab0c3f77dc9cf1e2fd750da475ff7abbc40ffe0333d8c518a8a9c8", size = 2115530, upload-time = "2025-09-23T10:47:03.816Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/2e/b9/4da9f80da4ac30b9645c9a3455e71c4f6652ed886f20e11bfb9a01bcacd0/rfc3161_client-1.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c47582ecea2ca4a3debf8a1eda775cc3d5ae1379da40272cc065d32e639a7a", size = 2124925, upload-time = "2025-09-23T10:47:05.386Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/46/ed/f173556ddbd667e9f4642f8f7eb0f920e3e3be4b7459ec98c73a5029200d/rfc3161_client-1.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d31d30e354d2349ae8483ce811ef61498a3780daf8622c0b79d8cd44d271b46b", size = 2695972, upload-time = "2025-09-23T10:47:07.272Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/84/97/2ca7bdbb2d84b75fad7f572264a45c0b54446a7a65735172275c09293bd6/rfc3161_client-1.0.5-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ae440461a310ae097417afe536d9d22fd71c95fbc9d21db3561b2707bed0aff0", size = 2096478, upload-time = "2025-09-23T10:47:08.736Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/da/94/9e16134e04a45347eaad5680f8f52b0388664b45be09a0877daa196e1157/rfc3161_client-1.0.5-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:8fb34470e867a29cc15dc4987ea14f19d3bd25c863e132b6f75dca583e2cc67e", size = 2243602, upload-time = "2025-09-23T10:47:10.196Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/c2/13/85b6a5b5247f79dfa75d80a2e8f8d415472ff7fd72b31d152e00f71198b9/rfc3161_client-1.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3106f3361a5a36789f43d2700e5678c847a9d3460a23f455f4c20cd39314c557", size = 2296304, upload-time = "2025-09-23T10:47:11.594Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/e7/0a/f7991ff6158a00ed79d6e151ede63ae50bef650cf49436cea7226a0457dc/rfc3161_client-1.0.5-cp39-abi3-win32.whl", hash = "sha256:078e4bbf0770ddc472e2ca96cf1e23efd0c313e6682b4c2c9765e1fdf09f55a3", size = 1917793, upload-time = "2025-09-23T10:47:12.92Z" },
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/47/28/140516906a2117e15c37505d54968e9cc9a8275d042b195728f5ffc2ad02/rfc3161_client-1.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:e904430e27e75a5a379fc4aac09bd60ba5f4b48054f0481b2fb417297e404047", size = 2313057, upload-time = "2025-09-23T10:47:14.243Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc3986"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/85/40/1520d68bfa07ab5a6f065a186815fb6610c86fe957bc065754e47f7b0840/rfc3986-2.0.0.tar.gz", hash = "sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c", size = 49026, upload-time = "2022-01-10T00:52:30.832Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/ff/9a/9afaade874b2fa6c752c36f1548f718b5b83af81ed9b76628329dab81c1b/rfc3986-2.0.0-py2.py3-none-any.whl", hash = "sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd", size = 31326, upload-time = "2022-01-10T00:52:29.594Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rfc8785"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ef/2f/fa1d2e740c490191b572d33dbca5daa180cb423c24396b856f5886371d8b/rfc8785-0.1.4.tar.gz", hash = "sha256:e545841329fe0eee4f6a3b44e7034343100c12b4ec566dc06ca9735681deb4da", size = 14321, upload-time = "2024-09-27T16:33:31.206Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/4d/78/119878110660b2ad709888c8a1614fce7e2fab39080ab960656dc8605bf6/rfc8785-0.1.4-py3-none-any.whl", hash = "sha256:520d690b448ecf0703691c76e1a34a24ddcd4fc5bc41d589cb7c58ec651bcd48", size = 9240, upload-time = "2024-09-27T16:33:29.683Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "14.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markdown-it-py" },
|
||||||
|
{ name = "pygments" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fb/d2/8920e102050a0de7bfabeb4c4614a49248cf8d5d7a8d01885fbb24dc767a/rich-14.2.0.tar.gz", hash = "sha256:73ff50c7c0c1c77c8243079283f4edb376f0f6442433aecb8ce7e6d0b92d1fe4", size = 219990, upload-time = "2025-10-09T14:16:53.064Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/25/7a/b0178788f8dc6cafce37a212c99565fa1fe7872c70c6c9c1e1a372d9d88f/rich-14.2.0-py3-none-any.whl", hash = "sha256:76bc51fe2e57d2b1be1f96c524b890b816e334ab4c1e45888799bfaab0021edd", size = 243393, upload-time = "2025-10-09T14:16:51.245Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "securesystemslib"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c2/dd/d1828dce0db18aa8d34f82aee4dbcf49b0f0303cad123a1c716bb1f3bf83/securesystemslib-1.3.1.tar.gz", hash = "sha256:ca915f4b88209bb5450ac05426b859d74b7cd1421cafcf73b8dd3418a0b17486", size = 934782, upload-time = "2025-09-26T13:36:56.79Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/bd/29/1c560f46b3a95d8c508e1bd8c6d0bbf53c42d412ee7d19ec2a89ceced5b9/securesystemslib-1.3.1-py3-none-any.whl", hash = "sha256:2e5414bbdde33155a91805b295cbedc4ae3f12b48dccc63e1089093537f43c81", size = 871380, upload-time = "2025-09-26T13:36:54.851Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sigstore"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "cryptography" },
|
||||||
|
{ name = "id" },
|
||||||
|
{ name = "platformdirs" },
|
||||||
|
{ name = "pyasn1" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "pyjwt" },
|
||||||
|
{ name = "pyopenssl" },
|
||||||
|
{ name = "requests" },
|
||||||
|
{ name = "rfc3161-client" },
|
||||||
|
{ name = "rfc8785" },
|
||||||
|
{ name = "rich" },
|
||||||
|
{ name = "sigstore-models" },
|
||||||
|
{ name = "sigstore-rekor-types" },
|
||||||
|
{ name = "tuf" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/64/1e/8c115a155b67254b52780730bc86edf90d108d172377e526ce91e42ba9de/sigstore-4.1.0.tar.gz", hash = "sha256:312f7f73fe27127784245f523b86b6334978c555fe4ba7831be5602c089807c1", size = 87928, upload-time = "2025-10-11T12:48:14.541Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d9/02/126842beb9ce3d66f86203cdf94d99805df040cf693501a36bd6d0319cdf/sigstore-4.1.0-py3-none-any.whl", hash = "sha256:ec3ed0d92bf53ffb23261245a78d4ad3da5af5cc9af889c86461a7d02407249a", size = 109014, upload-time = "2025-10-11T12:48:12.827Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sigstore-models"
|
||||||
|
version = "0.0.5"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/ac/13/f67a87e8d8c97b9a47d4971263ca6afbd5250315a55b8056358061fc07da/sigstore_models-0.0.5.tar.gz", hash = "sha256:8eda90fe16ef3e4e624edd029f4cbbc9832a192dc5c8f66011d94ec4253f9f3f", size = 7037, upload-time = "2025-07-23T17:22:30.173Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/61/f6/619d9b21df2688d54e61bdb181fa2be32697def742ec7dbbd34c462778ed/sigstore_models-0.0.5-py3-none-any.whl", hash = "sha256:ac3ca1554d5dd509a6710699d83a035a09ba112d1fa180959cbfcdd5d97633b7", size = 13253, upload-time = "2025-07-23T17:22:29.259Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sigstore-rekor-types"
|
||||||
|
version = "0.0.18"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "pydantic", extra = ["email"] },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b4/54/102e772445c5e849b826fbdcd44eb9ad7b3d10fda17b08964658ec7027dc/sigstore_rekor_types-0.0.18.tar.gz", hash = "sha256:19aef25433218ebf9975a1e8b523cc84aaf3cd395ad39a30523b083ea7917ec5", size = 15687, upload-time = "2024-11-22T13:59:54.009Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/45/7c/f0b4e19fd424df4cc964f5d454e1d814fd2dc3b386342e6040441024318f/sigstore_rekor_types-0.0.18-py3-none-any.whl", hash = "sha256:b62bf38c5b1a62bc0d7fe0ee51a0709e49311d137c7880c329882a8f4b2d1d78", size = 20610, upload-time = "2024-11-22T13:59:52.684Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sniffio"
|
name = "sniffio"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
|
|
@ -95,6 +627,19 @@ wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
|
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tuf"
|
||||||
|
version = "6.0.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "securesystemslib" },
|
||||||
|
{ name = "urllib3" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/25/b5/377a566dfa8286b2ca27ddbc792ab1645de0b6c65dd5bf03027b3bf8cc8f/tuf-6.0.0.tar.gz", hash = "sha256:9eed0f7888c5fff45dc62164ff243a05d47fb8a3208035eb268974287e0aee8d", size = 271268, upload-time = "2025-03-11T10:48:45.489Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/6b/3d/161ab4fec446048707cb13e8ba22220e05a6c4a6587d3631feeb5715037e/tuf-6.0.0-py3-none-any.whl", hash = "sha256:458f663a233d95cc76dde0e1a3d01796516a05ce2781fefafebe037f7729601a", size = 54774, upload-time = "2025-03-11T10:48:44.188Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.15.0"
|
version = "4.15.0"
|
||||||
|
|
@ -103,3 +648,24 @@ sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac8
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-inspection"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urllib3"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" },
|
||||||
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue