diff --git a/.gitignore b/.gitignore index b4baf23..2200111 100644 --- a/.gitignore +++ b/.gitignore @@ -83,6 +83,9 @@ continue.md .uv/ .analysis_archive/ +# Claude Code +.claude/ + # Rust med_core_rs/target/ med_core_rs/Cargo.lock diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22 diff --git a/docs/conf.py b/docs/conf.py index 0dbd175..90aef7d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,25 +12,25 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'MedFusion' -copyright = '2024-2026, MedFusion Team' -author = 'MedFusion Team' -release = '0.2.0' +project = "MedFusion" +copyright = "2024-2026, MedFusion Team" +author = "MedFusion Team" +release = "0.2.0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.napoleon', - 'sphinx.ext.viewcode', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.mathjax', - 'sphinx.ext.githubpages', - 'myst_parser', + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.napoleon", + "sphinx.ext.viewcode", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.mathjax", + "sphinx.ext.githubpages", + "myst_parser", ] # Napoleon settings @@ -51,14 +51,14 @@ # Autodoc settings autodoc_default_options = { - 'members': True, - 'member-order': 'bysource', - 'special-members': '__init__', - 'undoc-members': True, - 'exclude-members': '__weakref__' + "members": True, + "member-order": "bysource", + "special-members": "__init__", + "undoc-members": True, + "exclude-members": "__weakref__", } -autodoc_typehints = 'description' -autodoc_typehints_description_target = 'documented' +autodoc_typehints = "description" +autodoc_typehints_description_target = "documented" # Autosummary settings autosummary_generate = True @@ -80,14 +80,14 @@ "tasklist", ] -templates_path = ['_templates'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # -- Options for HTML output ------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output -html_theme = 'furo' -html_static_path = ['_static'] +html_theme = "furo" +html_static_path = ["_static"] html_theme_options = { "light_css_variables": { @@ -112,9 +112,9 @@ # Intersphinx mapping intersphinx_mapping = { - 'python': ('https://docs.python.org/3', None), - 'torch': ('https://pytorch.org/docs/stable/', None), - 'numpy': ('https://numpy.org/doc/stable/', None), + "python": ("https://docs.python.org/3", None), + "torch": ("https://pytorch.org/docs/stable/", None), + "numpy": ("https://numpy.org/doc/stable/", None), } # Todo extension diff --git a/examples/advanced_attention_demo.py b/examples/advanced_attention_demo.py index e48fedb..777e8bc 100644 --- a/examples/advanced_attention_demo.py +++ b/examples/advanced_attention_demo.py @@ -181,7 +181,7 @@ def demo_factory_function(): print(f" • {attn_type:12s}: {x.shape} -> {out.shape}") print("\n使用示例:") - code = ''' + code = """ from med_core.attention_supervision import create_attention_module # 创建注意力模块 @@ -202,7 +202,7 @@ def forward(self, x): x = self.conv(x) x = self.attention(x) # 应用注意力 return x -''' +""" print(code) @@ -267,7 +267,7 @@ def demo_integration_example(): print("=" * 60) print("\n完整的模型集成示例:") - code = ''' + code = """ import torch.nn as nn from med_core.attention_supervision import ( SEAttention, @@ -349,7 +349,7 @@ def compute_loss(self, x, y): loss, loss_dict = model.compute_loss(x, y) print(f"Total loss: {loss.item():.4f}") print(f"Loss components: {loss_dict}") -''' +""" print(code) @@ -403,6 +403,7 @@ def main(): except Exception as e: print(f"\n❌ 错误: {e}") import traceback + traceback.print_exc() diff --git a/examples/benchmark_demo.py b/examples/benchmark_demo.py index 8750509..4d7cccc 100644 --- a/examples/benchmark_demo.py +++ b/examples/benchmark_demo.py @@ -35,7 +35,7 @@ def fast_function(): slow_function() slow_time = time.time() - start print(f" 耗时: {slow_time:.3f}s") - print(f" 吞吐量: {100/slow_time:.1f} ops/s") + print(f" 吞吐量: {100 / slow_time:.1f} ops/s") # 测试快速实现 print("\n2. 测试快速实现:") @@ -44,7 +44,7 @@ def fast_function(): fast_function() fast_time = time.time() - start print(f" 耗时: {fast_time:.3f}s") - print(f" 吞吐量: {100/fast_time:.1f} ops/s") + print(f" 吞吐量: {100 / fast_time:.1f} ops/s") # 比较 speedup = slow_time / fast_time @@ -65,7 +65,7 @@ def demo_benchmark_suite(): print(" • 检测性能回归") print("\n使用示例:") - code = ''' + code = """ from med_core.utils.benchmark import BenchmarkSuite, PerformanceBenchmark # 1. 创建测试套件 @@ -86,7 +86,7 @@ def test_model_inference(): # 5. 与基线比较 suite.compare_with("baseline.json") -''' +""" print(code) @@ -204,7 +204,7 @@ def demo_ci_integration(): print("=" * 60) print("\nGitHub Actions 示例:") - yaml = ''' + yaml = """ name: Performance Benchmarks on: [push, pull_request] @@ -239,7 +239,7 @@ def demo_ci_integration(): with: name: benchmark-results path: benchmarks/ -''' +""" print(yaml) @@ -289,6 +289,7 @@ def main(): except Exception as e: print(f"\n❌ 错误: {e}") import traceback + traceback.print_exc() diff --git a/examples/cache_demo.py b/examples/cache_demo.py index 253b78b..b966976 100644 --- a/examples/cache_demo.py +++ b/examples/cache_demo.py @@ -116,7 +116,7 @@ def demo_usage_example(): print("实际使用示例") print("=" * 60) - code = ''' + code = """ # 1. 创建原始数据集 from med_core.datasets import MedicalDataset @@ -156,7 +156,7 @@ def demo_usage_example(): if hasattr(cached_dataset, 'get_cache_stats'): stats = cached_dataset.get_cache_stats() print(f"缓存命中率: {stats['hit_rate']:.2%}") -''' +""" print("\n代码示例:") print(code) @@ -193,6 +193,7 @@ def main(): except Exception as e: print(f"\n错误: {e}") import traceback + traceback.print_exc() diff --git a/examples/cache_demo_simple.py b/examples/cache_demo_simple.py index a8aa5d1..8e75103 100644 --- a/examples/cache_demo_simple.py +++ b/examples/cache_demo_simple.py @@ -66,11 +66,11 @@ def demo_lru_cache(): # 获取数据 print("\n2. 从缓存获取数据:") - result1 = cache.get('image_001') + result1 = cache.get("image_001") print(f" image_001: {result1} (命中)") - result2 = cache.get('image_002') + result2 = cache.get("image_002") print(f" image_002: {result2} (命中)") - result3 = cache.get('image_999') + result3 = cache.get("image_999") print(f" image_999: {result3} (未命中)") # 添加新数据(触发淘汰) @@ -84,7 +84,7 @@ def demo_lru_cache(): print("\n4. 缓存统计:") stats = cache.get_stats() for key, value in stats.items(): - if key == 'hit_rate': + if key == "hit_rate": print(f" {key}: {value:.2%}") else: print(f" {key}: {value}") @@ -126,7 +126,7 @@ def slow_load_data(idx): if time_with_cache > 0: speedup = time_no_cache / time_with_cache print(f"\n3. 加速比: {speedup:.1f}x") - print(f" 性能提升: {(1 - time_with_cache/time_no_cache) * 100:.1f}%") + print(f" 性能提升: {(1 - time_with_cache / time_no_cache) * 100:.1f}%") def demo_access_patterns(): @@ -185,7 +185,7 @@ def demo_cache_size_impact(): cache.get(idx) stats = cache.get_stats() - hit_rate = stats['hit_rate'] + hit_rate = stats["hit_rate"] if hit_rate < 0.3: desc = "太小,效果差" @@ -264,6 +264,7 @@ def main(): except Exception as e: print(f"\n❌ 错误: {e}") import traceback + traceback.print_exc() diff --git a/examples/distributed_training_demo.py b/examples/distributed_training_demo.py index 8d01a8f..71b4faf 100644 --- a/examples/distributed_training_demo.py +++ b/examples/distributed_training_demo.py @@ -57,8 +57,10 @@ def train_epoch(model, dataloader, criterion, optimizer, device, rank): total += target.size(0) if batch_idx % 10 == 0: - print(f"Rank {rank}: Batch {batch_idx}/{len(dataloader)}, " - f"Loss: {loss.item():.4f}") + print( + f"Rank {rank}: Batch {batch_idx}/{len(dataloader)}, " + f"Loss: {loss.item():.4f}" + ) avg_loss = total_loss / len(dataloader) accuracy = 100.0 * correct / total @@ -135,8 +137,8 @@ def train_ddp(args): optimizer, epoch + 1, f"outputs/checkpoint_ddp_epoch_{epoch + 1}.pt", - loss=avg_metrics['loss'].item(), - accuracy=avg_metrics['accuracy'].item(), + loss=avg_metrics["loss"].item(), + accuracy=avg_metrics["accuracy"].item(), ) # 清理 @@ -219,8 +221,8 @@ def train_fsdp(args): optimizer, epoch + 1, f"outputs/checkpoint_fsdp_epoch_{epoch + 1}.pt", - loss=avg_metrics['loss'].item(), - accuracy=avg_metrics['accuracy'].item(), + loss=avg_metrics["loss"].item(), + accuracy=avg_metrics["accuracy"].item(), ) # 清理 @@ -273,33 +275,40 @@ def main(): parser = argparse.ArgumentParser(description="分布式训练示例") # 训练参数 - parser.add_argument("--strategy", type=str, default="ddp", - choices=["ddp", "fsdp"], - help="分布式策略") - parser.add_argument("--backend", type=str, default="nccl", - choices=["nccl", "gloo", "mpi"], - help="分布式后端") - parser.add_argument("--epochs", type=int, default=5, - help="训练轮数") - parser.add_argument("--batch_size", type=int, default=32, - help="批次大小") - parser.add_argument("--lr", type=float, default=0.001, - help="学习率") - parser.add_argument("--num_samples", type=int, default=1000, - help="样本数量") - parser.add_argument("--save_interval", type=int, default=2, - help="保存间隔") + parser.add_argument( + "--strategy", + type=str, + default="ddp", + choices=["ddp", "fsdp"], + help="分布式策略", + ) + parser.add_argument( + "--backend", + type=str, + default="nccl", + choices=["nccl", "gloo", "mpi"], + help="分布式后端", + ) + parser.add_argument("--epochs", type=int, default=5, help="训练轮数") + parser.add_argument("--batch_size", type=int, default=32, help="批次大小") + parser.add_argument("--lr", type=float, default=0.001, help="学习率") + parser.add_argument("--num_samples", type=int, default=1000, help="样本数量") + parser.add_argument("--save_interval", type=int, default=2, help="保存间隔") # FSDP 参数 - parser.add_argument("--sharding_strategy", type=str, default="FULL_SHARD", - choices=["FULL_SHARD", "SHARD_GRAD_OP", "NO_SHARD", "HYBRID_SHARD"], - help="FSDP 分片策略") - parser.add_argument("--min_num_params", type=int, default=1000, - help="自动包装的最小参数数量") + parser.add_argument( + "--sharding_strategy", + type=str, + default="FULL_SHARD", + choices=["FULL_SHARD", "SHARD_GRAD_OP", "NO_SHARD", "HYBRID_SHARD"], + help="FSDP 分片策略", + ) + parser.add_argument( + "--min_num_params", type=int, default=1000, help="自动包装的最小参数数量" + ) # 其他 - parser.add_argument("--demo", action="store_true", - help="显示使用示例") + parser.add_argument("--demo", action="store_true", help="显示使用示例") args = parser.parse_args() diff --git a/examples/exception_handling_demo.py b/examples/exception_handling_demo.py index 0ad2cb9..0dd6247 100644 --- a/examples/exception_handling_demo.py +++ b/examples/exception_handling_demo.py @@ -27,8 +27,11 @@ def example_backbone_not_found(): try: available_backbones = [ - "resnet18", "resnet50", "efficientnet_b0", - "vit_b_16", "swin_t" + "resnet18", + "resnet50", + "efficientnet_b0", + "vit_b_16", + "swin_t", ] raise BackboneNotFoundError("resnet999", available_backbones) except BackboneNotFoundError as e: @@ -46,7 +49,7 @@ def example_dimension_mismatch(): expected=(32, 3, 224, 224), actual=(32, 3, 256, 256), tensor_name="input_images", - suggestion="Resize images to 224x224 or update model input size" + suggestion="Resize images to 224x224 or update model input size", ) except DimensionMismatchError as e: print(format_error_report(e)) @@ -59,9 +62,7 @@ def example_missing_column(): print("=" * 60) try: - available_columns = [ - "patient_id", "age", "gender", "image_path", "diagnosis" - ] + available_columns = ["patient_id", "age", "gender", "image_path", "diagnosis"] raise MissingColumnError("bmi", available_columns) except MissingColumnError as e: print(format_error_report(e)) @@ -78,7 +79,7 @@ def example_training_error(): "Loss became NaN", epoch=15, step=2500, - suggestion="Reduce learning rate or enable gradient clipping" + suggestion="Reduce learning rate or enable gradient clipping", ) except TrainingError as e: print(format_error_report(e)) @@ -95,9 +96,9 @@ def example_incompatible_config(): "Attention supervision requires CBAM attention mechanism", conflicting_options=[ "training.use_attention_supervision=True", - "model.vision.attention_type='se'" + "model.vision.attention_type='se'", ], - suggestion="Set model.vision.attention_type='cbam'" + suggestion="Set model.vision.attention_type='cbam'", ) except IncompatibleConfigError as e: print(format_error_report(e)) @@ -111,8 +112,7 @@ def example_missing_dependency(): try: raise MissingDependencyError( - "torch", - install_cmd="pip install torch torchvision" + "torch", install_cmd="pip install torch torchvision" ) except MissingDependencyError as e: print(format_error_report(e)) @@ -153,7 +153,7 @@ def example_configuration_error(): "Invalid batch size", config_path="training.batch_size", invalid_value=-1, - suggestion="Batch size must be a positive integer (e.g., 16, 32, 64)" + suggestion="Batch size must be a positive integer (e.g., 16, 32, 64)", ) except ConfigurationError as e: print(format_error_report(e)) diff --git a/examples/gradient_checkpointing_demo.py b/examples/gradient_checkpointing_demo.py index 870008f..a4a03ac 100644 --- a/examples/gradient_checkpointing_demo.py +++ b/examples/gradient_checkpointing_demo.py @@ -65,8 +65,10 @@ def train_without_checkpointing(): if device.type == "cuda": memory_allocated = torch.cuda.memory_allocated() / 1024**2 memory_reserved = torch.cuda.memory_reserved() / 1024**2 - print(f"Batch {batch_idx + 1}: Loss={loss.item():.4f}, " - f"Memory: {memory_allocated:.2f}MB / {memory_reserved:.2f}MB") + print( + f"Batch {batch_idx + 1}: Loss={loss.item():.4f}, " + f"Memory: {memory_allocated:.2f}MB / {memory_reserved:.2f}MB" + ) else: print(f"Batch {batch_idx + 1}: Loss={loss.item():.4f}") @@ -133,8 +135,10 @@ def train_with_checkpointing(): if device.type == "cuda": memory_allocated = torch.cuda.memory_allocated() / 1024**2 memory_reserved = torch.cuda.memory_reserved() / 1024**2 - print(f"Batch {batch_idx + 1}: Loss={loss.item():.4f}, " - f"Memory: {memory_allocated:.2f}MB / {memory_reserved:.2f}MB") + print( + f"Batch {batch_idx + 1}: Loss={loss.item():.4f}, " + f"Memory: {memory_allocated:.2f}MB / {memory_reserved:.2f}MB" + ) else: print(f"Batch {batch_idx + 1}: Loss={loss.item():.4f}") diff --git a/examples/hyperparameter_tuning_demo.py b/examples/hyperparameter_tuning_demo.py index cf6ea45..1b06b32 100644 --- a/examples/hyperparameter_tuning_demo.py +++ b/examples/hyperparameter_tuning_demo.py @@ -39,7 +39,9 @@ def train_and_evaluate(params): train_dataset = TensorDataset(X_train, y_train) val_dataset = TensorDataset(X_val, y_val) - train_loader = DataLoader(train_dataset, batch_size=params["batch_size"], shuffle=True) + train_loader = DataLoader( + train_dataset, batch_size=params["batch_size"], shuffle=True + ) val_loader = DataLoader(val_dataset, batch_size=params["batch_size"]) # 创建模型 @@ -47,11 +49,17 @@ def train_and_evaluate(params): # 优化器 if params["optimizer"] == "adam": - optimizer = optim.Adam(model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"]) + optimizer = optim.Adam( + model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"] + ) elif params["optimizer"] == "sgd": - optimizer = optim.SGD(model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"]) + optimizer = optim.SGD( + model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"] + ) else: - optimizer = optim.AdamW(model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"]) + optimizer = optim.AdamW( + model.parameters(), lr=params["lr"], weight_decay=params["weight_decay"] + ) criterion = nn.CrossEntropyLoss() @@ -92,7 +100,9 @@ def objective(trial): params = { "lr": trial.suggest_float("lr", 1e-5, 1e-1, log=True), "batch_size": trial.suggest_int("batch_size", 16, 128, step=16), - "optimizer": trial.suggest_categorical("optimizer", ["adam", "sgd", "adamw"]), + "optimizer": trial.suggest_categorical( + "optimizer", ["adam", "sgd", "adamw"] + ), "weight_decay": trial.suggest_float("weight_decay", 1e-6, 1e-2, log=True), "dropout": trial.suggest_float("dropout", 0.0, 0.5, step=0.1), } diff --git a/examples/logging_demo.py b/examples/logging_demo.py index 6249596..f0771b3 100644 --- a/examples/logging_demo.py +++ b/examples/logging_demo.py @@ -77,7 +77,9 @@ def example_performance_tracking(): time.sleep(0.05) # Simulate inference # Track with additional context - with PerformanceLogger("batch_processing", logger=logger, log_args=True, batch_size=32): + with PerformanceLogger( + "batch_processing", logger=logger, log_args=True, batch_size=32 + ): time.sleep(0.02) print() @@ -163,12 +165,15 @@ def example_json_logging(): with LogContext(user_id="user123", session_id="sess456"): logger.info("User logged in") logger.info("Processing request", extra={"request_id": "req789"}) - logger.warning("Rate limit approaching", extra={"requests": 95, "limit": 100}) + logger.warning( + "Rate limit approaching", extra={"requests": 95, "limit": 100} + ) # Read and display JSON logs print("\nJSON Log Output:") with open(log_file) as f: import json + for line in f: data = json.loads(line) print(f" {json.dumps(data, indent=2)}") diff --git a/examples/model_export_demo.py b/examples/model_export_demo.py index e42ac36..37de172 100644 --- a/examples/model_export_demo.py +++ b/examples/model_export_demo.py @@ -259,7 +259,9 @@ def demo_inference(): with torch.no_grad(): torchscript_output = loaded_model(x) print(f" 输出形状: {torchscript_output.shape}") - print(f" 与 PyTorch 的差异: {(pytorch_output - torchscript_output).abs().max():.6f}") + print( + f" 与 PyTorch 的差异: {(pytorch_output - torchscript_output).abs().max():.6f}" + ) # 3. ONNX 推理 print("\n3. ONNX 推理:") @@ -271,7 +273,9 @@ def demo_inference(): ort_output = ort_session.run(None, ort_inputs)[0] print(f" 输出形状: {ort_output.shape}") - print(f" 与 PyTorch 的差异: {abs(pytorch_output.numpy() - ort_output).max():.6f}") + print( + f" 与 PyTorch 的差异: {abs(pytorch_output.numpy() - ort_output).max():.6f}" + ) except ImportError: print(" ⚠ ONNXRuntime 未安装,跳过 ONNX 推理") @@ -354,6 +358,7 @@ def main(): except Exception as e: print(f"\n❌ 错误: {e}") import traceback + traceback.print_exc() diff --git a/examples/smurf_usage.py b/examples/smurf_usage.py index 0ff5add..7da82c7 100644 --- a/examples/smurf_usage.py +++ b/examples/smurf_usage.py @@ -17,14 +17,11 @@ def example_basic_usage(): print("=" * 60) # Create model - model = smurf_small( - num_classes=4, - fusion_strategy='fused_attention' - ) + model = smurf_small(num_classes=4, fusion_strategy="fused_attention") # Prepare dummy data ct_scan = torch.randn(2, 1, 64, 128, 128) # [B, C, D, H, W] - pathology = torch.randn(2, 3, 224, 224) # [B, C, H, W] + pathology = torch.randn(2, 3, 224, 224) # [B, C, H, W] # Forward pass model.eval() @@ -45,10 +42,7 @@ def example_with_features(): print("=" * 60) # Create model - model = smurf_small( - num_classes=4, - fusion_strategy='fused_attention' - ) + model = smurf_small(num_classes=4, fusion_strategy="fused_attention") # Prepare data ct_scan = torch.randn(2, 1, 64, 128, 128) @@ -73,10 +67,7 @@ def example_mil(): print("=" * 60) # Create model with MIL - model = smurf_with_mil_small( - num_classes=4, - fusion_strategy='fused_attention' - ) + model = smurf_with_mil_small(num_classes=4, fusion_strategy="fused_attention") # Prepare data with multiple pathology patches ct_scan = torch.randn(2, 1, 64, 128, 128) @@ -95,7 +86,7 @@ def example_mil(): print(f"Output logits: {logits.shape}") # Show attention weights for first sample - attention = features['attention_weights'][0].squeeze() + attention = features["attention_weights"][0].squeeze() print("\nAttention weights for first sample:") for i, weight in enumerate(attention): print(f" Patch {i}: {weight.item():.4f}") @@ -112,7 +103,7 @@ def example_different_fusion_strategies(): ct_scan = torch.randn(2, 1, 64, 128, 128) pathology = torch.randn(2, 3, 224, 224) - strategies = ['concat', 'kronecker', 'fused_attention'] + strategies = ["concat", "kronecker", "fused_attention"] for strategy in strategies: model = smurf_small(num_classes=4, fusion_strategy=strategy) @@ -134,7 +125,7 @@ def example_training_setup(): print("=" * 60) # Create model - model = smurf_small(num_classes=4, fusion_strategy='fused_attention') + model = smurf_small(num_classes=4, fusion_strategy="fused_attention") # Setup optimizer optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=0.01) diff --git a/examples/train_demo.py b/examples/train_demo.py index 1a960a7..26f3e18 100644 --- a/examples/train_demo.py +++ b/examples/train_demo.py @@ -178,18 +178,10 @@ def main(): model=ModelConfig( num_classes=2, vision=VisionConfig( - backbone="resnet18", - pretrained=True, - attention_type="cbam" + backbone="resnet18", pretrained=True, attention_type="cbam" ), - tabular=TabularConfig( - hidden_dims=[32, 16], - output_dim=16 - ), - fusion=FusionConfig( - fusion_type="gated", - hidden_dim=32 - ) + tabular=TabularConfig(hidden_dims=[32, 16], output_dim=16), + fusion=FusionConfig(fusion_type="gated", hidden_dim=32), ), training=TrainingConfig( num_epochs=5, # Short run for demo @@ -197,7 +189,7 @@ def main(): stage1_epochs=1, stage2_epochs=2, stage3_epochs=2, - ) + ), ) # 3. Data Loading @@ -209,12 +201,11 @@ def main(): target_column=config.data.target_column, numerical_features=config.data.numerical_features, categorical_features=config.data.categorical_features, - handle_missing="fill_mean" + handle_missing="fill_mean", ) train_ds, val_ds, test_ds = split_dataset( - full_dataset, - train_ratio=0.7, val_ratio=0.15, test_ratio=0.15 + full_dataset, train_ratio=0.7, val_ratio=0.15, test_ratio=0.15 ) # Add transforms @@ -227,7 +218,7 @@ def main(): val_dataset=val_ds, test_dataset=test_ds, batch_size=config.data.batch_size, - num_workers=config.data.num_workers + num_workers=config.data.num_workers, ) # 4. Model Setup @@ -236,33 +227,32 @@ def main(): backbone_name=config.model.vision.backbone, pretrained=config.model.vision.pretrained, feature_dim=config.model.vision.feature_dim, - attention_type=config.model.vision.attention_type + attention_type=config.model.vision.attention_type, ) tabular_backbone = create_tabular_backbone( input_dim=train_ds.get_tabular_dim(), output_dim=config.model.tabular.output_dim, - hidden_dims=config.model.tabular.hidden_dims + hidden_dims=config.model.tabular.hidden_dims, ) fusion_module = create_fusion_module( fusion_type=config.model.fusion.fusion_type, vision_dim=config.model.vision.feature_dim, tabular_dim=config.model.tabular.output_dim, - output_dim=config.model.fusion.hidden_dim + output_dim=config.model.fusion.hidden_dim, ) model = MultiModalFusionModel( vision_backbone=vision_backbone, tabular_backbone=tabular_backbone, fusion_module=fusion_module, - num_classes=config.model.num_classes + num_classes=config.model.num_classes, ) # 5. Training Setup optimizer = optim.AdamW( - model.parameters(), - lr=config.training.optimizer.learning_rate + model.parameters(), lr=config.training.optimizer.learning_rate ) scheduler = optim.lr_scheduler.CosineAnnealingLR( optimizer, T_max=config.training.num_epochs @@ -274,7 +264,7 @@ def main(): train_loader=dataloaders["train"], val_loader=dataloaders["val"], optimizer=optimizer, - scheduler=scheduler + scheduler=scheduler, ) # 6. Train @@ -306,7 +296,7 @@ def main(): metrics=metrics, output_dir=config.logging.output_dir, experiment_name=config.experiment_name, - config=config.to_dict() + config=config.to_dict(), ) logger.info(f"Demo complete! Report generated at {report_path}") diff --git a/med_core/cli/evaluate.py b/med_core/cli/evaluate.py index d8c8fe1..68b5fcd 100644 --- a/med_core/cli/evaluate.py +++ b/med_core/cli/evaluate.py @@ -138,7 +138,7 @@ def evaluate() -> None: logger.info(f"Loading weights from {args.checkpoint}") try: - checkpoint = torch.load(args.checkpoint, map_location=device) + checkpoint = torch.load(args.checkpoint, map_location=device, weights_only=True) model.load_state_dict(checkpoint["model_state_dict"]) model.to(device) model.eval() diff --git a/med_core/datasets/medical.py b/med_core/datasets/medical.py index 2bf7446..fbc42ea 100644 --- a/med_core/datasets/medical.py +++ b/med_core/datasets/medical.py @@ -190,6 +190,19 @@ def from_csv( else: img_path = image_dir / img_name + # Resolve to absolute path and validate it's within image_dir + try: + img_path = img_path.resolve() + # Ensure the resolved path is within image_dir (prevent path traversal) + if not Path(img_name).is_absolute(): + image_dir_resolved = image_dir.resolve() + if not str(img_path).startswith(str(image_dir_resolved)): + logger.warning(f"Path traversal attempt detected: {img_name}") + continue + except (OSError, RuntimeError) as e: + logger.warning(f"Invalid path {img_name}: {e}") + continue + if img_path.exists(): image_paths.append(img_path) valid_indices.append(idx) diff --git a/med_core/fusion/strategies.py b/med_core/fusion/strategies.py index c4d5f5c..1e4a0ab 100644 --- a/med_core/fusion/strategies.py +++ b/med_core/fusion/strategies.py @@ -149,8 +149,9 @@ def forward( # Apply dropout fused = self.dropout(fused) - # Store gate values for analysis - self._last_gate_values = z.detach() + # Store gate values for analysis (only in eval mode to prevent memory leak) + if not self.training: + self._last_gate_values = z.detach() aux_outputs = { "gate_values": z, @@ -260,8 +261,9 @@ def forward( # Extract CLS token as fused representation fused = tokens[:, 0, :] # (B, D) - # Store attention weights - self._last_attention_weights = attn_weights.detach() + # Store attention weights (only in eval mode to prevent memory leak) + if not self.training: + self._last_attention_weights = attn_weights.detach() aux_outputs = {"attention_weights": attn_weights} @@ -366,9 +368,10 @@ def forward( concat = torch.cat([v2t, t2v], dim=1) # (B, 2D) fused = self.output_proj(concat) # (B, D) - # Store attention weights - self._v2t_attn = v2t_attn.detach() - self._t2v_attn = t2v_attn.detach() + # Store attention weights (only in eval mode to prevent memory leak) + if not self.training: + self._v2t_attn = v2t_attn.detach() + self._t2v_attn = t2v_attn.detach() aux_outputs = { "vision_to_tabular_attn": v2t_attn, diff --git a/med_core/shared/model_utils/metrics.py b/med_core/shared/model_utils/metrics.py index df8b744..ad5ea2e 100644 --- a/med_core/shared/model_utils/metrics.py +++ b/med_core/shared/model_utils/metrics.py @@ -292,7 +292,8 @@ def calculate_confidence_intervals( try: auc_scores.append(roc_auc_score(y_true_boot, y_prob_boot)) accuracy_scores.append(accuracy_score(y_true_boot, y_pred_boot)) - except Exception: + except Exception as e: + logger.debug(f"Bootstrap iteration failed: {e}") continue ci_results = {} diff --git a/med_core/shared/model_utils/training.py b/med_core/shared/model_utils/training.py index 74a7794..c518739 100644 --- a/med_core/shared/model_utils/training.py +++ b/med_core/shared/model_utils/training.py @@ -217,7 +217,7 @@ def load_checkpoint( if not path.exists(): raise FileNotFoundError(f"Checkpoint not found: {path}") - checkpoint = torch.load(path, map_location=device) + checkpoint = torch.load(path, map_location=device, weights_only=True) model.load_state_dict(checkpoint["model_state_dict"]) if optimizer and "optimizer_state_dict" in checkpoint: diff --git a/med_core/trainers/base.py b/med_core/trainers/base.py index 85d8ea3..fcfac34 100644 --- a/med_core/trainers/base.py +++ b/med_core/trainers/base.py @@ -303,7 +303,7 @@ def _handle_checkpointing(self, val_metrics: dict[str, float]): self._save_checkpoint("last.pth", val_metrics) def _save_checkpoint(self, filename: str, metrics: dict[str, float]): - """Save model checkpoint.""" + """Save model checkpoint with atomic write to prevent corruption.""" checkpoint = { "epoch": self.current_epoch, "global_step": self.global_step, @@ -314,7 +314,12 @@ def _save_checkpoint(self, filename: str, metrics: dict[str, float]): } path = self.checkpoint_dir / filename - torch.save(checkpoint, path) + temp_path = path.with_suffix(".tmp") + + # Write to temporary file first + torch.save(checkpoint, temp_path) + # Atomic rename + temp_path.replace(path) def load_checkpoint(self, path: str | Path): """Load model checkpoint.""" @@ -322,7 +327,7 @@ def load_checkpoint(self, path: str | Path): if not path.exists(): raise FileNotFoundError(f"Checkpoint not found: {path}") - checkpoint = torch.load(path, map_location=self.device) + checkpoint = torch.load(path, map_location=self.device, weights_only=True) self.model.load_state_dict(checkpoint["model_state_dict"]) self.optimizer.load_state_dict(checkpoint["optimizer_state_dict"]) self.current_epoch = checkpoint["epoch"] diff --git a/med_core/utils/checkpoint.py b/med_core/utils/checkpoint.py index 720029c..923a938 100644 --- a/med_core/utils/checkpoint.py +++ b/med_core/utils/checkpoint.py @@ -74,7 +74,7 @@ def load_checkpoint( if not filepath.exists(): raise FileNotFoundError(f"Checkpoint not found: {filepath}") - checkpoint = torch.load(filepath, map_location=device) + checkpoint = torch.load(filepath, map_location=device, weights_only=True) model.load_state_dict(checkpoint["model_state_dict"]) diff --git a/med_core/utils/distributed.py b/med_core/utils/distributed.py index 8cae850..0a4912e 100644 --- a/med_core/utils/distributed.py +++ b/med_core/utils/distributed.py @@ -450,7 +450,7 @@ def load_checkpoint( """ # 加载检查点 map_location = {"cuda:0": f"cuda:{get_rank()}"} - checkpoint = torch.load(filepath, map_location=map_location) + checkpoint = torch.load(filepath, map_location=map_location, weights_only=True) # 加载模型状态 if isinstance(model, (DDPWrapper, FSDPWrapper)): diff --git a/med_core/web/checkpoint_manager.py b/med_core/web/checkpoint_manager.py index 39a98ed..2d85896 100644 --- a/med_core/web/checkpoint_manager.py +++ b/med_core/web/checkpoint_manager.py @@ -284,7 +284,7 @@ def _load_models(self, checkpoint_path: Path) -> dict[str, Any]: # 只加载权重字典,不加载模型结构 # 模型结构需要在恢复时重新构建 - state_dict = torch.load(model_file, map_location="cpu") + state_dict = torch.load(model_file, map_location="cpu", weights_only=True) models[f"{node_id}_{model_type}"] = state_dict logger.debug(f"Model weights loaded: {model_file}") diff --git a/med_core/web/node_executors.py b/med_core/web/node_executors.py index 1d0f310..08b801e 100644 --- a/med_core/web/node_executors.py +++ b/med_core/web/node_executors.py @@ -47,6 +47,7 @@ async def execute( Returns: 执行结果字典 """ + # TODO: 子类需要实现具体的执行逻辑 raise NotImplementedError diff --git a/med_core/web/resource_monitor.py b/med_core/web/resource_monitor.py index 1c2ca08..5d09fb3 100644 --- a/med_core/web/resource_monitor.py +++ b/med_core/web/resource_monitor.py @@ -95,8 +95,8 @@ def __del__(self): if self.gpu_available and PYNVML_AVAILABLE: try: pynvml.nvmlShutdown() - except Exception: - pass + except Exception as e: + logger.debug(f"Failed to shutdown NVML during cleanup: {e}") async def start(self) -> None: """启动监控""" @@ -191,7 +191,8 @@ def _get_gpu_info(self) -> list[dict[str, Any]]: temperature = pynvml.nvmlDeviceGetTemperature( handle, pynvml.NVML_TEMPERATURE_GPU ) - except Exception: + except Exception as e: + logger.debug(f"Failed to get GPU temperature: {e}") temperature = None # 功率 @@ -202,7 +203,8 @@ def _get_gpu_info(self) -> list[dict[str, Any]]: power_limit = ( pynvml.nvmlDeviceGetPowerManagementLimit(handle) / 1000.0 ) - except Exception: + except Exception as e: + logger.debug(f"Failed to get GPU power info: {e}") power_usage = None power_limit = None diff --git a/med_core/web/routers/workflow.py b/med_core/web/routers/workflow.py index ca891a0..3d6a101 100644 --- a/med_core/web/routers/workflow.py +++ b/med_core/web/routers/workflow.py @@ -251,13 +251,13 @@ async def progress_callback(node_id: str, status: NodeStatus, progress: float): logger.error(f"WebSocket error for workflow {workflow_id}: {e}") try: await websocket.send_json({"type": "error", "error": str(e)}) - except Exception: - pass + except Exception as send_error: + logger.debug(f"Failed to send error message: {send_error}") finally: try: await websocket.close() - except Exception: - pass + except Exception as close_error: + logger.debug(f"Failed to close websocket: {close_error}") @router.get("/") diff --git a/med_core_rs/analyze_bottleneck.py b/med_core_rs/analyze_bottleneck.py index fb6b408..b40008d 100644 --- a/med_core_rs/analyze_bottleneck.py +++ b/med_core_rs/analyze_bottleneck.py @@ -2,10 +2,11 @@ """ 深度性能分析:找出瓶颈 """ + import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'target/release')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "target/release")) import time @@ -13,9 +14,9 @@ import med_core_rs -print("="*70) +print("=" * 70) print("🔍 深度性能分析:数据拷贝 vs 计算时间") -print("="*70) +print("=" * 70) # Test 1: 测量数据拷贝开销 print("\n[测试 1] 数据拷贝开销分析") @@ -46,9 +47,11 @@ numpy_time = time.perf_counter() - start copy_overhead = copy_time / rust_time * 100 - print(f"批量 {n:4d}: 拷贝 {copy_time*1000:6.2f}ms ({copy_overhead:5.1f}%), " - f"Rust {rust_time*1000:6.2f}ms, NumPy {numpy_time*1000:6.2f}ms, " - f"加速 {numpy_time/rust_time:.2f}x") + print( + f"批量 {n:4d}: 拷贝 {copy_time * 1000:6.2f}ms ({copy_overhead:5.1f}%), " + f"Rust {rust_time * 1000:6.2f}ms, NumPy {numpy_time * 1000:6.2f}ms, " + f"加速 {numpy_time / rust_time:.2f}x" + ) # Test 2: 测量不同操作的时间分布 print("\n[测试 2] Rust 函数内部时间分布估算") @@ -77,11 +80,17 @@ _ = (img - vmin) / (vmax - vmin) compute_time = time.perf_counter() - start -print(f"总时间: {total_time*1000:6.2f} ms (100%)") -print(f"数据传输: {transfer_time*1000:6.2f} ms ({transfer_time/total_time*100:5.1f}%)") -print(f"纯计算: {compute_time*1000:6.2f} ms ({compute_time/total_time*100:5.1f}%)") -print(f"其他开销: {(total_time-transfer_time-compute_time)*1000:6.2f} ms " - f"({(total_time-transfer_time-compute_time)/total_time*100:5.1f}%)") +print(f"总时间: {total_time * 1000:6.2f} ms (100%)") +print( + f"数据传输: {transfer_time * 1000:6.2f} ms ({transfer_time / total_time * 100:5.1f}%)" +) +print( + f"纯计算: {compute_time * 1000:6.2f} ms ({compute_time / total_time * 100:5.1f}%)" +) +print( + f"其他开销: {(total_time - transfer_time - compute_time) * 1000:6.2f} ms " + f"({(total_time - transfer_time - compute_time) / total_time * 100:5.1f}%)" +) # Test 3: 不同方法的性能对比 print("\n[测试 3] 不同归一化方法的性能") @@ -117,8 +126,10 @@ numpy_time = time.perf_counter() - start speedup = numpy_time / rust_time - print(f"{method:12s}: Rust {rust_time*1000:6.2f}ms, " - f"NumPy {numpy_time*1000:6.2f}ms, 加速 {speedup:.2f}x") + print( + f"{method:12s}: Rust {rust_time * 1000:6.2f}ms, " + f"NumPy {numpy_time * 1000:6.2f}ms, 加速 {speedup:.2f}x" + ) # Test 4: 内存布局影响 print("\n[测试 4] 内存布局对性能的影响") @@ -134,11 +145,13 @@ start = time.perf_counter() result = med_core_rs.normalize_intensity_batch(images, method="minmax") elapsed = time.perf_counter() - start - print(f"{name:10s}: {elapsed*1000:6.2f} ms, 连续性: {images.flags['C_CONTIGUOUS']}") + print( + f"{name:10s}: {elapsed * 1000:6.2f} ms, 连续性: {images.flags['C_CONTIGUOUS']}" + ) -print("\n" + "="*70) +print("\n" + "=" * 70) print("💡 分析结论") -print("="*70) +print("=" * 70) print(""" 1. 数据拷贝开销占总时间的 20-30% 2. Python-Rust 边界开销约 10-15% diff --git a/med_core_rs/benchmark_3d.py b/med_core_rs/benchmark_3d.py index a66fadb..7a7cce7 100644 --- a/med_core_rs/benchmark_3d.py +++ b/med_core_rs/benchmark_3d.py @@ -2,10 +2,11 @@ """ Detailed performance analysis for 3D volume processing """ + import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'target/release')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "target/release")) import time @@ -13,9 +14,10 @@ import med_core_rs -print("="*70) +print("=" * 70) print("📊 3D 体积处理性能深度分析") -print("="*70) +print("=" * 70) + def benchmark(func, *args, n_runs=10, warmup=2): """运行基准测试""" @@ -32,6 +34,7 @@ def benchmark(func, *args, n_runs=10, warmup=2): return np.mean(times), np.std(times), result + # Test different batch sizes print("\n[测试 1] 不同批量大小的性能") print("-" * 70) @@ -43,8 +46,7 @@ def benchmark(func, *args, n_runs=10, warmup=2): # Rust rust_mean, rust_std, _ = benchmark( - lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), - volumes + lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), volumes ) # NumPy @@ -60,8 +62,10 @@ def numpy_batch(vols): numpy_mean, numpy_std, _ = benchmark(numpy_batch, volumes) speedup = numpy_mean / rust_mean - print(f"{batch_size:<10} {rust_mean*1000:>10.2f}±{rust_std*1000:.2f} " - f"{numpy_mean*1000:>10.2f}±{numpy_std*1000:.2f} {speedup:>8.2f}x") + print( + f"{batch_size:<10} {rust_mean * 1000:>10.2f}±{rust_std * 1000:.2f} " + f"{numpy_mean * 1000:>10.2f}±{numpy_std * 1000:.2f} {speedup:>8.2f}x" + ) # Test different volume sizes print("\n[测试 2] 不同体积大小的性能 (batch_size=8)") @@ -75,9 +79,7 @@ def numpy_batch(vols): # Rust rust_mean, rust_std, _ = benchmark( - lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), - volumes, - n_runs=5 + lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), volumes, n_runs=5 ) # NumPy @@ -94,8 +96,10 @@ def numpy_batch(vols): speedup = numpy_mean / rust_mean size_str = f"{size[0]}x{size[1]}x{size[2]}" - print(f"{size_str:<15} {rust_mean*1000:>10.2f}±{rust_std*1000:.2f} " - f"{numpy_mean*1000:>10.2f}±{numpy_std*1000:.2f} {speedup:>8.2f}x") + print( + f"{size_str:<15} {rust_mean * 1000:>10.2f}±{rust_std * 1000:.2f} " + f"{numpy_mean * 1000:>10.2f}±{numpy_std * 1000:.2f} {speedup:>8.2f}x" + ) # Test single volume vs batch print("\n[测试 3] 单体积 vs 批量处理") @@ -105,17 +109,14 @@ def numpy_batch(vols): volumes_batch = np.stack([volume] * 16) # Single volume (Rust) -single_rust_mean, _, _ = benchmark( - lambda v: med_core_rs.normalize_3d_minmax(v), - volume -) +single_rust_mean, _, _ = benchmark(lambda v: med_core_rs.normalize_3d_minmax(v), volume) # Batch (Rust) batch_rust_mean, _, _ = benchmark( - lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), - volumes_batch + lambda v: med_core_rs.normalize_3d_batch(v, method="minmax"), volumes_batch ) + # Single volume (NumPy) def numpy_single(vol): vmin, vmax = vol.min(), vol.max() @@ -123,16 +124,19 @@ def numpy_single(vol): return (vol - vmin) / (vmax - vmin) return np.zeros_like(vol) + single_numpy_mean, _, _ = benchmark(numpy_single, volume) -print(f"单体积 Rust: {single_rust_mean*1000:.2f} ms") -print(f"单体积 NumPy: {single_numpy_mean*1000:.2f} ms") -print(f"批量 Rust (16): {batch_rust_mean*1000:.2f} ms ({batch_rust_mean*1000/16:.2f} ms/体积)") -print(f"批量效率: {single_rust_mean*16/batch_rust_mean:.2f}x") +print(f"单体积 Rust: {single_rust_mean * 1000:.2f} ms") +print(f"单体积 NumPy: {single_numpy_mean * 1000:.2f} ms") +print( + f"批量 Rust (16): {batch_rust_mean * 1000:.2f} ms ({batch_rust_mean * 1000 / 16:.2f} ms/体积)" +) +print(f"批量效率: {single_rust_mean * 16 / batch_rust_mean:.2f}x") -print("\n" + "="*70) +print("\n" + "=" * 70) print("💡 分析结论") -print("="*70) +print("=" * 70) print(""" 1. NumPy 在小批量时非常快,因为它的 min/max 操作高度优化 2. Rust 的并行开销在小数据量时不值得 diff --git a/med_core_rs/benchmark_comparison.py b/med_core_rs/benchmark_comparison.py index 84fd670..2b06ad2 100644 --- a/med_core_rs/benchmark_comparison.py +++ b/med_core_rs/benchmark_comparison.py @@ -21,6 +21,7 @@ from med_core_rs import ( normalize_intensity_percentile as rust_percentile, ) + RUST_AVAILABLE = True except ImportError: print("Warning: Rust module not available. Install with: maturin develop --release") @@ -51,9 +52,9 @@ def benchmark_function(func: Callable, *args, iterations: int = 100) -> float: def compare_normalization(): """Compare normalization performance.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("NORMALIZATION BENCHMARK") - print("="*70) + print("=" * 70) sizes = [256, 512, 1024] @@ -65,14 +66,14 @@ def compare_normalization(): py_mean, py_std = benchmark_function( python_normalize, image, "minmax", iterations=50 ) - print(f" Python MinMax: {py_mean*1000:.2f} ± {py_std*1000:.2f} ms") + print(f" Python MinMax: {py_mean * 1000:.2f} ± {py_std * 1000:.2f} ms") if RUST_AVAILABLE: # Rust MinMax - rust_mean, rust_std = benchmark_function( - rust_minmax, image, iterations=50 + rust_mean, rust_std = benchmark_function(rust_minmax, image, iterations=50) + print( + f" Rust MinMax: {rust_mean * 1000:.2f} ± {rust_std * 1000:.2f} ms" ) - print(f" Rust MinMax: {rust_mean*1000:.2f} ± {rust_std*1000:.2f} ms") speedup = py_mean / rust_mean print(f" 🚀 Speedup: {speedup:.2f}x") @@ -82,23 +83,25 @@ def compare_normalization(): py_mean, py_std = benchmark_function( python_normalize, image, "percentile", iterations=50 ) - print(f" Python Percentile: {py_mean*1000:.2f} ± {py_std*1000:.2f} ms") + print(f" Python Percentile: {py_mean * 1000:.2f} ± {py_std * 1000:.2f} ms") if RUST_AVAILABLE: # Rust Percentile rust_mean, rust_std = benchmark_function( rust_percentile, image, 1.0, 99.0, iterations=50 ) - print(f" Rust Percentile: {rust_mean*1000:.2f} ± {rust_std*1000:.2f} ms") + print( + f" Rust Percentile: {rust_mean * 1000:.2f} ± {rust_std * 1000:.2f} ms" + ) speedup = py_mean / rust_mean print(f" 🚀 Speedup: {speedup:.2f}x") def compare_batch_processing(): """Compare batch processing performance.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("BATCH PROCESSING BENCHMARK") - print("="*70) + print("=" * 70) batch_sizes = [10, 50, 100] img_size = 512 @@ -109,22 +112,21 @@ def compare_batch_processing(): # Python sequential processing def python_batch_process(imgs): - return np.array([ - python_normalize(img, "percentile") - for img in imgs - ]) + return np.array([python_normalize(img, "percentile") for img in imgs]) py_mean, py_std = benchmark_function( python_batch_process, images, iterations=20 ) - print(f" Python (sequential): {py_mean*1000:.2f} ± {py_std*1000:.2f} ms") + print(f" Python (sequential): {py_mean * 1000:.2f} ± {py_std * 1000:.2f} ms") if RUST_AVAILABLE: # Rust parallel processing rust_mean, rust_std = benchmark_function( rust_batch, images, "percentile", 1.0, 99.0, iterations=20 ) - print(f" Rust (parallel): {rust_mean*1000:.2f} ± {rust_std*1000:.2f} ms") + print( + f" Rust (parallel): {rust_mean * 1000:.2f} ± {rust_std * 1000:.2f} ms" + ) speedup = py_mean / rust_mean print(f" 🚀 Speedup: {speedup:.2f}x") @@ -134,9 +136,9 @@ def python_batch_process(imgs): def verify_correctness(): """Verify that Rust and Python implementations produce similar results.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("CORRECTNESS VERIFICATION") - print("="*70) + print("=" * 70) if not RUST_AVAILABLE: print("⚠️ Rust module not available, skipping verification") @@ -162,9 +164,9 @@ def verify_correctness(): def main(): - print("\n" + "="*70) + print("\n" + "=" * 70) print("MedCore Rust Acceleration Benchmark") - print("="*70) + print("=" * 70) if not RUST_AVAILABLE: print("\n⚠️ Rust module not found!") @@ -177,9 +179,9 @@ def main(): compare_normalization() compare_batch_processing() - print("\n" + "="*70) + print("\n" + "=" * 70) print("Benchmark Complete!") - print("="*70) + print("=" * 70) if __name__ == "__main__": diff --git a/med_core_rs/benchmark_standalone.py b/med_core_rs/benchmark_standalone.py index 6d836a4..2ded949 100644 --- a/med_core_rs/benchmark_standalone.py +++ b/med_core_rs/benchmark_standalone.py @@ -21,6 +21,7 @@ from med_core_rs import ( normalize_intensity_percentile as rust_percentile, ) + RUST_AVAILABLE = True except ImportError: print("⚠️ Rust 模块未找到") @@ -37,7 +38,9 @@ def numpy_normalize_minmax(image: np.ndarray) -> np.ndarray: return np.zeros_like(image) -def numpy_normalize_percentile(image: np.ndarray, p_low: float = 1.0, p_high: float = 99.0) -> np.ndarray: +def numpy_normalize_percentile( + image: np.ndarray, p_low: float = 1.0, p_high: float = 99.0 +) -> np.ndarray: """NumPy Percentile normalization""" low = np.percentile(image, p_low) high = np.percentile(image, p_high) @@ -46,7 +49,9 @@ def numpy_normalize_percentile(image: np.ndarray, p_low: float = 1.0, p_high: fl return np.zeros_like(image) -def benchmark_function(func: Callable, *args, iterations: int = 50, warmup: int = 5) -> tuple[float, float]: +def benchmark_function( + func: Callable, *args, iterations: int = 50, warmup: int = 5 +) -> tuple[float, float]: """Benchmark a function and return (mean_time, std_time)""" # Warmup for _ in range(warmup): @@ -65,9 +70,9 @@ def benchmark_function(func: Callable, *args, iterations: int = 50, warmup: int def compare_single_image(): """对比单图像处理性能""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("📊 单图像处理性能对比") - print("="*70) + print("=" * 70) sizes = [256, 512, 1024] @@ -78,31 +83,33 @@ def compare_single_image(): # MinMax print("\n MinMax 归一化:") numpy_mean, numpy_std = benchmark_function(numpy_normalize_minmax, image) - print(f" NumPy: {numpy_mean*1000:6.2f} ± {numpy_std*1000:4.2f} ms") + print(f" NumPy: {numpy_mean * 1000:6.2f} ± {numpy_std * 1000:4.2f} ms") if RUST_AVAILABLE: rust_mean, rust_std = benchmark_function(rust_minmax, image) - print(f" Rust: {rust_mean*1000:6.2f} ± {rust_std*1000:4.2f} ms") + print(f" Rust: {rust_mean * 1000:6.2f} ± {rust_std * 1000:4.2f} ms") speedup = numpy_mean / rust_mean print(f" 🚀 加速: {speedup:.2f}x") # Percentile print("\n Percentile 归一化:") - numpy_mean, numpy_std = benchmark_function(numpy_normalize_percentile, image, 1.0, 99.0) - print(f" NumPy: {numpy_mean*1000:6.2f} ± {numpy_std*1000:4.2f} ms") + numpy_mean, numpy_std = benchmark_function( + numpy_normalize_percentile, image, 1.0, 99.0 + ) + print(f" NumPy: {numpy_mean * 1000:6.2f} ± {numpy_std * 1000:4.2f} ms") if RUST_AVAILABLE: rust_mean, rust_std = benchmark_function(rust_percentile, image, 1.0, 99.0) - print(f" Rust: {rust_mean*1000:6.2f} ± {rust_std*1000:4.2f} ms") + print(f" Rust: {rust_mean * 1000:6.2f} ± {rust_std * 1000:4.2f} ms") speedup = numpy_mean / rust_mean print(f" 🚀 加速: {speedup:.2f}x") def compare_batch_processing(): """对比批量处理性能""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("📊 批量处理性能对比") - print("="*70) + print("=" * 70) batch_sizes = [10, 50, 100] img_size = 512 @@ -115,25 +122,31 @@ def compare_batch_processing(): def numpy_batch_process(imgs): return np.array([numpy_normalize_percentile(img) for img in imgs]) - numpy_mean, numpy_std = benchmark_function(numpy_batch_process, images, iterations=20) - print(f" NumPy (顺序): {numpy_mean*1000:7.2f} ± {numpy_std*1000:5.2f} ms") - print(f" {batch_size/numpy_mean:6.1f} 张/秒") + numpy_mean, numpy_std = benchmark_function( + numpy_batch_process, images, iterations=20 + ) + print( + f" NumPy (顺序): {numpy_mean * 1000:7.2f} ± {numpy_std * 1000:5.2f} ms" + ) + print(f" {batch_size / numpy_mean:6.1f} 张/秒") if RUST_AVAILABLE: rust_mean, rust_std = benchmark_function( rust_batch, images, "percentile", 1.0, 99.0, iterations=20 ) - print(f" Rust (并行): {rust_mean*1000:7.2f} ± {rust_std*1000:5.2f} ms") - print(f" {batch_size/rust_mean:6.1f} 张/秒") + print( + f" Rust (并行): {rust_mean * 1000:7.2f} ± {rust_std * 1000:5.2f} ms" + ) + print(f" {batch_size / rust_mean:6.1f} 张/秒") speedup = numpy_mean / rust_mean print(f" 🚀 加速: {speedup:.2f}x") def verify_correctness(): """验证 Rust 和 NumPy 实现的正确性""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("✅ 正确性验证") - print("="*70) + print("=" * 70) if not RUST_AVAILABLE: print("⚠️ Rust 模块不可用,跳过验证") @@ -161,9 +174,9 @@ def verify_correctness(): def print_summary(): """打印总结""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("📈 性能总结") - print("="*70) + print("=" * 70) if not RUST_AVAILABLE: print("\n⚠️ Rust 模块不可用") @@ -186,9 +199,9 @@ def print_summary(): def main(): - print("\n" + "="*70) + print("\n" + "=" * 70) print("🦀 Rust vs NumPy 性能基准测试") - print("="*70) + print("=" * 70) if not RUST_AVAILABLE: print("\n⚠️ Rust 模块未安装!") @@ -200,9 +213,9 @@ def main(): compare_batch_processing() print_summary() - print("\n" + "="*70) + print("\n" + "=" * 70) print("✅ 基准测试完成!") - print("="*70 + "\n") + print("=" * 70 + "\n") if __name__ == "__main__": diff --git a/med_core_rs/example_integration.py b/med_core_rs/example_integration.py index 818fa91..b061680 100644 --- a/med_core_rs/example_integration.py +++ b/med_core_rs/example_integration.py @@ -16,6 +16,7 @@ normalize_intensity_minmax, normalize_intensity_percentile, ) + RUST_AVAILABLE = True print("✅ Rust acceleration available") except ImportError: @@ -71,14 +72,16 @@ def preprocess_single(self, image: np.ndarray) -> np.ndarray: # Crop to target size if self.output_size: if self.use_rust: - image = center_crop_rust(image, self.output_size[0], self.output_size[1]) + image = center_crop_rust( + image, self.output_size[0], self.output_size[1] + ) else: # Python fallback h, w = image.shape th, tw = self.output_size start_h = (h - th) // 2 start_w = (w - tw) // 2 - image = image[start_h:start_h+th, start_w:start_w+tw] + image = image[start_h : start_h + th, start_w : start_w + tw] return image @@ -102,17 +105,16 @@ def preprocess_batch(self, images: np.ndarray) -> np.ndarray: # Parallel normalization images = normalize_intensity_batch( - images, - method=self.normalize_method, - p_low=1.0, - p_high=99.0 + images, method=self.normalize_method, p_low=1.0, p_high=99.0 ) # Crop each image (TODO: batch crop in Rust) if self.output_size: processed = [] for img in images: - cropped = center_crop_rust(img, self.output_size[0], self.output_size[1]) + cropped = center_crop_rust( + img, self.output_size[0], self.output_size[1] + ) processed.append(cropped) images = np.array(processed) @@ -121,17 +123,16 @@ def preprocess_batch(self, images: np.ndarray) -> np.ndarray: def demo_single_image(): """Demo: Process a single image.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("DEMO 1: Single Image Processing") - print("="*70) + print("=" * 70) # Generate test image image = np.random.rand(1024, 1024).astype(np.float32) * 255 print(f"Input image shape: {image.shape}") preprocessor = RustAcceleratedPreprocessor( - normalize_method="percentile", - output_size=(224, 224) + normalize_method="percentile", output_size=(224, 224) ) start = time.perf_counter() @@ -139,15 +140,15 @@ def demo_single_image(): elapsed = time.perf_counter() - start print(f"Output image shape: {processed.shape}") - print(f"Processing time: {elapsed*1000:.2f} ms") + print(f"Processing time: {elapsed * 1000:.2f} ms") print(f"Value range: [{processed.min():.3f}, {processed.max():.3f}]") def demo_batch_processing(): """Demo: Process a batch of images.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("DEMO 2: Batch Processing") - print("="*70) + print("=" * 70) batch_size = 100 img_size = 512 @@ -157,8 +158,7 @@ def demo_batch_processing(): print(f"Input batch shape: {images.shape}") preprocessor = RustAcceleratedPreprocessor( - normalize_method="percentile", - output_size=(224, 224) + normalize_method="percentile", output_size=(224, 224) ) start = time.perf_counter() @@ -166,16 +166,16 @@ def demo_batch_processing(): elapsed = time.perf_counter() - start print(f"Output batch shape: {processed.shape}") - print(f"Total processing time: {elapsed*1000:.2f} ms") - print(f"Time per image: {elapsed/batch_size*1000:.2f} ms") - print(f"Throughput: {batch_size/elapsed:.1f} images/sec") + print(f"Total processing time: {elapsed * 1000:.2f} ms") + print(f"Time per image: {elapsed / batch_size * 1000:.2f} ms") + print(f"Throughput: {batch_size / elapsed:.1f} images/sec") def demo_integration_with_dataloader(): """Demo: Integration with PyTorch DataLoader.""" - print("\n" + "="*70) + print("\n" + "=" * 70) print("DEMO 3: Integration with DataLoader") - print("="*70) + print("=" * 70) try: import torch @@ -188,8 +188,7 @@ class MedicalDataset(Dataset): def __init__(self, num_samples=1000): self.num_samples = num_samples self.preprocessor = RustAcceleratedPreprocessor( - normalize_method="percentile", - output_size=(224, 224) + normalize_method="percentile", output_size=(224, 224) ) def __len__(self): @@ -227,21 +226,21 @@ def __getitem__(self, idx): elapsed = time.perf_counter() - start print(f"\nTotal time: {elapsed:.2f} sec") - print(f"Throughput: {len(dataset)/elapsed:.1f} samples/sec") + print(f"Throughput: {len(dataset) / elapsed:.1f} samples/sec") def main(): - print("\n" + "="*70) + print("\n" + "=" * 70) print("MedCore Rust Acceleration - Integration Examples") - print("="*70) + print("=" * 70) demo_single_image() demo_batch_processing() demo_integration_with_dataloader() - print("\n" + "="*70) + print("\n" + "=" * 70) print("✅ All demos completed!") - print("="*70) + print("=" * 70) print("\nNext steps:") print("1. Integrate into your training pipeline") print("2. Run benchmarks: python benchmark_comparison.py") diff --git a/med_core_rs/integration_example.py b/med_core_rs/integration_example.py index 1df7147..e466f8a 100644 --- a/med_core_rs/integration_example.py +++ b/med_core_rs/integration_example.py @@ -4,10 +4,11 @@ 这个示例展示了如何在真实的训练代码中集成 Rust 加速模块。 """ + import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'target/release')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "target/release")) import time @@ -17,6 +18,7 @@ try: import torch from torch.utils.data import DataLoader + HAS_TORCH = True except ImportError: HAS_TORCH = False @@ -24,14 +26,15 @@ import med_core_rs -print("="*70) +print("=" * 70) print("🚀 MedFusion + Rust 加速集成示例") -print("="*70) +print("=" * 70) # ============================================================================ # 1. 定义数据集 (模拟医学图像数据集) # ============================================================================ + class MedicalImageDataset: """模拟医学图像数据集""" @@ -49,10 +52,12 @@ def __getitem__(self, idx): label = idx % 2 # 二分类 return image, label + # ============================================================================ # 2. 定义 Collate 函数 (关键优化点) # ============================================================================ + def collate_fn_numpy(batch: list[tuple[np.ndarray, int]]): """传统的 NumPy collate 函数""" images, labels = zip(*batch) @@ -71,6 +76,7 @@ def collate_fn_numpy(batch: list[tuple[np.ndarray, int]]): else: return normalized, np.array(labels) + def collate_fn_rust(batch: list[tuple[np.ndarray, int]]): """🚀 使用 Rust 加速的 collate 函数""" images, labels = zip(*batch) @@ -78,10 +84,7 @@ def collate_fn_rust(batch: list[tuple[np.ndarray, int]]): # Rust Percentile 归一化 (4.8x 加速!) normalized = med_core_rs.normalize_intensity_batch( - images, - method="percentile", - p_low=1.0, - p_high=99.0 + images, method="percentile", p_low=1.0, p_high=99.0 ) if HAS_TORCH: @@ -89,15 +92,17 @@ def collate_fn_rust(batch: list[tuple[np.ndarray, int]]): else: return normalized, np.array(labels) + # ============================================================================ # 3. 性能对比测试 # ============================================================================ + def benchmark_dataloader(collate_fn, name: str, n_batches: int = 50): """测试 DataLoader 性能""" - print(f"\n{'='*70}") + print(f"\n{'=' * 70}") print(f"📊 测试: {name}") - print(f"{'='*70}") + print(f"{'=' * 70}") dataset = MedicalImageDataset(n_samples=1000) @@ -107,7 +112,7 @@ def benchmark_dataloader(collate_fn, name: str, n_batches: int = 50): batch_size=32, collate_fn=collate_fn, num_workers=0, # 单进程测试 - shuffle=False + shuffle=False, ) else: # 模拟 DataLoader @@ -119,7 +124,10 @@ def __init__(self, dataset, batch_size, collate_fn): def __iter__(self): for i in range(0, len(self.dataset), self.batch_size): - batch = [self.dataset[j] for j in range(i, min(i + self.batch_size, len(self.dataset)))] + batch = [ + self.dataset[j] + for j in range(i, min(i + self.batch_size, len(self.dataset))) + ] yield self.collate_fn(batch) dataloader = SimpleDataLoader(dataset, batch_size=32, collate_fn=collate_fn) @@ -149,46 +157,56 @@ def __iter__(self): total_time = time.time() - start_total print(f"总时间: {total_time:.2f} 秒") - print(f"平均每批: {np.mean(times)*1000:.2f} ms") + print(f"平均每批: {np.mean(times) * 1000:.2f} ms") print(f"吞吐量: {n_batches * 32 / total_time:.1f} 张/秒") return total_time, np.mean(times) + # ============================================================================ # 4. 运行对比测试 # ============================================================================ -print("\n" + "="*70) +print("\n" + "=" * 70) print("🔬 开始性能对比测试") -print("="*70) +print("=" * 70) # 测试 NumPy 版本 -numpy_total, numpy_avg = benchmark_dataloader(collate_fn_numpy, "NumPy Percentile", n_batches=50) +numpy_total, numpy_avg = benchmark_dataloader( + collate_fn_numpy, "NumPy Percentile", n_batches=50 +) # 测试 Rust 版本 -rust_total, rust_avg = benchmark_dataloader(collate_fn_rust, "Rust Percentile 🚀", n_batches=50) +rust_total, rust_avg = benchmark_dataloader( + collate_fn_rust, "Rust Percentile 🚀", n_batches=50 +) # 计算加速比 speedup = numpy_total / rust_total -print("\n" + "="*70) +print("\n" + "=" * 70) print("📊 性能对比结果") -print("="*70) +print("=" * 70) print(f"{'方法':<20} {'总时间':<15} {'平均每批':<15} {'吞吐量':<15}") -print("-"*70) -print(f"{'NumPy':<20} {numpy_total:>10.2f} s {numpy_avg*1000:>10.2f} ms {50*32/numpy_total:>10.1f} 张/秒") -print(f"{'Rust 🚀':<20} {rust_total:>10.2f} s {rust_avg*1000:>10.2f} ms {50*32/rust_total:>10.1f} 张/秒") -print("-"*70) +print("-" * 70) +print( + f"{'NumPy':<20} {numpy_total:>10.2f} s {numpy_avg * 1000:>10.2f} ms {50 * 32 / numpy_total:>10.1f} 张/秒" +) +print( + f"{'Rust 🚀':<20} {rust_total:>10.2f} s {rust_avg * 1000:>10.2f} ms {50 * 32 / rust_total:>10.1f} 张/秒" +) +print("-" * 70) print(f"{'加速比':<20} {speedup:>10.2f}x") -print("="*70) +print("=" * 70) # ============================================================================ # 5. 实际训练示例 # ============================================================================ -print("\n" + "="*70) +print("\n" + "=" * 70) print("🎓 实际训练流程示例") -print("="*70) +print("=" * 70) + def train_one_epoch_simulation(dataloader, name: str): """模拟训练一个 epoch""" @@ -213,44 +231,59 @@ def train_one_epoch_simulation(dataloader, name: str): elapsed = time.time() - start print(f" Epoch 完成: {elapsed:.2f} 秒") - print(f" 平均 loss: {total_loss / (i+1):.4f}") + print(f" 平均 loss: {total_loss / (i + 1):.4f}") return elapsed + # 创建数据集 dataset = MedicalImageDataset(n_samples=1000) # NumPy 版本 if HAS_TORCH: - dataloader_numpy = DataLoader(dataset, batch_size=32, collate_fn=collate_fn_numpy, num_workers=0) + dataloader_numpy = DataLoader( + dataset, batch_size=32, collate_fn=collate_fn_numpy, num_workers=0 + ) else: + class SimpleDataLoader: def __init__(self, dataset, batch_size, collate_fn): self.dataset = dataset self.batch_size = batch_size self.collate_fn = collate_fn + def __iter__(self): for i in range(0, len(self.dataset), self.batch_size): - batch = [self.dataset[j] for j in range(i, min(i + self.batch_size, len(self.dataset)))] + batch = [ + self.dataset[j] + for j in range(i, min(i + self.batch_size, len(self.dataset))) + ] yield self.collate_fn(batch) - dataloader_numpy = SimpleDataLoader(dataset, batch_size=32, collate_fn=collate_fn_numpy) + + dataloader_numpy = SimpleDataLoader( + dataset, batch_size=32, collate_fn=collate_fn_numpy + ) numpy_epoch_time = train_one_epoch_simulation(dataloader_numpy, "NumPy") # Rust 版本 if HAS_TORCH: - dataloader_rust = DataLoader(dataset, batch_size=32, collate_fn=collate_fn_rust, num_workers=0) + dataloader_rust = DataLoader( + dataset, batch_size=32, collate_fn=collate_fn_rust, num_workers=0 + ) else: - dataloader_rust = SimpleDataLoader(dataset, batch_size=32, collate_fn=collate_fn_rust) + dataloader_rust = SimpleDataLoader( + dataset, batch_size=32, collate_fn=collate_fn_rust + ) rust_epoch_time = train_one_epoch_simulation(dataloader_rust, "Rust 🚀") # 计算训练加速 train_speedup = numpy_epoch_time / rust_epoch_time -print("\n" + "="*70) +print("\n" + "=" * 70) print("🎯 训练性能提升") -print("="*70) +print("=" * 70) print(f"NumPy epoch 时间: {numpy_epoch_time:.2f} 秒") print(f"Rust epoch 时间: {rust_epoch_time:.2f} 秒") print(f"加速比: {train_speedup:.2f}x") @@ -259,9 +292,9 @@ def __iter__(self): print(f" Rust: {rust_epoch_time * 100 / 60:.1f} 分钟") print(f" 节省: {(numpy_epoch_time - rust_epoch_time) * 100 / 60:.1f} 分钟") -print("\n" + "="*70) +print("\n" + "=" * 70) print("✅ 集成示例完成!") -print("="*70) +print("=" * 70) print(""" 📝 如何在你的项目中使用: diff --git a/med_core_rs/test_3d.py b/med_core_rs/test_3d.py index a89ed2a..25f819e 100644 --- a/med_core_rs/test_3d.py +++ b/med_core_rs/test_3d.py @@ -2,10 +2,11 @@ """ Test 3D volume preprocessing functions """ + import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'target/release')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "target/release")) import time @@ -13,14 +14,15 @@ try: import med_core_rs + print("✅ med_core_rs 模块加载成功") except ImportError as e: print(f"❌ 无法加载 med_core_rs: {e}") sys.exit(1) -print("\n" + "="*60) +print("\n" + "=" * 60) print("🧪 3D 体积处理功能测试") -print("="*60) +print("=" * 60) # Test 1: Single volume normalization print("\n[测试 1] 单个 3D 体积归一化") @@ -35,8 +37,12 @@ # Percentile normalization result_percentile = med_core_rs.normalize_3d_percentile(volume, p_low=1.0, p_high=99.0) -print(f"Percentile 归一化: 范围 [{result_percentile.min():.4f}, {result_percentile.max():.4f}]") -assert result_percentile.min() >= 0.0 and result_percentile.max() <= 1.0, "Percentile 归一化失败" +print( + f"Percentile 归一化: 范围 [{result_percentile.min():.4f}, {result_percentile.max():.4f}]" +) +assert result_percentile.min() >= 0.0 and result_percentile.max() <= 1.0, ( + "Percentile 归一化失败" +) print("✅ Percentile 归一化正确") # Test 2: Batch processing @@ -49,8 +55,8 @@ result_batch = med_core_rs.normalize_3d_batch(volumes, method="percentile") elapsed = time.time() - start -print(f"批量处理完成: {elapsed*1000:.2f} ms") -print(f"吞吐量: {batch_size/elapsed:.1f} 体积/秒") +print(f"批量处理完成: {elapsed * 1000:.2f} ms") +print(f"吞吐量: {batch_size / elapsed:.1f} 体积/秒") print(f"输出形状: {result_batch.shape}") assert result_batch.shape == volumes.shape, "批量处理形状不匹配" print("✅ 批量处理正确") @@ -62,11 +68,13 @@ target_shape = (32, 64, 64) start = time.time() -resampled = med_core_rs.resample_3d(volume, target_shape[0], target_shape[1], target_shape[2]) +resampled = med_core_rs.resample_3d( + volume, target_shape[0], target_shape[1], target_shape[2] +) elapsed = time.time() - start print(f"重采样后形状: {resampled.shape}") -print(f"重采样耗时: {elapsed*1000:.2f} ms") +print(f"重采样耗时: {elapsed * 1000:.2f} ms") assert resampled.shape == target_shape, "重采样形状不匹配" print("✅ 重采样正确") @@ -80,6 +88,7 @@ rust_result = med_core_rs.normalize_3d_batch(volumes, method="minmax") rust_time = time.time() - start + # NumPy processing def numpy_normalize_batch(volumes): result = np.zeros_like(volumes) @@ -90,13 +99,18 @@ def numpy_normalize_batch(volumes): result[i] = (vol - vmin) / (vmax - vmin) return result + start = time.time() numpy_result = numpy_normalize_batch(volumes) numpy_time = time.time() - start speedup = numpy_time / rust_time -print(f"Rust 批量处理: {rust_time*1000:.2f} ms ({batch_size/rust_time:.1f} 体积/秒)") -print(f"NumPy 批量处理: {numpy_time*1000:.2f} ms ({batch_size/numpy_time:.1f} 体积/秒)") +print( + f"Rust 批量处理: {rust_time * 1000:.2f} ms ({batch_size / rust_time:.1f} 体积/秒)" +) +print( + f"NumPy 批量处理: {numpy_time * 1000:.2f} ms ({batch_size / numpy_time:.1f} 体积/秒)" +) print(f"🚀 加速比: {speedup:.2f}x") # Verify correctness @@ -105,13 +119,13 @@ def numpy_normalize_batch(volumes): assert max_diff < 1e-5, "结果不匹配" print("✅ 结果正确性验证通过") -print("\n" + "="*60) +print("\n" + "=" * 60) print("🎉 所有测试通过!") -print("="*60) +print("=" * 60) print("\n📊 性能总结:") -print(f" - 单体积归一化: ~{elapsed*1000:.1f} ms") -print(f" - 批量处理 ({batch_size} 体积): {rust_time*1000:.1f} ms") -print(f" - 吞吐量: {batch_size/rust_time:.1f} 体积/秒") +print(f" - 单体积归一化: ~{elapsed * 1000:.1f} ms") +print(f" - 批量处理 ({batch_size} 体积): {rust_time * 1000:.1f} ms") +print(f" - 吞吐量: {batch_size / rust_time:.1f} 体积/秒") print(f" - 相比 NumPy 加速: {speedup:.2f}x") -print(f" - 3D 重采样: ~{elapsed*1000:.1f} ms") +print(f" - 3D 重采样: ~{elapsed * 1000:.1f} ms") diff --git a/med_core_rs/test_mil.py b/med_core_rs/test_mil.py index 417da33..bc22360 100644 --- a/med_core_rs/test_mil.py +++ b/med_core_rs/test_mil.py @@ -2,10 +2,11 @@ """ Test MIL aggregation functions """ + import os import sys -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'target/release')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "target/release")) import time @@ -13,22 +14,26 @@ try: import med_core_rs + print("✅ med_core_rs 模块加载成功") except ImportError as e: print(f"❌ 无法加载 med_core_rs: {e}") sys.exit(1) -print("\n" + "="*60) +print("\n" + "=" * 60) print("🧪 MIL 聚合器功能测试") -print("="*60) +print("=" * 60) # Test 1: Max pooling print("\n[测试 1] Max Pooling MIL") -instances = np.array([ - [1.0, 2.0, 3.0, 4.0], - [5.0, 1.0, 2.0, 3.0], - [2.0, 4.0, 1.0, 5.0], -], dtype=np.float32) +instances = np.array( + [ + [1.0, 2.0, 3.0, 4.0], + [5.0, 1.0, 2.0, 3.0], + [2.0, 4.0, 1.0, 5.0], + ], + dtype=np.float32, +) print(f"输入实例: {instances.shape}") result = med_core_rs.max_pooling_mil(instances) @@ -39,11 +44,14 @@ # Test 2: Mean pooling print("\n[测试 2] Mean Pooling MIL") -instances = np.array([ - [1.0, 2.0], - [3.0, 4.0], - [5.0, 6.0], -], dtype=np.float32) +instances = np.array( + [ + [1.0, 2.0], + [3.0, 4.0], + [5.0, 6.0], + ], + dtype=np.float32, +) result = med_core_rs.mean_pooling_mil(instances) print(f"Mean pooling 结果: {result}") @@ -53,11 +61,14 @@ # Test 3: Attention MIL print("\n[测试 3] Attention MIL") -instances = np.array([ - [1.0, 2.0], - [3.0, 4.0], - [5.0, 6.0], -], dtype=np.float32) +instances = np.array( + [ + [1.0, 2.0], + [3.0, 4.0], + [5.0, 6.0], + ], + dtype=np.float32, +) attention_weights = np.array([[0.5], [0.3], [0.2]], dtype=np.float32) result = med_core_rs.attention_mil(instances, attention_weights) @@ -70,8 +81,10 @@ # Test 4: Batch processing print("\n[测试 4] 批量 MIL 聚合") n_bags = 100 -bags = [np.random.rand(np.random.randint(10, 50), 512).astype(np.float32) - for _ in range(n_bags)] +bags = [ + np.random.rand(np.random.randint(10, 50), 512).astype(np.float32) + for _ in range(n_bags) +] print(f"批量大小: {n_bags} bags") print("特征维度: 512") @@ -80,14 +93,14 @@ start = time.time() result_max = med_core_rs.batch_mil_aggregation(bags, method="max") time_max = time.time() - start -print(f"Max pooling: {time_max*1000:.2f} ms ({n_bags/time_max:.1f} bags/秒)") +print(f"Max pooling: {time_max * 1000:.2f} ms ({n_bags / time_max:.1f} bags/秒)") assert result_max.shape == (n_bags, 512), f"形状不匹配: {result_max.shape}" # Mean pooling start = time.time() result_mean = med_core_rs.batch_mil_aggregation(bags, method="mean") time_mean = time.time() - start -print(f"Mean pooling: {time_mean*1000:.2f} ms ({n_bags/time_mean:.1f} bags/秒)") +print(f"Mean pooling: {time_mean * 1000:.2f} ms ({n_bags / time_mean:.1f} bags/秒)") assert result_mean.shape == (n_bags, 512), f"形状不匹配: {result_mean.shape}" print("✅ 批量处理正确") @@ -95,25 +108,29 @@ # Test 5: Performance comparison print("\n[测试 5] 性能对比 (Rust vs NumPy)") n_bags = 200 -bags = [np.random.rand(np.random.randint(20, 100), 512).astype(np.float32) - for _ in range(n_bags)] +bags = [ + np.random.rand(np.random.randint(20, 100), 512).astype(np.float32) + for _ in range(n_bags) +] # Rust batch processing start = time.time() rust_result = med_core_rs.batch_mil_aggregation(bags, method="max") rust_time = time.time() - start + # NumPy processing def numpy_batch_max(bags): return np.array([bag.max(axis=0) for bag in bags]) + start = time.time() numpy_result = numpy_batch_max(bags) numpy_time = time.time() - start speedup = numpy_time / rust_time -print(f"Rust 批量处理: {rust_time*1000:.2f} ms ({n_bags/rust_time:.1f} bags/秒)") -print(f"NumPy 批量处理: {numpy_time*1000:.2f} ms ({n_bags/numpy_time:.1f} bags/秒)") +print(f"Rust 批量处理: {rust_time * 1000:.2f} ms ({n_bags / rust_time:.1f} bags/秒)") +print(f"NumPy 批量处理: {numpy_time * 1000:.2f} ms ({n_bags / numpy_time:.1f} bags/秒)") print(f"🚀 加速比: {speedup:.2f}x") # Verify correctness @@ -122,12 +139,12 @@ def numpy_batch_max(bags): assert max_diff < 1e-5, "结果不匹配" print("✅ 结果正确性验证通过") -print("\n" + "="*60) +print("\n" + "=" * 60) print("🎉 所有测试通过!") -print("="*60) +print("=" * 60) print("\n📊 性能总结:") -print(f" - Max pooling (100 bags): {time_max*1000:.1f} ms") -print(f" - Mean pooling (100 bags): {time_mean*1000:.1f} ms") -print(f" - 吞吐量: {n_bags/rust_time:.1f} bags/秒") +print(f" - Max pooling (100 bags): {time_max * 1000:.1f} ms") +print(f" - Mean pooling (100 bags): {time_mean * 1000:.1f} ms") +print(f" - 吞吐量: {n_bags / rust_time:.1f} bags/秒") print(f" - 相比 NumPy 加速: {speedup:.2f}x") diff --git a/med_core_rs/test_percentile_analysis.py b/med_core_rs/test_percentile_analysis.py index fec4e06..6dec16c 100644 --- a/med_core_rs/test_percentile_analysis.py +++ b/med_core_rs/test_percentile_analysis.py @@ -11,14 +11,16 @@ def test_percentile_algorithms(): """对比不同大小数据的 percentile 计算""" - print("="*70) + print("=" * 70) print("Percentile 算法性能对比") - print("="*70) + print("=" * 70) - sizes = [256*256, 512*512, 1024*1024] + sizes = [256 * 256, 512 * 512, 1024 * 1024] for size in sizes: - print(f"\n数据大小: {size:,} 个元素 ({int(np.sqrt(size))}×{int(np.sqrt(size))})") + print( + f"\n数据大小: {size:,} 个元素 ({int(np.sqrt(size))}×{int(np.sqrt(size))})" + ) data = np.random.rand(size).astype(np.float32) * 255 @@ -31,7 +33,7 @@ def test_percentile_algorithms(): times.append(time.perf_counter() - start) numpy_time = np.mean(times) - print(f" NumPy percentile: {numpy_time*1000:6.2f} ms") + print(f" NumPy percentile: {numpy_time * 1000:6.2f} ms") # 纯 Python 排序 times = [] @@ -45,15 +47,16 @@ def test_percentile_algorithms(): times.append(time.perf_counter() - start) sort_time = np.mean(times) - print(f" NumPy sort: {sort_time*1000:6.2f} ms") - print(f" 排序 vs percentile: {sort_time/numpy_time:.2f}x") + print(f" NumPy sort: {sort_time * 1000:6.2f} ms") + print(f" 排序 vs percentile: {sort_time / numpy_time:.2f}x") + if __name__ == "__main__": test_percentile_algorithms() - print("\n" + "="*70) + print("\n" + "=" * 70) print("结论:") - print("="*70) + print("=" * 70) print("NumPy 的 percentile 函数已经高度优化(使用 quickselect)") print("我们的 Rust 实现需要:") print(" 1. 数据从 Python 传到 Rust(开销)") diff --git a/med_core_rs/test_quick.py b/med_core_rs/test_quick.py index fcd9ad6..c61e6be 100644 --- a/med_core_rs/test_quick.py +++ b/med_core_rs/test_quick.py @@ -16,6 +16,7 @@ normalize_intensity_minmax, normalize_intensity_percentile, ) + print("✅ 模块导入成功!") except ImportError as e: print(f"❌ 导入失败: {e}") @@ -30,16 +31,20 @@ normalized = normalize_intensity_minmax(image) elapsed = time.perf_counter() - start -print(f" 输出: {normalized.shape}, 范围: [{normalized.min():.2f}, {normalized.max():.2f}]") -print(f" ⏱️ 耗时: {elapsed*1000:.2f} ms") +print( + f" 输出: {normalized.shape}, 范围: [{normalized.min():.2f}, {normalized.max():.2f}]" +) +print(f" ⏱️ 耗时: {elapsed * 1000:.2f} ms") # 测试 2: Percentile 归一化 print("\n📊 测试 2: Percentile 归一化") start = time.perf_counter() normalized = normalize_intensity_percentile(image, 1.0, 99.0) elapsed = time.perf_counter() - start -print(f" 输出: {normalized.shape}, 范围: [{normalized.min():.2f}, {normalized.max():.2f}]") -print(f" ⏱️ 耗时: {elapsed*1000:.2f} ms") +print( + f" 输出: {normalized.shape}, 范围: [{normalized.min():.2f}, {normalized.max():.2f}]" +) +print(f" ⏱️ 耗时: {elapsed * 1000:.2f} ms") # 测试 3: 批量处理 print("\n📊 测试 3: 批量处理 (100 张图像)") @@ -51,9 +56,9 @@ elapsed = time.perf_counter() - start print(f" 输出: {normalized_batch.shape}") -print(f" ⏱️ 总耗时: {elapsed*1000:.2f} ms") -print(f" ⏱️ 单张耗时: {elapsed/100*1000:.2f} ms") -print(f" 📈 吞吐量: {100/elapsed:.1f} 张/秒") +print(f" ⏱️ 总耗时: {elapsed * 1000:.2f} ms") +print(f" ⏱️ 单张耗时: {elapsed / 100 * 1000:.2f} ms") +print(f" 📈 吞吐量: {100 / elapsed:.1f} 张/秒") # 测试 4: 中心裁剪 print("\n📊 测试 4: 中心裁剪") @@ -62,7 +67,7 @@ cropped = center_crop_rust(image, 224, 224) elapsed = time.perf_counter() - start print(f" 输入: {image.shape} -> 输出: {cropped.shape}") -print(f" ⏱️ 耗时: {elapsed*1000:.2f} ms") +print(f" ⏱️ 耗时: {elapsed * 1000:.2f} ms") # 测试 5: 正确性验证 print("\n📊 测试 5: 正确性验证") diff --git a/notebooks/quickstart.ipynb b/notebooks/quickstart.ipynb index ed5292c..4d004bd 100644 --- a/notebooks/quickstart.ipynb +++ b/notebooks/quickstart.ipynb @@ -13,8 +13,7 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "print('MedFusion 已加载')" + "print(\"MedFusion 已加载\")" ] } ], diff --git a/scripts/analyze_coverage.py b/scripts/analyze_coverage.py index d0cdb85..fa2c493 100644 --- a/scripts/analyze_coverage.py +++ b/scripts/analyze_coverage.py @@ -14,10 +14,10 @@ def find_python_files(directory): python_files = [] for root, dirs, files in os.walk(directory): # Skip __pycache__ and hidden directories - dirs[:] = [d for d in dirs if not d.startswith('__') and not d.startswith('.')] + dirs[:] = [d for d in dirs if not d.startswith("__") and not d.startswith(".")] for file in files: - if file.endswith('.py') and not file.startswith('__'): + if file.endswith(".py") and not file.startswith("__"): python_files.append(os.path.join(root, file)) return sorted(python_files) @@ -28,7 +28,7 @@ def find_test_files(directory): test_files = [] for root, _dirs, files in os.walk(directory): for file in files: - if file.startswith('test_') and file.endswith('.py'): + if file.startswith("test_") and file.endswith(".py"): test_files.append(os.path.join(root, file)) return sorted(test_files) @@ -37,15 +37,15 @@ def find_test_files(directory): def get_module_name(filepath, base_dir): """Convert file path to module name.""" rel_path = os.path.relpath(filepath, base_dir) - module = rel_path.replace(os.sep, '.').replace('.py', '') + module = rel_path.replace(os.sep, ".").replace(".py", "") return module def analyze_coverage(): """Analyze test coverage.""" base_dir = Path(__file__).parent.parent - med_core_dir = base_dir / 'med_core' - tests_dir = base_dir / 'tests' + med_core_dir = base_dir / "med_core" + tests_dir = base_dir / "tests" print("=" * 80) print("MedFusion Test Coverage Analysis") @@ -76,8 +76,8 @@ def analyze_coverage(): filename = os.path.basename(filepath) # Extract module name from test file # e.g., test_backbones.py -> backbones - if filename.startswith('test_'): - module = filename[5:].replace('.py', '') + if filename.startswith("test_"): + module = filename[5:].replace(".py", "") if module not in test_modules: test_modules[module] = [] test_modules[module].append(filepath) @@ -109,7 +109,9 @@ def analyze_coverage(): print("-" * 80) coverage_pct = (total_with_tests / len(modules) * 100) if modules else 0 - print(f"Overall module coverage: {total_with_tests}/{len(modules)} ({coverage_pct:.1f}%)") + print( + f"Overall module coverage: {total_with_tests}/{len(modules)} ({coverage_pct:.1f}%)" + ) print() # Identify modules needing tests @@ -143,7 +145,7 @@ def analyze_coverage(): return needs_tests -if __name__ == '__main__': +if __name__ == "__main__": needs_tests = analyze_coverage() if needs_tests: diff --git a/scripts/ci_diagnostic.py b/scripts/ci_diagnostic.py index 4cad98c..19ec9a6 100644 --- a/scripts/ci_diagnostic.py +++ b/scripts/ci_diagnostic.py @@ -6,21 +6,20 @@ import subprocess import sys from pathlib import Path -from typing import List, Tuple class Colors: - GREEN = '\033[0;32m' - RED = '\033[0;31m' - YELLOW = '\033[1;33m' - BLUE = '\033[0;34m' - NC = '\033[0m' + GREEN = "\033[0;32m" + RED = "\033[0;31m" + YELLOW = "\033[1;33m" + BLUE = "\033[0;34m" + NC = "\033[0m" def print_header(text: str): print(f"\n{'=' * 80}") print(f" {text}") - print('=' * 80) + print("=" * 80) def print_step(text: str): @@ -39,15 +38,11 @@ def print_warning(text: str): print(f"{Colors.YELLOW}⚠ {text}{Colors.NC}") -def run_command(cmd: List[str], check: bool = True) -> Tuple[bool, str]: +def run_command(cmd: list[str], check: bool = True) -> tuple[bool, str]: """运行命令并返回结果""" try: result = subprocess.run( - cmd, - capture_output=True, - text=True, - check=check, - timeout=60 + cmd, capture_output=True, text=True, check=check, timeout=60 ) return True, result.stdout + result.stderr except subprocess.CalledProcessError as e: @@ -167,8 +162,7 @@ def check_code_quality(): # Ruff 检查 print_step("Ruff Linting") success, output = run_command( - ["ruff", "check", "med_core/", "tests/", "--output-format=text"], - check=False + ["ruff", "check", "med_core/", "tests/", "--output-format=text"], check=False ) if success: print_success("Ruff 检查通过") @@ -179,8 +173,7 @@ def check_code_quality(): # Ruff 格式检查 print_step("Ruff Format") success, output = run_command( - ["ruff", "format", "--check", "med_core/", "tests/"], - check=False + ["ruff", "format", "--check", "med_core/", "tests/"], check=False ) if success: print_success("代码格式正确") @@ -191,8 +184,7 @@ def check_code_quality(): # mypy 类型检查 print_step("mypy 类型检查") success, output = run_command( - ["mypy", "med_core/", "--ignore-missing-imports"], - check=False + ["mypy", "med_core/", "--ignore-missing-imports"], check=False ) if success: print_success("类型检查通过") @@ -221,8 +213,7 @@ def check_tests(): # 运行测试 print_step("运行测试") success, output = run_command( - [sys.executable, "-m", "pytest", "tests/", "-v", "--tb=short"], - check=False + [sys.executable, "-m", "pytest", "tests/", "-v", "--tb=short"], check=False ) if success: print_success("测试通过") @@ -255,8 +246,7 @@ def check_scripts(): # 检查语法 success, output = run_command( - [sys.executable, "-m", "py_compile", script], - check=False + [sys.executable, "-m", "py_compile", script], check=False ) if success: print_success(f"{script}") @@ -287,8 +277,17 @@ def check_docker(): # 尝试验证 Dockerfile 语法 print_step("验证 Dockerfile 语法") success, output = run_command( - ["docker", "build", "--no-cache", "-f", "Dockerfile", "-t", "medfusion:test", "."], - check=False + [ + "docker", + "build", + "--no-cache", + "-f", + "Dockerfile", + "-t", + "medfusion:test", + ".", + ], + check=False, ) if success: print_success("Docker 构建成功") @@ -320,8 +319,7 @@ def check_examples(): for example in example_files: success, output = run_command( - [sys.executable, "-m", "py_compile", str(example)], - check=False + [sys.executable, "-m", "py_compile", str(example)], check=False ) if success: print_success(f"{example.name}") diff --git a/scripts/compare_benchmarks.py b/scripts/compare_benchmarks.py index 20bc2bc..ffc43cc 100644 --- a/scripts/compare_benchmarks.py +++ b/scripts/compare_benchmarks.py @@ -46,7 +46,9 @@ def compare_dict(base_dict, curr_dict, path=""): if isinstance(base_val, dict) and isinstance(curr_val, dict): # 递归比较 compare_dict(base_val, curr_val, f"{path}.{key}" if path else key) - elif isinstance(base_val, (int, float)) and isinstance(curr_val, (int, float)): + elif isinstance(base_val, (int, float)) and isinstance( + curr_val, (int, float) + ): # 比较数值 if key == "throughput": # 吞吐量:越高越好 @@ -97,7 +99,9 @@ def print_comparison(comparisons, verbose=False): # 按是否回归分组 regressions = [c for c in comparisons if c["is_regression"]] - improvements = [c for c in comparisons if c["change"] > 5 and not c["is_regression"]] + improvements = [ + c for c in comparisons if c["change"] > 5 and not c["is_regression"] + ] stable = [c for c in comparisons if abs(c["change"]) <= 5] # 打印回归 diff --git a/scripts/full_workflow_test.py b/scripts/full_workflow_test.py index 762e586..e0237bc 100644 --- a/scripts/full_workflow_test.py +++ b/scripts/full_workflow_test.py @@ -114,7 +114,7 @@ def main(): config.data.image_dir = str(data_dir / "images") config.logging.output_dir = "outputs/full_workflow_test" - logger.info(f"✅ 配置加载成功") + logger.info("✅ 配置加载成功") logger.info(f" - 实验名称: {config.experiment_name}") logger.info(f" - 模型: {config.model.vision.backbone}") logger.info(f" - 融合方式: {config.model.fusion.fusion_type}") @@ -155,7 +155,7 @@ def main(): num_workers=0, # 避免多进程问题 ) - logger.info(f"✅ 数据集准备完成") + logger.info("✅ 数据集准备完成") logger.info(f" - 训练集: {len(train_ds)} 样本") logger.info(f" - 验证集: {len(val_ds)} 样本") logger.info(f" - 测试集: {len(test_ds)} 样本") @@ -194,7 +194,7 @@ def main(): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = model.to(device) - logger.info(f"✅ 模型创建完成") + logger.info("✅ 模型创建完成") logger.info(f" - 设备: {device}") logger.info(f" - 参数量: {sum(p.numel() for p in model.parameters()):,}") @@ -204,7 +204,9 @@ def main(): logger.info("=" * 60) criterion = nn.CrossEntropyLoss() - optimizer = optim.Adam(model.parameters(), lr=config.training.optimizer.learning_rate) + optimizer = optim.Adam( + model.parameters(), lr=config.training.optimizer.learning_rate + ) for epoch in range(config.training.num_epochs): model.train() @@ -238,9 +240,11 @@ def main(): train_loss = total_loss / len(dataloaders["train"]) train_acc = 100.0 * correct / total - logger.info(f"Epoch {epoch + 1}/{config.training.num_epochs} - Loss: {train_loss:.4f}, Acc: {train_acc:.2f}%") + logger.info( + f"Epoch {epoch + 1}/{config.training.num_epochs} - Loss: {train_loss:.4f}, Acc: {train_acc:.2f}%" + ) - logger.info(f"✅ 训练完成") + logger.info("✅ 训练完成") # 6. 评估模型 logger.info("\n" + "=" * 60) @@ -277,7 +281,7 @@ def main(): y_prob=all_probs, ) - logger.info(f"✅ 评估完成") + logger.info("✅ 评估完成") logger.info(f" - Accuracy: {metrics['accuracy']:.4f}") logger.info(f" - AUC: {metrics['auc']:.4f}") logger.info(f" - F1 Score: {metrics['f1']:.4f}") @@ -313,10 +317,10 @@ def main(): logger.info("\n" + "=" * 60) logger.info("🎉 完整工作流测试完成!") logger.info("=" * 60) - logger.info(f"测试结果:") - logger.info(f" ✅ 配置加载: 成功") + logger.info("测试结果:") + logger.info(" ✅ 配置加载: 成功") logger.info(f" ✅ 数据准备: 成功 ({len(full_dataset)} 样本)") - logger.info(f" ✅ 模型创建: 成功") + logger.info(" ✅ 模型创建: 成功") logger.info(f" ✅ 模型训练: 成功 ({config.training.num_epochs} epochs)") logger.info(f" ✅ 模型评估: 成功 (Acc: {metrics['accuracy']:.2%})") logger.info(f" {report_status}: 报告生成") diff --git a/scripts/generate_mock_data.py b/scripts/generate_mock_data.py index 5321265..05a9a17 100644 --- a/scripts/generate_mock_data.py +++ b/scripts/generate_mock_data.py @@ -51,7 +51,9 @@ def generate_mock_images(output_dir: Path, num_images: int = 10, image_size: int return image_paths -def generate_mock_metadata(output_dir: Path, image_paths: list[str], num_samples: int = 10): +def generate_mock_metadata( + output_dir: Path, image_paths: list[str], num_samples: int = 10 +): """ Generate mock patient metadata CSV. @@ -109,7 +111,9 @@ def main(): print(f"Output directory: {output_dir.absolute()}") # Generate images - print(f"\n1. Generating {args.num_samples} images ({args.image_size}x{args.image_size})...") + print( + f"\n1. Generating {args.num_samples} images ({args.image_size}x{args.image_size})..." + ) image_paths = generate_mock_images( output_dir, num_images=args.num_samples, image_size=args.image_size ) @@ -117,7 +121,9 @@ def main(): # Generate metadata print("\n2. Generating metadata CSV...") - csv_path = generate_mock_metadata(output_dir, image_paths, num_samples=args.num_samples) + csv_path = generate_mock_metadata( + output_dir, image_paths, num_samples=args.num_samples + ) print(f" ✓ Metadata saved to {csv_path}") # Summary @@ -126,12 +132,14 @@ def main(): print("=" * 60) print("\nGenerated files:") print(f" - {args.num_samples} images in {output_dir / 'images'}") - print(" - metadata.csv with columns: patient_id, image_path, age, gender, diagnosis") + print( + " - metadata.csv with columns: patient_id, image_path, age, gender, diagnosis" + ) print("\nTo use this data:") print(" 1. Update your config YAML:") print(" data:") - print(f" csv_path: \"{csv_path}\"") - print(f" image_dir: \"{output_dir}\"") + print(f' csv_path: "{csv_path}"') + print(f' image_dir: "{output_dir}"') print(" 2. Run training:") print(" uv run med-train --config configs/your_config.yaml") diff --git a/scripts/generate_test_stubs.py b/scripts/generate_test_stubs.py index 28c61cd..0b278a6 100644 --- a/scripts/generate_test_stubs.py +++ b/scripts/generate_test_stubs.py @@ -36,16 +36,14 @@ def test_basic_functionality(self): def create_test_file(module_name, test_path): """Create a basic test file for a module.""" - class_name = ''.join(word.capitalize() for word in module_name.split('_')) + class_name = "".join(word.capitalize() for word in module_name.split("_")) import_path = f"med_core.{module_name}" content = BASIC_TEST_TEMPLATE.format( - module_name=module_name, - class_name=class_name, - import_path=import_path + module_name=module_name, class_name=class_name, import_path=import_path ) - with open(test_path, 'w') as f: + with open(test_path, "w") as f: f.write(content) print(f"✅ Created: {test_path}") @@ -54,15 +52,15 @@ def create_test_file(module_name, test_path): def main(): """Generate test files for modules without tests.""" base_dir = Path(__file__).parent.parent - tests_dir = base_dir / 'tests' + tests_dir = base_dir / "tests" # Modules that need tests (from coverage analysis) modules_needing_tests = [ - 'extractors', - 'models', - 'shared', - 'utils', - 'visualization', + "extractors", + "models", + "shared", + "utils", + "visualization", ] print("=" * 80) @@ -85,5 +83,5 @@ def main(): print("=" * 80) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/scripts/quick_ci_test.py b/scripts/quick_ci_test.py index 9c7401e..cc7f038 100644 --- a/scripts/quick_ci_test.py +++ b/scripts/quick_ci_test.py @@ -2,6 +2,7 @@ """ 简化的 CI 本地测试脚本 """ + import subprocess import sys from pathlib import Path diff --git a/scripts/quick_simulation_test.py b/scripts/quick_simulation_test.py index 786e4bb..2508dea 100644 --- a/scripts/quick_simulation_test.py +++ b/scripts/quick_simulation_test.py @@ -14,13 +14,11 @@ """ import logging -import sys import time from pathlib import Path import numpy as np import pandas as pd -import torch from PIL import Image # 设置日志 diff --git a/scripts/simple_test.py b/scripts/simple_test.py index 2590e40..472626e 100644 --- a/scripts/simple_test.py +++ b/scripts/simple_test.py @@ -23,7 +23,9 @@ from med_core.backbones import create_tabular_backbone, create_vision_backbone from med_core.fusion import MultiModalFusionModel, create_fusion_module -logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s") +logging.basicConfig( + level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s" +) logger = logging.getLogger(__name__) # 测试记录 diff --git a/scripts/smoke_test.py b/scripts/smoke_test.py index 0baac67..89481f6 100644 --- a/scripts/smoke_test.py +++ b/scripts/smoke_test.py @@ -54,7 +54,9 @@ def analyze_model_architecture(model: nn.Module, config): print(f" Frozen: {config.model.vision.freeze_backbone}") print(f" Output Dim: {vision.output_dim}") print(f" Parameters: {sum(p.numel() for p in vision.parameters()):,}") - print(f" Trainable: {sum(p.numel() for p in vision.parameters() if p.requires_grad):,}") + print( + f" Trainable: {sum(p.numel() for p in vision.parameters() if p.requires_grad):,}" + ) # Tabular Backbone print_subsection("Tabular Backbone") @@ -63,7 +65,9 @@ def analyze_model_architecture(model: nn.Module, config): print(f" Hidden Dims: {config.model.tabular.hidden_dims}") print(f" Output Dim: {tabular.output_dim}") print(f" Parameters: {sum(p.numel() for p in tabular.parameters()):,}") - print(f" Trainable: {sum(p.numel() for p in tabular.parameters() if p.requires_grad):,}") + print( + f" Trainable: {sum(p.numel() for p in tabular.parameters() if p.requires_grad):,}" + ) # Fusion Module print_subsection("Fusion Module") @@ -122,9 +126,13 @@ def test_dimension_alignment(model: nn.Module, sample_batch): # Check auxiliary heads if present if "vision_logits" in outputs: - print(f" Vision Logits (aux): {tuple(outputs['vision_logits'].shape)}") + print( + f" Vision Logits (aux): {tuple(outputs['vision_logits'].shape)}" + ) if "tabular_logits" in outputs: - print(f" Tabular Logits (aux): {tuple(outputs['tabular_logits'].shape)}") + print( + f" Tabular Logits (aux): {tuple(outputs['tabular_logits'].shape)}" + ) else: logits = outputs print_subsection("Forward Pass Results") @@ -197,7 +205,9 @@ def test_gradient_flow(model: nn.Module, sample_batch, criterion): return False -def test_training_loop(model, train_loader, val_loader, criterion, optimizer, num_epochs=3): +def test_training_loop( + model, train_loader, val_loader, criterion, optimizer, num_epochs=3 +): """Test training loop and loss convergence.""" print_section("TRAINING LOOP TEST") @@ -258,7 +268,9 @@ def test_training_loop(model, train_loader, val_loader, criterion, optimizer, nu avg_val_loss = epoch_val_loss / num_val_batches val_losses.append(avg_val_loss) - print(f" Epoch {epoch + 1}/{num_epochs}: Train Loss = {avg_train_loss:.4f}, Val Loss = {avg_val_loss:.4f}") + print( + f" Epoch {epoch + 1}/{num_epochs}: Train Loss = {avg_train_loss:.4f}, Val Loss = {avg_val_loss:.4f}" + ) # Analyze loss trends print_subsection("Loss Analysis") @@ -291,7 +303,9 @@ def generate_report(results: dict): status = "✓ PASS" if passed else "✗ FAIL" print(f" {status}: {test_name}") - print(f"\n Overall Status: {'✓ ALL TESTS PASSED' if all_passed else '✗ SOME TESTS FAILED'}") + print( + f"\n Overall Status: {'✓ ALL TESTS PASSED' if all_passed else '✗ SOME TESTS FAILED'}" + ) if all_passed: print("\n 🎉 Framework is ready for production use!") @@ -302,7 +316,9 @@ def generate_report(results: dict): def main(): - parser = argparse.ArgumentParser(description="Run smoke test for Med-Core framework") + parser = argparse.ArgumentParser( + description="Run smoke test for Med-Core framework" + ) parser.add_argument( "--config", type=str, @@ -426,7 +442,12 @@ def main(): # Test 4: Training Loop optimizer = torch.optim.Adam(model.parameters(), lr=0.001) train_losses, val_losses = test_training_loop( - model, dataloaders["train"], dataloaders["val"], criterion, optimizer, num_epochs=args.epochs + model, + dataloaders["train"], + dataloaders["val"], + criterion, + optimizer, + num_epochs=args.epochs, ) results["Training Loop"] = True diff --git a/scripts/test_attention_supervision.py b/scripts/test_attention_supervision.py index ace3d7b..1882487 100644 --- a/scripts/test_attention_supervision.py +++ b/scripts/test_attention_supervision.py @@ -81,6 +81,7 @@ def generate_synthetic_data(output_dir: Path, num_samples: int = 200): data.append(record) import pandas as pd + df = pd.DataFrame(data) csv_path = output_dir / "dataset.csv" df.to_csv(csv_path, index=False) @@ -89,11 +90,13 @@ def generate_synthetic_data(output_dir: Path, num_samples: int = 200): return csv_path -def train_model(model, train_loader, val_loader, device, num_epochs=5, model_name="Model"): +def train_model( + model, train_loader, val_loader, device, num_epochs=5, model_name="Model" +): """训练模型""" - logger.info(f"\n{'='*60}") + logger.info(f"\n{'=' * 60}") logger.info(f"训练 {model_name}") - logger.info(f"{'='*60}") + logger.info(f"{'=' * 60}") criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) @@ -163,8 +166,8 @@ def train_model(model, train_loader, val_loader, device, num_epochs=5, model_nam logger.info( f"Epoch {epoch + 1}/{num_epochs} - " - f"Train Loss: {train_loss/len(train_loader):.4f}, Train Acc: {train_acc:.2f}% | " - f"Val Loss: {val_loss/len(val_loader):.4f}, Val Acc: {val_acc:.2f}%" + f"Train Loss: {train_loss / len(train_loader):.4f}, Train Acc: {train_acc:.2f}% | " + f"Val Loss: {val_loss / len(val_loader):.4f}, Val Acc: {val_acc:.2f}%" ) logger.info(f"✅ {model_name} 训练完成 - 最佳验证准确率: {best_val_acc:.2f}%") @@ -173,9 +176,9 @@ def train_model(model, train_loader, val_loader, device, num_epochs=5, model_nam def evaluate_model(model, test_loader, device, model_name="Model"): """评估模型""" - logger.info(f"\n{'='*60}") + logger.info(f"\n{'=' * 60}") logger.info(f"评估 {model_name}") - logger.info(f"{'='*60}") + logger.info(f"{'=' * 60}") model.eval() all_preds = [] @@ -207,7 +210,7 @@ def evaluate_model(model, test_loader, device, model_name="Model"): y_prob=all_probs, ) - logger.info(f"测试结果:") + logger.info("测试结果:") logger.info(f" - Accuracy: {metrics['accuracy']:.4f}") logger.info(f" - AUC: {metrics['auc']:.4f}") logger.info(f" - F1 Score: {metrics['f1']:.4f}") @@ -264,7 +267,7 @@ def main(): num_workers=0, ) - logger.info(f"✅ 数据集准备完成") + logger.info("✅ 数据集准备完成") logger.info(f" - 训练集: {len(train_ds)} 样本") logger.info(f" - 验证集: {len(val_ds)} 样本") logger.info(f" - 测试集: {len(test_ds)} 样本") @@ -303,7 +306,7 @@ def main(): num_classes=2, ) - logger.info(f"✅ 基线模型创建完成") + logger.info("✅ 基线模型创建完成") # 4. 创建注意力监督模型 logger.info("\n" + "=" * 60) @@ -337,7 +340,7 @@ def main(): num_classes=2, ) - logger.info(f"✅ 注意力模型创建完成") + logger.info("✅ 注意力模型创建完成") # 5. 训练基线模型 best_val_acc_baseline = train_model( @@ -380,22 +383,24 @@ def main(): logger.info("📊 对比结果") logger.info("=" * 60) - logger.info(f"\n验证集最佳准确率:") + logger.info("\n验证集最佳准确率:") logger.info(f" 基线模型: {best_val_acc_baseline:.2f}%") logger.info(f" 注意力模型: {best_val_acc_attention:.2f}%") logger.info(f" 提升: {best_val_acc_attention - best_val_acc_baseline:+.2f}%") - logger.info(f"\n测试集准确率:") + logger.info("\n测试集准确率:") logger.info(f" 基线模型: {metrics_baseline['accuracy']:.4f}") logger.info(f" 注意力模型: {metrics_attention['accuracy']:.4f}") - logger.info(f" 提升: {metrics_attention['accuracy'] - metrics_baseline['accuracy']:+.4f}") + logger.info( + f" 提升: {metrics_attention['accuracy'] - metrics_baseline['accuracy']:+.4f}" + ) - logger.info(f"\n测试集 AUC:") + logger.info("\n测试集 AUC:") logger.info(f" 基线模型: {metrics_baseline['auc']:.4f}") logger.info(f" 注意力模型: {metrics_attention['auc']:.4f}") logger.info(f" 提升: {metrics_attention['auc'] - metrics_baseline['auc']:+.4f}") - logger.info(f"\n测试集 F1 Score:") + logger.info("\n测试集 F1 Score:") logger.info(f" 基线模型: {metrics_baseline['f1']:.4f}") logger.info(f" 注意力模型: {metrics_attention['f1']:.4f}") logger.info(f" 提升: {metrics_attention['f1'] - metrics_baseline['f1']:+.4f}") @@ -405,18 +410,18 @@ def main(): logger.info("💡 结论") logger.info("=" * 60) - improvement = metrics_attention['accuracy'] - metrics_baseline['accuracy'] + improvement = metrics_attention["accuracy"] - metrics_baseline["accuracy"] if improvement > 0.02: # 提升超过 2% logger.info("✅ 注意力监督有明显效果,建议保留") - logger.info(f" 准确率提升: {improvement:.4f} ({improvement*100:.2f}%)") + logger.info(f" 准确率提升: {improvement:.4f} ({improvement * 100:.2f}%)") elif improvement > 0: logger.info("⚠️ 注意力监督有轻微提升,但不明显") - logger.info(f" 准确率提升: {improvement:.4f} ({improvement*100:.2f}%)") + logger.info(f" 准确率提升: {improvement:.4f} ({improvement * 100:.2f}%)") logger.info(" 建议:在真实数据上测试后再决定") else: logger.info("❌ 注意力监督没有提升,甚至可能降低性能") - logger.info(f" 准确率变化: {improvement:.4f} ({improvement*100:.2f}%)") + logger.info(f" 准确率变化: {improvement:.4f} ({improvement * 100:.2f}%)") logger.info(" 建议:删除注意力监督模块(2,678 行代码)") logger.info("\n注意:这是合成数据测试,真实数据可能有不同结果") diff --git a/scripts/test_enhanced_report.py b/scripts/test_enhanced_report.py index 1bdd944..ddd1ead 100644 --- a/scripts/test_enhanced_report.py +++ b/scripts/test_enhanced_report.py @@ -14,7 +14,6 @@ import matplotlib.pyplot as plt import numpy as np -import torch from sklearn.metrics import roc_curve # Add project root to path @@ -28,8 +27,7 @@ ) logging.basicConfig( - level=logging.INFO, - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" + level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s" ) logger = logging.getLogger(__name__) @@ -42,10 +40,7 @@ def create_sample_metrics(accuracy: float = 0.95, n_samples: int = 100): n_negative = n_samples - n_positive # True labels - y_true = np.concatenate([ - np.ones(n_positive), - np.zeros(n_negative) - ]) + y_true = np.concatenate([np.ones(n_positive), np.zeros(n_negative)]) # Predictions with specified accuracy y_pred = y_true.copy() @@ -69,18 +64,18 @@ def create_high_res_roc_plot(y_true, y_scores, output_path: Path, dpi: int = 300 fpr, tpr, _ = roc_curve(y_true, y_scores) plt.figure(figsize=(8, 6)) - plt.plot(fpr, tpr, linewidth=2, label='ROC Curve') - plt.plot([0, 1], [0, 1], 'k--', linewidth=1, label='Random Classifier') + plt.plot(fpr, tpr, linewidth=2, label="ROC Curve") + plt.plot([0, 1], [0, 1], "k--", linewidth=1, label="Random Classifier") plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.05]) - plt.xlabel('False Positive Rate', fontsize=12) - plt.ylabel('True Positive Rate', fontsize=12) - plt.title('Receiver Operating Characteristic (ROC) Curve', fontsize=14) + plt.xlabel("False Positive Rate", fontsize=12) + plt.ylabel("True Positive Rate", fontsize=12) + plt.title("Receiver Operating Characteristic (ROC) Curve", fontsize=14) plt.legend(loc="lower right", fontsize=11) plt.grid(True, alpha=0.3) plt.tight_layout() - plt.savefig(output_path, dpi=dpi, bbox_inches='tight') + plt.savefig(output_path, dpi=dpi, bbox_inches="tight") plt.close() logger.info(f"✅ High-resolution ROC curve saved: {output_path}") @@ -88,34 +83,43 @@ def create_high_res_roc_plot(y_true, y_scores, output_path: Path, dpi: int = 300 def create_high_res_confusion_matrix(metrics, output_path: Path, dpi: int = 300): """Create high-resolution confusion matrix plot.""" - cm = np.array([ - [metrics.true_negatives, metrics.false_positives], - [metrics.false_negatives, metrics.true_positives] - ]) + cm = np.array( + [ + [metrics.true_negatives, metrics.false_positives], + [metrics.false_negatives, metrics.true_positives], + ] + ) fig, ax = plt.subplots(figsize=(8, 6)) - im = ax.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues) + im = ax.imshow(cm, interpolation="nearest", cmap=plt.cm.Blues) ax.figure.colorbar(im, ax=ax) - ax.set(xticks=np.arange(cm.shape[1]), - yticks=np.arange(cm.shape[0]), - xticklabels=['Negative', 'Positive'], - yticklabels=['Negative', 'Positive'], - title='Confusion Matrix', - ylabel='True Label', - xlabel='Predicted Label') + ax.set( + xticks=np.arange(cm.shape[1]), + yticks=np.arange(cm.shape[0]), + xticklabels=["Negative", "Positive"], + yticklabels=["Negative", "Positive"], + title="Confusion Matrix", + ylabel="True Label", + xlabel="Predicted Label", + ) # Add text annotations - thresh = cm.max() / 2. + thresh = cm.max() / 2.0 for i in range(cm.shape[0]): for j in range(cm.shape[1]): - ax.text(j, i, format(cm[i, j], 'd'), - ha="center", va="center", - color="white" if cm[i, j] > thresh else "black", - fontsize=14) + ax.text( + j, + i, + format(cm[i, j], "d"), + ha="center", + va="center", + color="white" if cm[i, j] > thresh else "black", + fontsize=14, + ) plt.tight_layout() - plt.savefig(output_path, dpi=dpi, bbox_inches='tight') + plt.savefig(output_path, dpi=dpi, bbox_inches="tight") plt.close() logger.info(f"✅ High-resolution confusion matrix saved: {output_path}") @@ -183,7 +187,9 @@ def test_statistical_comparison(): # Generate baseline and improved metrics baseline_metrics, _, _ = create_sample_metrics(accuracy=0.85, n_samples=200) - improved_metrics, y_true, y_scores = create_sample_metrics(accuracy=0.92, n_samples=200) + improved_metrics, y_true, y_scores = create_sample_metrics( + accuracy=0.92, n_samples=200 + ) logger.info(f"Baseline 准确率: {baseline_metrics.accuracy:.4f}") logger.info(f"改进后准确率: {improved_metrics.accuracy:.4f}") @@ -213,7 +219,7 @@ def test_statistical_comparison(): logger.info(f"✅ 报告生成成功: {report_path}") # Read and display statistical tests section - with open(report_path, 'r', encoding='utf-8') as f: + with open(report_path, encoding="utf-8") as f: content = f.read() if "Statistical Significance Tests" in content: logger.info("✅ 统计检验部分已添加到报告") @@ -271,7 +277,7 @@ def test_latex_output(): logger.info(f"✅ LaTeX 报告生成成功: {latex_path}") # Display LaTeX table - with open(latex_path, 'r', encoding='utf-8') as f: + with open(latex_path, encoding="utf-8") as f: content = f.read() # Extract table start = content.find("\\begin{table}") diff --git a/scripts/test_pluggability.py b/scripts/test_pluggability.py index bee4a5d..87d3561 100644 --- a/scripts/test_pluggability.py +++ b/scripts/test_pluggability.py @@ -28,7 +28,11 @@ if "PYTEST_CURRENT_TEST" in os.environ or "pytest" in sys.modules: try: import pytest # type: ignore - pytest.skip("Script-style tests are skipped during pytest collection", allow_module_level=True) + + pytest.skip( + "Script-style tests are skipped during pytest collection", + allow_module_level=True, + ) except Exception: # If pytest cannot be imported for some reason, simply exit early to avoid collection. # This branch is conservative: in normal script execution pytest won't be in sys.modules @@ -285,8 +289,8 @@ def main(): failed = sum(1 for r in results if r["status"] == "FAIL") print(f"\n Total Tests: {total_tests}") - print(f" Passed: {passed} ({passed/total_tests*100:.1f}%)") - print(f" Failed: {failed} ({failed/total_tests*100:.1f}%)") + print(f" Passed: {passed} ({passed / total_tests * 100:.1f}%)") + print(f" Failed: {failed} ({failed / total_tests * 100:.1f}%)") if failed > 0: print("\n Failed Combinations:") @@ -302,14 +306,26 @@ def main(): for vision in vision_backbones: vision_results = [r for r in results if r["vision"] == vision] vision_passed = sum(1 for r in vision_results if r["status"] == "PASS") - status = "PASS" if vision_passed == len(vision_results) else "PARTIAL" if vision_passed > 0 else "FAIL" + status = ( + "PASS" + if vision_passed == len(vision_results) + else "PARTIAL" + if vision_passed > 0 + else "FAIL" + ) print_result("Vision", vision, status) print("\n Fusion Strategies:") for fusion in fusion_types: fusion_results = [r for r in results if r["fusion"] == fusion] fusion_passed = sum(1 for r in fusion_results if r["status"] == "PASS") - status = "PASS" if fusion_passed == len(fusion_results) else "PARTIAL" if fusion_passed > 0 else "FAIL" + status = ( + "PASS" + if fusion_passed == len(fusion_results) + else "PARTIAL" + if fusion_passed > 0 + else "FAIL" + ) print_result("Fusion", fusion, status) print("\n Tabular Configurations:") @@ -317,7 +333,13 @@ def main(): tabular_str = str(tabular) tabular_results = [r for r in results if r["tabular"] == tabular_str] tabular_passed = sum(1 for r in tabular_results if r["status"] == "PASS") - status = "PASS" if tabular_passed == len(tabular_results) else "PARTIAL" if tabular_passed > 0 else "FAIL" + status = ( + "PASS" + if tabular_passed == len(tabular_results) + else "PARTIAL" + if tabular_passed > 0 + else "FAIL" + ) print_result("Tabular", tabular_str, status) # Final verdict diff --git a/scripts/verify_ci_fixes.py b/scripts/verify_ci_fixes.py index 970c7e4..52d575a 100644 --- a/scripts/verify_ci_fixes.py +++ b/scripts/verify_ci_fixes.py @@ -2,6 +2,7 @@ """ CI 配置验证脚本 - 检查所有修复是否正确应用 """ + import sys from pathlib import Path @@ -14,13 +15,13 @@ def check_pyproject(): issues = [] # 检查 dev 依赖位置 - if '[project.optional-dependencies]' in content and 'dev = [' in content: + if "[project.optional-dependencies]" in content and "dev = [" in content: print(" ✓ dev 依赖在正确位置 (optional-dependencies)") else: issues.append("dev 依赖配置错误") # 检查是否还有 dependency-groups - if '[dependency-groups]' in content: + if "[dependency-groups]" in content: issues.append("仍然存在 [dependency-groups] 节") else: print(" ✓ 已移除 [dependency-groups]") @@ -48,13 +49,13 @@ def check_ci_workflow(): issues.append("测试矩阵配置不正确") # 检查安全工具版本 - if 'bandit==1.7.5 safety==3.0.1' in content: + if "bandit==1.7.5 safety==3.0.1" in content: print(" ✓ 安全工具版本已固定") else: issues.append("安全工具版本未固定") # 检查 Docker 平台 - if 'platforms: linux/amd64' in content: + if "platforms: linux/amd64" in content: print(" ✓ Docker 构建限制为单平台") else: issues.append("Docker 平台配置不正确") @@ -70,13 +71,13 @@ def check_setup_action(): issues = [] # 检查缓存配置 - if 'actions/cache@v4' in content: + if "actions/cache@v4" in content: print(" ✓ 已添加依赖缓存") else: issues.append("缺少缓存配置") # 检查缓存路径 - if '~/.cache/uv' in content: + if "~/.cache/uv" in content: print(" ✓ uv 缓存路径正确") else: issues.append("uv 缓存路径不正确") @@ -158,7 +159,9 @@ def main(): if passed == total: print("\n✓ 所有配置修复已正确应用!") print("\n下一步:") - print(" 1. 提交更改: git add -A && git commit -m 'fix: CI configuration issues'") + print( + " 1. 提交更改: git add -A && git commit -m 'fix: CI configuration issues'" + ) print(" 2. 推送到远程: git push") print(" 3. 观察 GitHub Actions 运行结果") return 0 diff --git a/src/data/dataset.py b/src/data/dataset.py index 306319d..8be6b06 100644 --- a/src/data/dataset.py +++ b/src/data/dataset.py @@ -25,6 +25,7 @@ # Optional DICOM support try: import pydicom + PYDICOM_AVAILABLE = True except ImportError: PYDICOM_AVAILABLE = False @@ -51,7 +52,9 @@ def __init__( label_column: str = "label", feature_columns: list[str] | None = None, transform: Callable | None = None, - intensity_norm: Literal["minmax", "zscore", "percentile", "none"] = "percentile", + intensity_norm: Literal[ + "minmax", "zscore", "percentile", "none" + ] = "percentile", percentile_range: tuple[float, float] = (1.0, 99.0), target_size: tuple[int, int] | None = None, ): @@ -86,7 +89,9 @@ def __init__( # Auto-detect feature columns if not provided if feature_columns is None: exclude_cols = {image_column, label_column, "patient_id", "study_id"} - feature_columns = [col for col in self.df.columns if col not in exclude_cols] + feature_columns = [ + col for col in self.df.columns if col not in exclude_cols + ] self.feature_columns = feature_columns @@ -129,7 +134,9 @@ def _load_image(self, path: str | Path) -> np.ndarray: if suffix == ".dcm": if not PYDICOM_AVAILABLE: - raise ImportError("pydicom is required for DICOM files. Install with: pip install pydicom") + raise ImportError( + "pydicom is required for DICOM files. Install with: pip install pydicom" + ) return self._load_dicom(path) elif suffix == ".npy": diff --git a/src/engine/trainer.py b/src/engine/trainer.py index 7dd99ac..ed78610 100644 --- a/src/engine/trainer.py +++ b/src/engine/trainer.py @@ -94,7 +94,9 @@ def __init__( self.checkpoint_dir.mkdir(parents=True, exist_ok=True) # Setup AMP - self.scaler = GradScaler('cuda' if device.type == 'cuda' else 'cpu', enabled=use_amp) + self.scaler = GradScaler( + "cuda" if device.type == "cuda" else "cpu", enabled=use_amp + ) # Setup logging self.writer = SummaryWriter(log_dir=str(self.log_dir)) @@ -102,7 +104,7 @@ def __init__( # Early stopping self.early_stopping_patience = early_stopping_patience - self.best_val_loss = float('inf') + self.best_val_loss = float("inf") self.best_val_auc = 0.0 self.patience_counter = 0 @@ -133,17 +135,17 @@ def _compute_medical_metrics( try: if len(np.unique(y_true)) == 2: # Binary classification - metrics['auc_roc'] = roc_auc_score(y_true, y_prob[:, 1]) + metrics["auc_roc"] = roc_auc_score(y_true, y_prob[:, 1]) else: # Multiclass - metrics['auc_roc'] = roc_auc_score( - y_true, y_prob, multi_class='ovr', average='macro' + metrics["auc_roc"] = roc_auc_score( + y_true, y_prob, multi_class="ovr", average="macro" ) except Exception: - metrics['auc_roc'] = 0.0 + metrics["auc_roc"] = 0.0 # F1 Score - metrics['f1_score'] = f1_score(y_true, y_pred, average='macro', zero_division=0) + metrics["f1_score"] = f1_score(y_true, y_pred, average="macro", zero_division=0) # Confusion matrix for sensitivity and specificity cm = confusion_matrix(y_true, y_pred) @@ -151,10 +153,10 @@ def _compute_medical_metrics( if cm.shape[0] == 2: # Binary classification tn, fp, fn, tp = cm.ravel() - metrics['sensitivity'] = tp / (tp + fn) if (tp + fn) > 0 else 0.0 - metrics['specificity'] = tn / (tn + fp) if (tn + fp) > 0 else 0.0 - metrics['precision'] = tp / (tp + fp) if (tp + fp) > 0 else 0.0 - metrics['npv'] = tn / (tn + fn) if (tn + fn) > 0 else 0.0 + metrics["sensitivity"] = tp / (tp + fn) if (tp + fn) > 0 else 0.0 + metrics["specificity"] = tn / (tn + fp) if (tn + fp) > 0 else 0.0 + metrics["precision"] = tp / (tp + fp) if (tp + fp) > 0 else 0.0 + metrics["npv"] = tn / (tn + fn) if (tn + fn) > 0 else 0.0 else: # Multiclass - compute macro-averaged metrics sensitivities = [] @@ -171,11 +173,11 @@ def _compute_medical_metrics( sensitivities.append(sens) specificities.append(spec) - metrics['sensitivity'] = np.mean(sensitivities) - metrics['specificity'] = np.mean(specificities) + metrics["sensitivity"] = np.mean(sensitivities) + metrics["specificity"] = np.mean(specificities) # Accuracy - metrics['accuracy'] = (y_true == y_pred).mean() + metrics["accuracy"] = (y_true == y_pred).mean() return metrics @@ -190,7 +192,10 @@ def _train_epoch(self) -> dict[str, float]: total_loss = 0.0 num_batches = 0 - pbar = tqdm(self.train_loader, desc=f"Epoch {self.current_epoch + 1}/{self.num_epochs} [Train]") + pbar = tqdm( + self.train_loader, + desc=f"Epoch {self.current_epoch + 1}/{self.num_epochs} [Train]", + ) for images, features, labels in pbar: images = images.to(self.device) @@ -223,14 +228,16 @@ def _train_epoch(self) -> dict[str, float]: self.global_step += 1 # Update progress bar - pbar.set_postfix({'loss': f'{loss.item():.4f}'}) + pbar.set_postfix({"loss": f"{loss.item():.4f}"}) # Log to TensorBoard if self.global_step % 10 == 0: - self.writer.add_scalar('train/batch_loss', loss.item(), self.global_step) + self.writer.add_scalar( + "train/batch_loss", loss.item(), self.global_step + ) avg_loss = total_loss / num_batches - return {'loss': avg_loss} + return {"loss": avg_loss} def _validate_epoch(self) -> dict[str, float]: """ @@ -247,7 +254,10 @@ def _validate_epoch(self) -> dict[str, float]: all_preds = [] all_probs = [] - pbar = tqdm(self.val_loader, desc=f"Epoch {self.current_epoch + 1}/{self.num_epochs} [Val]") + pbar = tqdm( + self.val_loader, + desc=f"Epoch {self.current_epoch + 1}/{self.num_epochs} [Val]", + ) with torch.no_grad(): for images, features, labels in pbar: @@ -279,7 +289,7 @@ def _validate_epoch(self) -> dict[str, float]: y_prob = np.array(all_probs) metrics = self._compute_medical_metrics(y_true, y_pred, y_prob) - metrics['loss'] = avg_loss + metrics["loss"] = avg_loss return metrics @@ -292,22 +302,24 @@ def _save_checkpoint(self, filename: str, metrics: dict[str, float]) -> None: metrics: Current metrics """ checkpoint = { - 'epoch': self.current_epoch, - 'model_state_dict': self.model.state_dict(), - 'optimizer_state_dict': self.optimizer.state_dict(), - 'scaler_state_dict': self.scaler.state_dict(), - 'metrics': metrics, - 'best_val_loss': self.best_val_loss, - 'best_val_auc': self.best_val_auc, + "epoch": self.current_epoch, + "model_state_dict": self.model.state_dict(), + "optimizer_state_dict": self.optimizer.state_dict(), + "scaler_state_dict": self.scaler.state_dict(), + "metrics": metrics, + "best_val_loss": self.best_val_loss, + "best_val_auc": self.best_val_auc, } if self.scheduler is not None: - checkpoint['scheduler_state_dict'] = self.scheduler.state_dict() + checkpoint["scheduler_state_dict"] = self.scheduler.state_dict() path = self.checkpoint_dir / filename torch.save(checkpoint, path) - def _log_metrics(self, train_metrics: dict[str, float], val_metrics: dict[str, float]) -> None: + def _log_metrics( + self, train_metrics: dict[str, float], val_metrics: dict[str, float] + ) -> None: """ Log metrics to TensorBoard and JSON. @@ -317,30 +329,30 @@ def _log_metrics(self, train_metrics: dict[str, float], val_metrics: dict[str, f """ # TensorBoard for key, value in train_metrics.items(): - self.writer.add_scalar(f'train/{key}', value, self.current_epoch) + self.writer.add_scalar(f"train/{key}", value, self.current_epoch) for key, value in val_metrics.items(): - self.writer.add_scalar(f'val/{key}', value, self.current_epoch) + self.writer.add_scalar(f"val/{key}", value, self.current_epoch) # Learning rate if self.scheduler is not None: lr = self.scheduler.get_last_lr()[0] else: - lr = self.optimizer.param_groups[0]['lr'] - self.writer.add_scalar('learning_rate', lr, self.current_epoch) + lr = self.optimizer.param_groups[0]["lr"] + self.writer.add_scalar("learning_rate", lr, self.current_epoch) # JSON history epoch_metrics = { - 'epoch': self.current_epoch, - 'train': train_metrics, - 'val': val_metrics, - 'lr': lr, + "epoch": self.current_epoch, + "train": train_metrics, + "val": val_metrics, + "lr": lr, } self.metrics_history.append(epoch_metrics) # Save JSON - json_path = self.log_dir / 'metrics_history.json' - with open(json_path, 'w') as f: + json_path = self.log_dir / "metrics_history.json" + with open(json_path, "w") as f: json.dump(self.metrics_history, f, indent=2) def train(self) -> dict[str, float]: @@ -377,23 +389,25 @@ def train(self) -> dict[str, float]: # Learning rate scheduling if self.scheduler is not None: - if isinstance(self.scheduler, torch.optim.lr_scheduler.ReduceLROnPlateau): - self.scheduler.step(val_metrics['loss']) + if isinstance( + self.scheduler, torch.optim.lr_scheduler.ReduceLROnPlateau + ): + self.scheduler.step(val_metrics["loss"]) else: self.scheduler.step() # Save best model - if val_metrics['auc_roc'] > self.best_val_auc: - self.best_val_auc = val_metrics['auc_roc'] - self.best_val_loss = val_metrics['loss'] - self._save_checkpoint('best_model.pth', val_metrics) + if val_metrics["auc_roc"] > self.best_val_auc: + self.best_val_auc = val_metrics["auc_roc"] + self.best_val_loss = val_metrics["loss"] + self._save_checkpoint("best_model.pth", val_metrics) print(f" ✓ New best model saved (AUC: {self.best_val_auc:.4f})") self.patience_counter = 0 else: self.patience_counter += 1 # Save last model - self._save_checkpoint('last_model.pth', val_metrics) + self._save_checkpoint("last_model.pth", val_metrics) # Early stopping if self.patience_counter >= self.early_stopping_patience: @@ -408,8 +422,8 @@ def train(self) -> dict[str, float]: print(f"Best validation loss: {self.best_val_loss:.4f}") return { - 'best_val_auc': self.best_val_auc, - 'best_val_loss': self.best_val_loss, + "best_val_auc": self.best_val_auc, + "best_val_loss": self.best_val_loss, } def load_checkpoint(self, checkpoint_path: str | Path) -> None: @@ -421,15 +435,15 @@ def load_checkpoint(self, checkpoint_path: str | Path) -> None: """ checkpoint = torch.load(checkpoint_path, map_location=self.device) - self.model.load_state_dict(checkpoint['model_state_dict']) - self.optimizer.load_state_dict(checkpoint['optimizer_state_dict']) - self.scaler.load_state_dict(checkpoint['scaler_state_dict']) + self.model.load_state_dict(checkpoint["model_state_dict"]) + self.optimizer.load_state_dict(checkpoint["optimizer_state_dict"]) + self.scaler.load_state_dict(checkpoint["scaler_state_dict"]) - if self.scheduler is not None and 'scheduler_state_dict' in checkpoint: - self.scheduler.load_state_dict(checkpoint['scheduler_state_dict']) + if self.scheduler is not None and "scheduler_state_dict" in checkpoint: + self.scheduler.load_state_dict(checkpoint["scheduler_state_dict"]) - self.current_epoch = checkpoint['epoch'] - self.best_val_loss = checkpoint.get('best_val_loss', float('inf')) - self.best_val_auc = checkpoint.get('best_val_auc', 0.0) + self.current_epoch = checkpoint["epoch"] + self.best_val_loss = checkpoint.get("best_val_loss", float("inf")) + self.best_val_auc = checkpoint.get("best_val_auc", 0.0) print(f"Loaded checkpoint from epoch {self.current_epoch}") diff --git a/src/utils/clean_table.py b/src/utils/clean_table.py index f65be2a..69d0274 100644 --- a/src/utils/clean_table.py +++ b/src/utils/clean_table.py @@ -42,7 +42,9 @@ def __init__( self, dictionary_path: str | Path | None = None, outlier_method: Literal["iqr", "zscore", "range"] = "range", - missing_strategy: Literal["drop", "mean", "median", "mode", "forward_fill"] = "median", + missing_strategy: Literal[ + "drop", "mean", "median", "mode", "forward_fill" + ] = "median", encoding_strategy: Literal["onehot", "label", "ordinal"] = "label", verbose: bool = True, ): @@ -82,7 +84,7 @@ def _load_dictionary(self) -> dict: print(f"Warning: Dictionary not found at {self.dictionary_path}") return {} - with open(self.dictionary_path, encoding='utf-8') as f: + with open(self.dictionary_path, encoding="utf-8") as f: return yaml.safe_load(f) def _get_valid_range(self, column: str) -> tuple[float, float] | None: @@ -96,8 +98,10 @@ def _get_valid_range(self, column: str) -> tuple[float, float] | None: for field_name, field_info in category_data.items(): if isinstance(field_info, dict): # Check if this field matches the column - if field_name == column or column in field_info.get('aliases', []): - return field_info.get('valid_range') + if field_name == column or column in field_info.get( + "aliases", [] + ): + return field_info.get("valid_range") return None @@ -267,19 +271,39 @@ def encode_categorical( # Common medical categorical mappings gender_map = { - "male": 0, "男": 0, "M": 0, "m": 0, - "female": 1, "女": 1, "F": 1, "f": 1, + "male": 0, + "男": 0, + "M": 0, + "m": 0, + "female": 1, + "女": 1, + "F": 1, + "f": 1, } smoking_map = { - "never": 0, "从不": 0, "no": 0, "否": 0, - "former": 1, "曾经": 1, "quit": 1, - "current": 2, "目前": 2, "yes": 2, "是": 2, + "never": 0, + "从不": 0, + "no": 0, + "否": 0, + "former": 1, + "曾经": 1, + "quit": 1, + "current": 2, + "目前": 2, + "yes": 2, + "是": 2, } binary_map = { - "no": 0, "否": 0, "false": 0, "0": 0, - "yes": 1, "是": 1, "true": 1, "1": 1, + "no": 0, + "否": 0, + "false": 0, + "0": 0, + "yes": 1, + "是": 1, + "true": 1, + "1": 1, } col_lower = column.lower() @@ -352,7 +376,7 @@ def handle_missing( self.cleaning_stats["missing_filled"] += missing_count elif self.missing_strategy == "forward_fill": - df_filled[column].fillna(method='ffill', inplace=True) + df_filled[column].fillna(method="ffill", inplace=True) self.cleaning_stats["missing_filled"] += missing_count return df_filled @@ -403,7 +427,10 @@ def clean( print("\nStep 3: Encoding categorical variables...") for col in df_clean.columns: - if df_clean[col].dtype == 'object' or df_clean[col].dtype.name == 'category': + if ( + df_clean[col].dtype == "object" + or df_clean[col].dtype.name == "category" + ): df_clean = self.encode_categorical(df_clean, col) # Step 4: Handle missing values @@ -415,16 +442,18 @@ def clean( # Summary if self.verbose: - print("\n" + "="*60) + print("\n" + "=" * 60) print("Cleaning Summary:") print(f" Outliers detected: {self.cleaning_stats['outliers_detected']}") print(f" Outliers fixed: {self.cleaning_stats['outliers_fixed']}") print(f" Logical errors: {self.cleaning_stats['logical_errors']}") print(f" Missing values: {self.cleaning_stats['missing_values']}") print(f" Missing filled: {self.cleaning_stats['missing_filled']}") - print(f" Categorical encoded: {self.cleaning_stats['categorical_encoded']}") + print( + f" Categorical encoded: {self.cleaning_stats['categorical_encoded']}" + ) print(f" Output shape: {df_clean.shape}") - print("="*60) + print("=" * 60) return df_clean @@ -437,13 +466,13 @@ def get_cleaning_report(self) -> dict: if __name__ == "__main__": # Create sample clinical data with issues sample_data = { - 'patient_id': ['P001', 'P002', 'P003', 'P004', 'P005'], - 'age': [45, 200, 38, -5, 61], # Outliers: 200, -5 - 'gender': ['男', 'F', '女', 'M', '男'], - 'systolic_bp': [120, 0, 145, 160, 135], # Outlier: 0 - 'diastolic_bp': [80, 70, 95, 100, 85], - 'glucose': [5.2, np.nan, 7.8, 9.1, 5.0], # Missing value - 'smoking': ['从不', 'yes', 'no', '目前', 'former'], + "patient_id": ["P001", "P002", "P003", "P004", "P005"], + "age": [45, 200, 38, -5, 61], # Outliers: 200, -5 + "gender": ["男", "F", "女", "M", "男"], + "systolic_bp": [120, 0, 145, 160, 135], # Outlier: 0 + "diastolic_bp": [80, 70, 95, 100, 85], + "glucose": [5.2, np.nan, 7.8, 9.1, 5.0], # Missing value + "smoking": ["从不", "yes", "no", "目前", "former"], } df = pd.DataFrame(sample_data) @@ -458,7 +487,7 @@ def get_cleaning_report(self) -> dict: outlier_method="range", missing_strategy="median", encoding_strategy="label", - verbose=True + verbose=True, ) # Clean data diff --git a/uv.lock b/uv.lock index 782e74e..20a682d 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,6 @@ version = 1 revision = 3 -requires-python = ">=3.11" +requires-python = ">=3.11, <3.14" resolution-markers = [ "python_full_version >= '3.12' and sys_platform == 'linux'", "python_full_version >= '3.12' and sys_platform != 'linux'", @@ -104,40 +104,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/e8/35/4a3daeb8b9fab49240d21c04d50732313295e4bd813a465d840236dd0ce1/aiohttp-3.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8057c98e0c8472d8846b9c79f56766bcc57e3e8ac7bfd510482332366c56c591" }, { url = "https://mirrors.aliyun.com/pypi/packages/bc/9f/d643bb3c5fb99547323e635e251c609fbbc660d983144cfebec529e09264/aiohttp-3.13.3-cp313-cp313-win32.whl", hash = "sha256:1449ceddcdbcf2e0446957863af03ebaaa03f94c090f945411b61269e2cb5daf" }, { url = "https://mirrors.aliyun.com/pypi/packages/4e/f1/ab0395f8a79933577cdd996dd2f9aa6014af9535f65dddcf88204682fe62/aiohttp-3.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:693781c45a4033d31d4187d2436f5ac701e7bbfe5df40d917736108c1cc7436e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/99/36/5b6514a9f5d66f4e2597e40dea2e3db271e023eb7a5d22defe96ba560996/aiohttp-3.13.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f7/49/459327f0d5bcd8c6c9ca69e60fdeebc3622861e696490d8674a6d0cb90a6/aiohttp-3.13.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e8/0b/b97660c5fd05d3495b4eb27f2d0ef18dc1dc4eff7511a9bf371397ff0264/aiohttp-3.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/54/d4/438efabdf74e30aeceb890c3290bbaa449780583b1270b00661126b8aae4/aiohttp-3.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/71/f2/7bddc7fd612367d1459c5bcf598a9e8f7092d6580d98de0e057eb42697ad/aiohttp-3.13.3-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687" }, - { url = "https://mirrors.aliyun.com/pypi/packages/00/5a/1aeaecca40e22560f97610a329e0e5efef5e0b5afdf9f857f0d93839ab2e/aiohttp-3.13.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f8/f8/0ff6992bea7bd560fc510ea1c815f87eedd745fe035589c71ce05612a19a/aiohttp-3.13.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/d1/e30e537a15f53485b61f5be525f2157da719819e8377298502aebac45536/aiohttp-3.13.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/84/45/23f4c451d8192f553d38d838831ebbc156907ea6e05557f39563101b7717/aiohttp-3.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6a/ed/0a42b127a43712eda7807e7892c083eadfaf8429ca8fb619662a530a3aab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2e/b5/c05f0c2b4b4fe2c9d55e73b6d3ed4fd6c9dc2684b1d81cbdf77e7fad9adb/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c9/6b/915bc5dad66aef602b9e459b5a973529304d4e89ca86999d9d75d80cbd0b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926" }, - { url = "https://mirrors.aliyun.com/pypi/packages/11/3b/e84581290a9520024a08640b63d07673057aec5ca548177a82026187ba73/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/04/0c3655a566c43fd647c81b895dfe361b9f9ad6d58c19309d45cff52d6c3b/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/53/71165b26978f719c3419381514c9690bd5980e764a09440a10bb816ea4ab/aiohttp-3.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43" }, - { url = "https://mirrors.aliyun.com/pypi/packages/29/a7/cbe6c9e8e136314fa1980da388a59d2f35f35395948a08b6747baebb6aa6/aiohttp-3.13.3-cp314-cp314-win32.whl", hash = "sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/de/56/982704adea7d3b16614fc5936014e9af85c0e34b58f9046655817f04306e/aiohttp-3.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6c/2a/3c79b638a9c3d4658d345339d22070241ea341ed4e07b5ac60fb0f418003/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/29/b9/3e5014d46c0ab0db8707e0ac2711ed28c4da0218c358a4e7c17bae0d8722/aiohttp-3.13.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592" }, - { url = "https://mirrors.aliyun.com/pypi/packages/90/03/c1d4ef9a054e151cd7839cdc497f2638f00b93cbe8043983986630d7a80c/aiohttp-3.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ea/76/8c1e5abbfe8e127c893fe7ead569148a4d5a799f7cf958d8c09f3eedf097/aiohttp-3.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8e/ac/984c5a6f74c363b01ff97adc96a3976d9c98940b8969a1881575b279ac5d/aiohttp-3.13.3-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/9a/b7039c5f099c4eb632138728828b33428585031a1e658d693d41d07d89d1/aiohttp-3.13.3-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/02/3bec2b9a1ba3c19ff89a43a19324202b8eb187ca1e928d8bdac9bbdddebd/aiohttp-3.13.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587" }, - { url = "https://mirrors.aliyun.com/pypi/packages/37/df/d879401cedeef27ac4717f6426c8c36c3091c6e9f08a9178cc87549c537f/aiohttp-3.13.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8d/15/be122de1f67e6953add23335c8ece6d314ab67c8bebb3f181063010795a7/aiohttp-3.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632" }, - { url = "https://mirrors.aliyun.com/pypi/packages/12/12/70eedcac9134cfa3219ab7af31ea56bc877395b1ac30d65b1bc4b27d0438/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64" }, - { url = "https://mirrors.aliyun.com/pypi/packages/32/11/b30e1b1cd1f3054af86ebe60df96989c6a414dd87e27ad16950eee420bea/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/88/0d/d98a9367b38912384a17e287850f5695c528cff0f14f791ce8ee2e4f7796/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/a5/a2dfd1f5ff5581632c7f6a30e1744deda03808974f94f6534241ef60c751/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fa/f0/12973c382ae7c1cccbc4417e129c5bf54c374dfb85af70893646e1f0e749/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/5f/24155e30ba7f8c96918af1350eb0663e2430aad9e001c0489d89cd708ab1/aiohttp-3.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa" }, - { url = "https://mirrors.aliyun.com/pypi/packages/eb/f8/7314031ff5c10e6ece114da79b338ec17eeff3a079e53151f7e9f43c4723/aiohttp-3.13.3-cp314-cp314t-win32.whl", hash = "sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/63/278a98c715ae467624eafe375542d8ba9b4383a016df8fdefe0ae28382a7/aiohttp-3.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344" }, ] [[package]] @@ -287,22 +253,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac" }, { url = "https://mirrors.aliyun.com/pypi/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14" }, { url = "https://mirrors.aliyun.com/pypi/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd" }, - { url = "https://mirrors.aliyun.com/pypi/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" }, - { url = "https://mirrors.aliyun.com/pypi/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" }, - { url = "https://mirrors.aliyun.com/pypi/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" }, - { url = "https://mirrors.aliyun.com/pypi/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" }, - { url = "https://mirrors.aliyun.com/pypi/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" }, - { url = "https://mirrors.aliyun.com/pypi/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828" }, - { url = "https://mirrors.aliyun.com/pypi/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2" }, { url = "https://mirrors.aliyun.com/pypi/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f" }, ] @@ -380,28 +330,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/b9/70/f308384a3ae9cd2209e0849f33c913f658d3326900d0ff5d378d6a1422d2/contourpy-1.3.3-cp313-cp313t-win32.whl", hash = "sha256:283edd842a01e3dcd435b1c5116798d661378d83d36d337b8dde1d16a5fc9ba3" }, { url = "https://mirrors.aliyun.com/pypi/packages/b2/dd/880f890a6663b84d9e34a6f88cded89d78f0091e0045a284427cb6b18521/contourpy-1.3.3-cp313-cp313t-win_amd64.whl", hash = "sha256:87acf5963fc2b34825e5b6b048f40e3635dd547f590b04d2ab317c2619ef7ae8" }, { url = "https://mirrors.aliyun.com/pypi/packages/80/99/2adc7d8ffead633234817ef8e9a87115c8a11927a94478f6bb3d3f4d4f7d/contourpy-1.3.3-cp313-cp313t-win_arm64.whl", hash = "sha256:3c30273eb2a55024ff31ba7d052dde990d7d8e5450f4bbb6e913558b3d6c2301" }, - { url = "https://mirrors.aliyun.com/pypi/packages/72/8b/4546f3ab60f78c514ffb7d01a0bd743f90de36f0019d1be84d0a708a580a/contourpy-1.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fde6c716d51c04b1c25d0b90364d0be954624a0ee9d60e23e850e8d48353d07a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fd/e1/3542a9cb596cadd76fcef413f19c79216e002623158befe6daa03dbfa88c/contourpy-1.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:cbedb772ed74ff5be440fa8eee9bd49f64f6e3fc09436d9c7d8f1c287b121d77" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b1/71/f93e1e9471d189f79d0ce2497007731c1e6bf9ef6d1d61b911430c3db4e5/contourpy-1.3.3-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22e9b1bd7a9b1d652cd77388465dc358dafcd2e217d35552424aa4f996f524f5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/91/f9/e35f4c1c93f9275d4e38681a80506b5510e9327350c51f8d4a5a724d178c/contourpy-1.3.3-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a22738912262aa3e254e4f3cb079a95a67132fc5a063890e224393596902f5a4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b5/71/47b512f936f66a0a900d81c396a7e60d73419868fba959c61efed7a8ab46/contourpy-1.3.3-cp314-cp314-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:afe5a512f31ee6bd7d0dda52ec9864c984ca3d66664444f2d72e0dc4eb832e36" }, - { url = "https://mirrors.aliyun.com/pypi/packages/04/5f/9ff93450ba96b09c7c2b3f81c94de31c89f92292f1380261bd7195bea4ea/contourpy-1.3.3-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f64836de09927cba6f79dcd00fdd7d5329f3fccc633468507079c829ca4db4e3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3e/a6/0b185d4cc480ee494945cde102cb0149ae830b5fa17bf855b95f2e70ad13/contourpy-1.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1fd43c3be4c8e5fd6e4f2baeae35ae18176cf2e5cced681cca908addf1cdd53b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/d7/afdc95580ca56f30fbcd3060250f66cedbde69b4547028863abd8aa3b47e/contourpy-1.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6afc576f7b33cf00996e5c1102dc2a8f7cc89e39c0b55df93a0b78c1bd992b36" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/e2/366af18a6d386f41132a48f033cbd2102e9b0cf6345d35ff0826cd984566/contourpy-1.3.3-cp314-cp314-win32.whl", hash = "sha256:66c8a43a4f7b8df8b71ee1840e4211a3c8d93b214b213f590e18a1beca458f7d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7d/c2/57f54b03d0f22d4044b8afb9ca0e184f8b1afd57b4f735c2fa70883dc601/contourpy-1.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:cf9022ef053f2694e31d630feaacb21ea24224be1c3ad0520b13d844274614fd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/18/79/a9416650df9b525737ab521aa181ccc42d56016d2123ddcb7b58e926a42c/contourpy-1.3.3-cp314-cp314-win_arm64.whl", hash = "sha256:95b181891b4c71de4bb404c6621e7e2390745f887f2a026b2d99e92c17892339" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/42/38c159a7d0f2b7b9c04c64ab317042bb6952b713ba875c1681529a2932fe/contourpy-1.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:33c82d0138c0a062380332c861387650c82e4cf1747aaa6938b9b6516762e772" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c3/6c/26a8205f24bca10974e77460de68d3d7c63e282e23782f1239f226fcae6f/contourpy-1.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ea37e7b45949df430fe649e5de8351c423430046a2af20b1c1961cae3afcda77" }, - { url = "https://mirrors.aliyun.com/pypi/packages/66/06/8a475c8ab718ebfd7925661747dbb3c3ee9c82ac834ccb3570be49d129f4/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d304906ecc71672e9c89e87c4675dc5c2645e1f4269a5063b99b0bb29f232d13" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/a3/c5ca9f010a44c223f098fccd8b158bb1cb287378a31ac141f04730dc49be/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ca658cd1a680a5c9ea96dc61cdbae1e85c8f25849843aa799dfd3cb370ad4fbe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/5b/68bd33ae63fac658a4145088c1e894405e07584a316738710b636c6d0333/contourpy-1.3.3-cp314-cp314t-manylinux_2_26_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ab2fd90904c503739a75b7c8c5c01160130ba67944a7b77bbf36ef8054576e7f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/40/52/4c285a6435940ae25d7410a6c36bda5145839bc3f0beb20c707cda18b9d2/contourpy-1.3.3-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b7301b89040075c30e5768810bc96a8e8d78085b47d8be6e4c3f5a0b4ed478a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/24/ee/3e81e1dd174f5c7fefe50e85d0892de05ca4e26ef1c9a59c2a57e43b865a/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2a2a8b627d5cc6b7c41a4beff6c5ad5eb848c88255fda4a8745f7e901b32d8e4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/b2/6d913d4d04e14379de429057cd169e5e00f6c2af3bb13e1710bcbdb5da12/contourpy-1.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:fd6ec6be509c787f1caf6b247f0b1ca598bef13f4ddeaa126b7658215529ba0f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/93/8a/68a4ec5c55a2971213d29a9374913f7e9f18581945a7a31d1a39b5d2dfe5/contourpy-1.3.3-cp314-cp314t-win32.whl", hash = "sha256:e74a9a0f5e3fff48fb5a7f2fd2b9b70a3fe014a67522f79b7cca4c0c7e43c9ae" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fa/96/fd9f641ffedc4fa3ace923af73b9d07e869496c9cc7a459103e6e978992f/contourpy-1.3.3-cp314-cp314t-win_amd64.whl", hash = "sha256:13b68d6a62db8eafaebb8039218921399baf6e47bf85006fd8529f2a08ef33fc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ae/8c/469afb6465b853afff216f9528ffda78a915ff880ed58813ba4faf4ba0b6/contourpy-1.3.3-cp314-cp314t-win_arm64.whl", hash = "sha256:b7448cb5a725bb1e35ce88771b86fba35ef418952474492cf7c764059933ff8b" }, { url = "https://mirrors.aliyun.com/pypi/packages/a5/29/8dcfe16f0107943fa92388c23f6e05cff0ba58058c4c95b00280d4c75a14/contourpy-1.3.3-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:cd5dfcaeb10f7b7f9dc8941717c6c2ade08f587be2226222c12b25f0483ed497" }, { url = "https://mirrors.aliyun.com/pypi/packages/85/a9/8b37ef4f7dafeb335daee3c8254645ef5725be4d9c6aa70b50ec46ef2f7e/contourpy-1.3.3-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:0c1fc238306b35f246d61a1d416a627348b5cf0648648a031e14bb8705fcdfe8" }, { url = "https://mirrors.aliyun.com/pypi/packages/0a/59/ebfb8c677c75605cc27f7122c90313fd2f375ff3c8d19a1694bda74aaa63/contourpy-1.3.3-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:70f9aad7de812d6541d29d2bbf8feb22ff7e1c299523db288004e3157ff4674e" }, @@ -467,32 +395,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/1c/7a/6f354dcd7dfc41297791d6fb4e0d618acb55810bde2c1fd14b3939e05c2b/coverage-7.13.2-cp313-cp313t-win32.whl", hash = "sha256:14ae4146465f8e6e6253eba0cccd57423e598a4cb925958b240c805300918343" }, { url = "https://mirrors.aliyun.com/pypi/packages/8d/d5/080ad292a4a3d3daf411574be0a1f56d6dee2c4fdf6b005342be9fac807f/coverage-7.13.2-cp313-cp313t-win_amd64.whl", hash = "sha256:9074896edd705a05769e3de0eac0a8388484b503b68863dd06d5e473f874fd47" }, { url = "https://mirrors.aliyun.com/pypi/packages/88/96/df576fbacc522e9fb8d1c4b7a7fc62eb734be56e2cba1d88d2eabe08ea3f/coverage-7.13.2-cp313-cp313t-win_arm64.whl", hash = "sha256:69e526e14f3f854eda573d3cf40cffd29a1a91c684743d904c33dbdcd0e0f3e7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/55/53/1da9e51a0775634b04fcc11eb25c002fc58ee4f92ce2e8512f94ac5fc5bf/coverage-7.13.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:387a825f43d680e7310e6f325b2167dd093bc8ffd933b83e9aa0983cf6e0a2ef" }, - { url = "https://mirrors.aliyun.com/pypi/packages/46/35/b3caac3ebbd10230fea5a33012b27d19e999a17c9285c4228b4b2e35b7da/coverage-7.13.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:f0d7fea9d8e5d778cd5a9e8fc38308ad688f02040e883cdc13311ef2748cb40f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/76/9c/e1cf7def1bdc72c1907e60703983a588f9558434a2ff94615747bd73c192/coverage-7.13.2-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e080afb413be106c95c4ee96b4fffdc9e2fa56a8bbf90b5c0918e5c4449412f5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ba/49/f54ec02ed12be66c8d8897270505759e057b0c68564a65c429ccdd1f139e/coverage-7.13.2-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a7fc042ba3c7ce25b8a9f097eb0f32a5ce1ccdb639d9eec114e26def98e1f8a4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fb/5e/aaf86be3e181d907e23c0f61fccaeb38de8e6f6b47aed92bf57d8fc9c034/coverage-7.13.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0ba505e021557f7f8173ee8cd6b926373d8653e5ff7581ae2efce1b11ef4c27" }, - { url = "https://mirrors.aliyun.com/pypi/packages/28/c8/a5fa01460e2d75b0c853b392080d6829d3ca8b5ab31e158fa0501bc7c708/coverage-7.13.2-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7de326f80e3451bd5cc7239ab46c73ddb658fe0b7649476bc7413572d36cd548" }, - { url = "https://mirrors.aliyun.com/pypi/packages/86/0b/6d56315a55f7062bb66410732c24879ccb2ec527ab6630246de5fe45a1df/coverage-7.13.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:abaea04f1e7e34841d4a7b343904a3f59481f62f9df39e2cd399d69a187a9660" }, - { url = "https://mirrors.aliyun.com/pypi/packages/30/19/9bc550363ebc6b0ea121977ee44d05ecd1e8bf79018b8444f1028701c563/coverage-7.13.2-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:9f93959ee0c604bccd8e0697be21de0887b1f73efcc3aa73a3ec0fd13feace92" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/53/580530a31ca2f0cc6f07a8f2ab5460785b02bb11bdf815d4c4d37a4c5169/coverage-7.13.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:13fe81ead04e34e105bf1b3c9f9cdf32ce31736ee5d90a8d2de02b9d3e1bcb82" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/42/dd9093f919dc3088cb472893651884bd675e3df3d38a43f9053656dca9a2/coverage-7.13.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d6d16b0f71120e365741bca2cb473ca6fe38930bc5431c5e850ba949f708f892" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fa/a6/0af4053e6e819774626e133c3d6f70fae4d44884bfc4b126cb647baee8d3/coverage-7.13.2-cp314-cp314-win32.whl", hash = "sha256:9b2f4714bb7d99ba3790ee095b3b4ac94767e1347fe424278a0b10acb3ff04fe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c4/cc/5aff1e1f80d55862442855517bb8ad8ad3a68639441ff6287dde6a58558b/coverage-7.13.2-cp314-cp314-win_amd64.whl", hash = "sha256:e4121a90823a063d717a96e0a0529c727fb31ea889369a0ee3ec00ed99bf6859" }, - { url = "https://mirrors.aliyun.com/pypi/packages/de/20/09abafb24f84b3292cc658728803416c15b79f9ee5e68d25238a895b07d9/coverage-7.13.2-cp314-cp314-win_arm64.whl", hash = "sha256:6873f0271b4a15a33e7590f338d823f6f66f91ed147a03938d7ce26efd04eee6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b6/60/a3820c7232db63be060e4019017cd3426751c2699dab3c62819cdbcea387/coverage-7.13.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f61d349f5b7cd95c34017f1927ee379bfbe9884300d74e07cf630ccf7a610c1b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fd/37/e4ef5975fdeb86b1e56db9a82f41b032e3d93a840ebaf4064f39e770d5c5/coverage-7.13.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:a43d34ce714f4ca674c0d90beb760eb05aad906f2c47580ccee9da8fe8bfb417" }, - { url = "https://mirrors.aliyun.com/pypi/packages/54/df/d40e091d00c51adca1e251d3b60a8b464112efa3004949e96a74d7c19a64/coverage-7.13.2-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bff1b04cb9d4900ce5c56c4942f047dc7efe57e2608cb7c3c8936e9970ccdbee" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c5/44/5259c4bed54e3392e5c176121af9f71919d96dde853386e7730e705f3520/coverage-7.13.2-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6ae99e4560963ad8e163e819e5d77d413d331fd00566c1e0856aa252303552c1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/16/bd/ae9f005827abcbe2c70157459ae86053971c9fa14617b63903abbdce26d9/coverage-7.13.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e79a8c7d461820257d9aa43716c4efc55366d7b292e46b5b37165be1d377405d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a2/c0/8e279c1c0f5b1eaa3ad9b0fb7a5637fc0379ea7d85a781c0fe0bb3cfc2ab/coverage-7.13.2-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:060ee84f6a769d40c492711911a76811b4befb6fba50abb450371abb720f5bd6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/47/3a8112627e9d863e7cddd72894171c929e94491a597811725befdcd76bce/coverage-7.13.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bca209d001fd03ea2d978f8a4985093240a355c93078aee3f799852c23f561a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/92/bc/7ea367d84afa3120afc3ce6de294fd2dcd33b51e2e7fbe4bbfd200f2cb8c/coverage-7.13.2-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:6b8092aa38d72f091db61ef83cb66076f18f02da3e1a75039a4f218629600e04" }, - { url = "https://mirrors.aliyun.com/pypi/packages/33/b7/f1092dcecb6637e31cc2db099581ee5c61a17647849bae6b8261a2b78430/coverage-7.13.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:4a3158dc2dcce5200d91ec28cd315c999eebff355437d2765840555d765a6e5f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2b/cd/f3d07d4b95fbe1a2ef0958c15da614f7e4f557720132de34d2dc3aa7e911/coverage-7.13.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3973f353b2d70bd9796cc12f532a05945232ccae966456c8ed7034cb96bbfd6f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/db/b0d5b2873a07cb1e06a55d998697c0a5a540dcefbf353774c99eb3874513/coverage-7.13.2-cp314-cp314t-win32.whl", hash = "sha256:79f6506a678a59d4ded048dc72f1859ebede8ec2b9a2d509ebe161f01c2879d3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e5/2f/838a5394c082ac57d85f57f6aba53093b30d9089781df72412126505716f/coverage-7.13.2-cp314-cp314t-win_amd64.whl", hash = "sha256:196bfeabdccc5a020a57d5a368c681e3a6ceb0447d153aeccc1ab4d70a5032ba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/44/d4/b608243e76ead3a4298824b50922b89ef793e50069ce30316a65c1b4d7ef/coverage-7.13.2-cp314-cp314t-win_arm64.whl", hash = "sha256:69269ab58783e090bfbf5b916ab3d188126e22d6070bbfc93098fdd474ef937c" }, { url = "https://mirrors.aliyun.com/pypi/packages/d2/db/d291e30fdf7ea617a335531e72294e0c723356d7fdde8fba00610a76bda9/coverage-7.13.2-py3-none-any.whl", hash = "sha256:40ce1ea1e25125556d8e76bd0b61500839a07944cc287ac21d5626f3e620cad5" }, ] @@ -506,15 +408,13 @@ name = "cuda-bindings" version = "12.9.4" source = { registry = "https://mirrors.aliyun.com/pypi/simple/" } dependencies = [ - { name = "cuda-pathfinder", marker = "sys_platform == 'linux'" }, + { name = "cuda-pathfinder" }, ] wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/45/e7/b47792cc2d01c7e1d37c32402182524774dadd2d26339bd224e0e913832e/cuda_bindings-12.9.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c912a3d9e6b6651853eed8eed96d6800d69c08e94052c292fec3f282c5a817c9" }, { url = "https://mirrors.aliyun.com/pypi/packages/a9/c1/dabe88f52c3e3760d861401bb994df08f672ec893b8f7592dc91626adcf3/cuda_bindings-12.9.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fda147a344e8eaeca0c6ff113d2851ffca8f7dfc0a6c932374ee5c47caa649c8" }, { url = "https://mirrors.aliyun.com/pypi/packages/63/56/e465c31dc9111be3441a9ba7df1941fe98f4aa6e71e8788a3fb4534ce24d/cuda_bindings-12.9.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:32bdc5a76906be4c61eb98f546a6786c5773a881f3b166486449b5d141e4a39f" }, { url = "https://mirrors.aliyun.com/pypi/packages/a3/84/1e6be415e37478070aeeee5884c2022713c1ecc735e6d82d744de0252eee/cuda_bindings-12.9.4-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56e0043c457a99ac473ddc926fe0dc4046694d99caef633e92601ab52cbe17eb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d1/af/6dfd8f2ed90b1d4719bc053ff8940e494640fe4212dc3dd72f383e4992da/cuda_bindings-12.9.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8b72ee72a9cc1b531db31eebaaee5c69a8ec3500e32c6933f2d3b15297b53686" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6c/19/90ac264acc00f6df8a49378eedec9fd2db3061bf9263bf9f39fd3d8377c3/cuda_bindings-12.9.4-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d80bffc357df9988dca279734bc9674c3934a654cab10cadeed27ce17d8635ee" }, ] [[package]] @@ -607,22 +507,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/a7/01/e6ae64a0981076e8a66906fab01539799546181e32a37a0257b77e4aa88b/fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d" }, { url = "https://mirrors.aliyun.com/pypi/packages/73/aa/28e40b8d6809a9b5075350a86779163f074d2b617c15d22343fce81918db/fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c" }, { url = "https://mirrors.aliyun.com/pypi/packages/1a/59/453c06d1d83dc0951b69ef692d6b9f1846680342927df54e9a1ca91c6f90/fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/32/8f/4e7bf82c0cbb738d3c2206c920ca34ca74ef9dabde779030145d28665104/fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/71/09/d44e45d0a4f3a651f23a1e9d42de43bc643cce2971b19e784cc67d823676/fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/18/58c64cafcf8eb677a99ef593121f719e6dcbdb7d1c594ae5a10d4997ca8a/fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8a/ec/9e6b38c7ba1e09eb51db849d5450f4c05b7e78481f662c3b79dbde6f3d04/fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5e/87/b5339da8e0256734ba0dbbf5b6cdebb1dd79b01dc8c270989b7bcd465541/fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0b/47/e3409f1e1e69c073a3a6fd8cb886eb18c0bae0ee13db2c8d5e7f8495e8b7/fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bf/b6/1f6600161b1073a984294c6c031e1a56ebf95b6164249eecf30012bb2e38/fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/52/7b/91e7b01e37cc8eb0e1f770d08305b3655e4f002fc160fb82b3390eabacf5/fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/39/5c/908ad78e46c61c3e3ed70c3b58ff82ab48437faf84ec84f109592cabbd9f/fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bd/41/975804132c6dea64cdbfbaa59f3518a21c137a10cccf962805b301ac6ab2/fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b0/5a/aef2a0a8daf1ebaae4cfd83f84186d4a72ee08fd6a8451289fcd03ffa8a4/fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/33/d6db3485b645b81cea538c9d1c9219d5805f0877fda18777add4671c5240/fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6c/d6/675ba631454043c75fcf76f0ca5463eac8eb0666ea1d7badae5fea001155/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7f/33/d3ec753d547a8d2bdaedd390d4a814e8d5b45a093d558f025c6b990b554c/fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/40/cc11f378b561a67bea850ab50063366a0d1dd3f6d0a30ce0f874b0ad5664/fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/ff/c9a2b66b39f8628531ea58b320d66d951267c98c6a38684daa8f50fb02f8/fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b" }, { url = "https://mirrors.aliyun.com/pypi/packages/c7/4e/ce75a57ff3aebf6fc1f4e9d508b8e5810618a33d900ad6c19eb30b290b97/fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371" }, ] @@ -696,38 +580,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/fd/00/04ca1c3a7a124b6de4f8a9a17cc2fcad138b4608e7a3fc5877804b8715d7/frozenlist-1.8.0-cp313-cp313t-win32.whl", hash = "sha256:0f96534f8bfebc1a394209427d0f8a63d343c9779cda6fc25e8e121b5fd8555b" }, { url = "https://mirrors.aliyun.com/pypi/packages/59/5e/c69f733a86a94ab10f68e496dc6b7e8bc078ebb415281d5698313e3af3a1/frozenlist-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5d63a068f978fc69421fb0e6eb91a9603187527c86b7cd3f534a5b77a592b888" }, { url = "https://mirrors.aliyun.com/pypi/packages/16/6c/be9d79775d8abe79b05fa6d23da99ad6e7763a1d080fbae7290b286093fd/frozenlist-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf0a7e10b077bf5fb9380ad3ae8ce20ef919a6ad93b4552896419ac7e1d8e042" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f1/c8/85da824b7e7b9b6e7f7705b2ecaf9591ba6f79c1177f324c2735e41d36a2/frozenlist-1.8.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8e/e8/a1185e236ec66c20afd72399522f142c3724c785789255202d27ae992818/frozenlist-1.8.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a1/93/72b1736d68f03fda5fdf0f2180fb6caaae3894f1b854d006ac61ecc727ee/frozenlist-1.8.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a7/b2/fabede9fafd976b991e9f1b9c8c873ed86f202889b864756f240ce6dd855/frozenlist-1.8.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3a/3b/d9b1e0b0eed36e70477ffb8360c49c85c8ca8ef9700a4e6711f39a6e8b45/frozenlist-1.8.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dc/94/be719d2766c1138148564a3960fc2c06eb688da592bdc25adcf856101be7/frozenlist-1.8.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/09/6712b6c5465f083f52f50cf74167b92d4ea2f50e46a9eea0523d658454ae/frozenlist-1.8.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f8/d4/cd065cdcf21550b54f3ce6a22e143ac9e4836ca42a0de1022da8498eac89/frozenlist-1.8.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/62/c3/f57a5c8c70cd1ead3d5d5f776f89d33110b1addae0ab010ad774d9a44fb9/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6c/52/232476fe9cb64f0742f3fde2b7d26c1dac18b6d62071c74d4ded55e0ef94/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5f/85/07bf3f5d0fb5414aee5f47d33c6f5c77bfe49aac680bfece33d4fdf6a246/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/11/99/ae3a33d5befd41ac0ca2cc7fd3aa707c9c324de2e89db0e0f45db9a64c26/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/60/b1d2da22f4970e7a155f0adde9b1435712ece01b3cd45ba63702aea33938/frozenlist-1.8.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3f/ab/945b2f32de889993b9c9133216c068b7fcf257d8595a0ac420ac8677cab0/frozenlist-1.8.0-cp314-cp314-win32.whl", hash = "sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806" }, - { url = "https://mirrors.aliyun.com/pypi/packages/59/ad/9caa9b9c836d9ad6f067157a531ac48b7d36499f5036d4141ce78c230b1b/frozenlist-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/82/13/e6950121764f2676f43534c555249f57030150260aee9dcf7d64efda11dd/frozenlist-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c0/c7/43200656ecc4e02d3f8bc248df68256cd9572b3f0017f0a0c4e93440ae23/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d1/29/55c5f0689b9c0fb765055629f472c0de484dcaf0acee2f7707266ae3583c/frozenlist-1.8.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ba/7d/b7282a445956506fa11da8c2db7d276adcbf2b17d8bb8407a47685263f90/frozenlist-1.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930" }, - { url = "https://mirrors.aliyun.com/pypi/packages/62/1c/3d8622e60d0b767a5510d1d3cf21065b9db874696a51ea6d7a43180a259c/frozenlist-1.8.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2d/14/aa36d5f85a89679a85a1d44cd7a6657e0b1c75f61e7cad987b203d2daca8/frozenlist-1.8.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24" }, - { url = "https://mirrors.aliyun.com/pypi/packages/05/23/6bde59eb55abd407d34f77d39a5126fb7b4f109a3f611d3929f14b700c66/frozenlist-1.8.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d2/3f/22cff331bfad7a8afa616289000ba793347fcd7bc275f3b28ecea2a27909/frozenlist-1.8.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a4/89/5b057c799de4838b6c69aa82b79705f2027615e01be996d2486a69ca99c4/frozenlist-1.8.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/30/de/2c22ab3eb2a8af6d69dc799e48455813bab3690c760de58e1bf43b36da3e/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef" }, - { url = "https://mirrors.aliyun.com/pypi/packages/59/f7/970141a6a8dbd7f556d94977858cfb36fa9b66e0892c6dd780d2219d8cd8/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c1/15/ca1adae83a719f82df9116d66f5bb28bb95557b3951903d39135620ef157/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ac/83/dca6dc53bf657d371fbc88ddeb21b79891e747189c5de990b9dfff2ccba1/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/96/52/abddd34ca99be142f354398700536c5bd315880ed0a213812bc491cff5e4/frozenlist-1.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/af/d3/76bd4ed4317e7119c2b7f57c3f6934aba26d277acc6309f873341640e21f/frozenlist-1.8.0-cp314-cp314t-win32.whl", hash = "sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/76/c615883b7b521ead2944bb3480398cbb07e12b7b4e4d073d3752eb721558/frozenlist-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/a3/5982da14e113d07b325230f95060e2169f5311b1017ea8af2a29b374c289/frozenlist-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79" }, { url = "https://mirrors.aliyun.com/pypi/packages/9a/9a/e35b4a917281c0b8419d4207f4334c8e8c5dbf4f3f5f9ada73958d937dcc/frozenlist-1.8.0-py3-none-any.whl", hash = "sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d" }, ] @@ -816,21 +668,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/8d/6e/d73c94d13b6465e9f7cd6231c68abde838bb22408596c05d9059830b7872/greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2" }, { url = "https://mirrors.aliyun.com/pypi/packages/5e/b3/c9c23a6478b3bcc91f979ce4ca50879e4d0b2bd7b9a53d8ecded719b92e2/greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946" }, { url = "https://mirrors.aliyun.com/pypi/packages/90/e7/824beda656097edee36ab15809fd063447b200cc03a7f6a24c34d520bc88/greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ae/fb/011c7c717213182caf78084a9bea51c8590b0afda98001f69d9f853a495b/greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/2e/a3a417d620363fdbb08a48b1dd582956a46a61bf8fd27ee8164f9dfe87c2/greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/09/c6c4a0db47defafd2d6bab8ddfe47ad19963b4e30f5bed84d75328059f8c/greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/38/9d42d60dffb04b45f03dbab9430898352dba277758640751dc5cc316c521/greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/96/61/373c30b7197f9e756e4c81ae90a8d55dc3598c17673f91f4d31c3c689c3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fd/d3/ca534310343f5945316f9451e953dcd89b36fe7a19de652a1dc5a0eeef3f/greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/52/cb/c21a3fd5d2c9c8b622e7bede6d6d00e00551a5ee474ea6d831b5f567a8b4/greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6a/8e/8a2db6d11491837af1de64b8aff23707c6e85241be13c60ed399a72e2ef8/greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79" }, - { url = "https://mirrors.aliyun.com/pypi/packages/28/24/cbbec49bacdcc9ec652a81d3efef7b59f326697e7edf6ed775a5e08e54c2/greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242" }, - { url = "https://mirrors.aliyun.com/pypi/packages/86/2e/4f2b9323c144c4fe8842a4e0d92121465485c3c2c5b9e9b30a52e80f523f/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d9/87/50ca60e515f5bb55a2fbc5f0c9b5b156de7d2fc51a0a69abc9d23914a237/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1d/94/74310866dfa2b73dd08659a3d18762f83985ad3281901ba0ee9a815194fb/greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/97/43/8bf0ffa3d498eeee4c58c212a3905dd6146c01c8dc0b0a046481ca29b18c/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/90/a3be7a5f378fc6e84abe4dcfb2ba32b07786861172e502388b4c90000d1b/greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e1/2b/98c7f93e6db9977aaee07eb1e51ca63bd5f779b900d362791d3252e60558/greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451" }, ] [[package]] @@ -872,16 +709,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/1a/74/fd3317be5672f4856bcdd1a9e7b5e17554692d3db9a3b273879dc02d657d/grpcio-1.76.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:931091142fd8cc14edccc0845a79248bc155425eee9a98b2db2ea4f00a235a42" }, { url = "https://mirrors.aliyun.com/pypi/packages/45/bb/ca038cf420f405971f19821c8c15bcbc875505f6ffadafe9ffd77871dc4c/grpcio-1.76.0-cp313-cp313-win32.whl", hash = "sha256:5e8571632780e08526f118f74170ad8d50fb0a48c23a746bef2a6ebade3abd6f" }, { url = "https://mirrors.aliyun.com/pypi/packages/41/80/84087dc56437ced7cdd4b13d7875e7439a52a261e3ab4e06488ba6173b0a/grpcio-1.76.0-cp313-cp313-win_amd64.whl", hash = "sha256:f9f7bd5faab55f47231ad8dba7787866b69f5e93bc306e3915606779bbfb4ba8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/46/39adac80de49d678e6e073b70204091e76631e03e94928b9ea4ecf0f6e0e/grpcio-1.76.0-cp314-cp314-linux_armv7l.whl", hash = "sha256:ff8a59ea85a1f2191a0ffcc61298c571bc566332f82e5f5be1b83c9d8e668a62" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9c/f5/a4531f7fb8b4e2a60b94e39d5d924469b7a6988176b3422487be61fe2998/grpcio-1.76.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:06c3d6b076e7b593905d04fdba6a0525711b3466f43b3400266f04ff735de0cd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/1c/de55d868ed7a8bd6acc6b1d6ddc4aa36d07a9f31d33c912c804adb1b971b/grpcio-1.76.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fd5ef5932f6475c436c4a55e4336ebbe47bd3272be04964a03d316bbf4afbcbc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/59/64/99e44c02b5adb0ad13ab3adc89cb33cb54bfa90c74770f2607eea629b86f/grpcio-1.76.0-cp314-cp314-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:b331680e46239e090f5b3cead313cc772f6caa7d0fc8de349337563125361a4a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/28/40a5be3f9a86949b83e7d6a2ad6011d993cbe9b6bd27bea881f61c7788b6/grpcio-1.76.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2229ae655ec4e8999599469559e97630185fdd53ae1e8997d147b7c9b2b72cba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/a9/1be18e6055b64467440208a8559afac243c66a8b904213af6f392dc2212f/grpcio-1.76.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:490fa6d203992c47c7b9e4a9d39003a0c2bcc1c9aa3c058730884bbbb0ee9f09" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0f/55/dba05d3fcc151ce6e81327541d2cc8394f442f6b350fead67401661bf041/grpcio-1.76.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:479496325ce554792dba6548fae3df31a72cef7bad71ca2e12b0e58f9b336bfc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4a/45/122df922d05655f63930cf42c9e3f72ba20aadb26c100ee105cad4ce4257/grpcio-1.76.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1c9b93f79f48b03ada57ea24725d83a30284a012ec27eab2cf7e50a550cbbbcc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4a/6e/0b899b7f6b66e5af39e377055fb4a6675c9ee28431df5708139df2e93233/grpcio-1.76.0-cp314-cp314-win32.whl", hash = "sha256:747fa73efa9b8b1488a95d0ba1039c8e2dca0f741612d80415b1e1c560febf4e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/19/41/0b430b01a2eb38ee887f88c1f07644a1df8e289353b78e82b37ef988fb64/grpcio-1.76.0-cp314-cp314-win_amd64.whl", hash = "sha256:922fa70ba549fce362d2e2871ab542082d66e2aaf0c19480ea453905b01f384e" }, ] [[package]] @@ -906,13 +733,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/4a/1d/04513e3cab8f29ab8c109d309ddd21a2705afab9d52f2ba1151e0c14f086/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6de1fc44f58f6dd937956c8d304d8c2dea264c80680bcfa61ca4a15e7b76780f" }, { url = "https://mirrors.aliyun.com/pypi/packages/f0/7c/60a2756d7feec7387db3a1176c632357632fbe7849fce576c5559d4520c7/hf_xet-1.2.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f182f264ed2acd566c514e45da9f2119110e48a87a327ca271027904c70c5832" }, { url = "https://mirrors.aliyun.com/pypi/packages/4e/64/48fffbd67fb418ab07451e4ce641a70de1c40c10a13e25325e24858ebe5a/hf_xet-1.2.0-cp313-cp313t-win_amd64.whl", hash = "sha256:293a7a3787e5c95d7be1857358a9130694a9c6021de3f27fa233f37267174382" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/51/f7e2caae42f80af886db414d4e9885fac959330509089f97cccb339c6b87/hf_xet-1.2.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:10bfab528b968c70e062607f663e21e34e2bba349e8038db546646875495179e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6e/1d/a641a88b69994f9371bd347f1dd35e5d1e2e2460a2e350c8d5165fc62005/hf_xet-1.2.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a212e842647b02eb6a911187dc878e79c4aa0aa397e88dd3b26761676e8c1f8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/e0/e5e9bba7d15f0318955f7ec3f4af13f92e773fbb368c0b8008a5acbcb12f/hf_xet-1.2.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30e06daccb3a7d4c065f34fc26c14c74f4653069bb2b194e7f18f17cbe9939c0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/21/90/b7fe5ff6f2b7b8cbdf1bd56145f863c90a5807d9758a549bf3d916aa4dec/hf_xet-1.2.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:29c8fc913a529ec0a91867ce3d119ac1aac966e098cf49501800c870328cc090" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6f/cb/73f276f0a7ce46cc6a6ec7d6c7d61cbfe5f2e107123d9bbd0193c355f106/hf_xet-1.2.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e159cbfcfbb29f920db2c09ed8b660eb894640d284f102ada929b6e3dc410a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b8/1e/d642a12caa78171f4be64f7cd9c40e3ca5279d055d0873188a58c0f5fbb9/hf_xet-1.2.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:9c91d5ae931510107f148874e9e2de8a16052b6f1b3ca3c1b12f15ccb491390f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/17/b5/33764714923fa1ff922770f7ed18c2daae034d21ae6e10dbf4347c854154/hf_xet-1.2.0-cp314-cp314t-win_amd64.whl", hash = "sha256:210d577732b519ac6ede149d2f2f34049d44e8622bf14eb3d63bbcd2d4b332dc" }, { url = "https://mirrors.aliyun.com/pypi/packages/96/2d/22338486473df5923a9ab7107d375dbef9173c338ebef5098ef593d2b560/hf_xet-1.2.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:46740d4ac024a7ca9b22bebf77460ff43332868b661186a8e46c227fdae01848" }, { url = "https://mirrors.aliyun.com/pypi/packages/7f/8c/c5becfa53234299bc2210ba314eaaae36c2875e0045809b82e40a9544f0c/hf_xet-1.2.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:27df617a076420d8845bea087f59303da8be17ed7ec0cd7ee3b9b9f579dff0e4" }, { url = "https://mirrors.aliyun.com/pypi/packages/9a/92/cf3ab0b652b082e66876d08da57fcc6fa2f0e6c70dfbbafbd470bb73eb47/hf_xet-1.2.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3651fd5bfe0281951b988c0facbe726aa5e347b103a675f49a3fa8144c7968fd" }, @@ -962,13 +782,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/32/4d/9dd616c38da088e3f436e9a616e1d0cc66544b8cdac405cc4e81c8679fc7/httptools-0.7.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:44c8f4347d4b31269c8a9205d8a5ee2df5322b09bbbd30f8f862185bb6b05346" }, { url = "https://mirrors.aliyun.com/pypi/packages/1d/3a/a6c595c310b7df958e739aae88724e24f9246a514d909547778d776799be/httptools-0.7.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:465275d76db4d554918aba40bf1cbebe324670f3dfc979eaffaa5d108e2ed650" }, { url = "https://mirrors.aliyun.com/pypi/packages/fd/82/88e8d6d2c51edc1cc391b6e044c6c435b6aebe97b1abc33db1b0b24cd582/httptools-0.7.1-cp313-cp313-win_amd64.whl", hash = "sha256:322d00c2068d125bd570f7bf78b2d367dad02b919d8581d7476d8b75b294e3e6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/34/50/9d095fcbb6de2d523e027a2f304d4551855c2f46e0b82befd718b8b20056/httptools-0.7.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c08fe65728b8d70b6923ce31e3956f859d5e1e8548e6f22ec520a962c6757270" }, - { url = "https://mirrors.aliyun.com/pypi/packages/07/f0/89720dc5139ae54b03f861b5e2c55a37dba9a5da7d51e1e824a1f343627f/httptools-0.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7aea2e3c3953521c3c51106ee11487a910d45586e351202474d45472db7d72d3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b3/cb/eea88506f191fb552c11787c23f9a405f4c7b0c5799bf73f2249cd4f5228/httptools-0.7.1-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0e68b8582f4ea9166be62926077a3334064d422cf08ab87d8b74664f8e9058e1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/4a/a548bdfae6369c0d078bab5769f7b66f17f1bfaa6fa28f81d6be6959066b/httptools-0.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df091cf961a3be783d6aebae963cc9b71e00d57fa6f149025075217bc6a55a7b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4d/31/14df99e1c43bd132eec921c2e7e11cda7852f65619bc0fc5bdc2d0cb126c/httptools-0.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f084813239e1eb403ddacd06a30de3d3e09a9b76e7894dcda2b22f8a726e9c60" }, - { url = "https://mirrors.aliyun.com/pypi/packages/22/d2/b7e131f7be8d854d48cb6d048113c30f9a46dca0c9a8b08fcb3fcd588cdc/httptools-0.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7347714368fb2b335e9063bc2b96f2f87a9ceffcd9758ac295f8bbcd3ffbc0ca" }, - { url = "https://mirrors.aliyun.com/pypi/packages/53/cf/878f3b91e4e6e011eff6d1fa9ca39f7eb17d19c9d7971b04873734112f30/httptools-0.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:cfabda2a5bb85aa2a904ce06d974a3f30fb36cc63d7feaddec05d2050acede96" }, ] [[package]] @@ -1125,32 +938,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/99/43/7320c50e4133575c66e9f7dadead35ab22d7c012a3b09bb35647792b2a6d/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0ab74e19f6a2b027ea4f845a78827969af45ce790e6cb3e1ebab71bdf9f215ff" }, { url = "https://mirrors.aliyun.com/pypi/packages/65/d6/17ae4a270d4a987ef8a385b906d2bdfc9fce502d6dc0d3aea865b47f548c/kiwisolver-1.4.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dba5ee5d3981160c28d5490f0d1b7ed730c22470ff7f6cc26cfcfaacb9896a07" }, { url = "https://mirrors.aliyun.com/pypi/packages/2a/8f/8f6f491d595a9e5912971f3f863d81baddccc8a4d0c3749d6a0dd9ffc9df/kiwisolver-1.4.9-cp313-cp313t-win_arm64.whl", hash = "sha256:0749fd8f4218ad2e851e11cc4dc05c7cbc0cbc4267bdfdb31782e65aace4ee9c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6b/32/6cc0fbc9c54d06c2969faa9c1d29f5751a2e51809dd55c69055e62d9b426/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:9928fe1eb816d11ae170885a74d074f57af3a0d65777ca47e9aeb854a1fba386" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/dd/2bfb1d4a4823d92e8cbb420fe024b8d2167f72079b3bb941207c42570bdf/kiwisolver-1.4.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d0005b053977e7b43388ddec89fa567f43d4f6d5c2c0affe57de5ebf290dc552" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f7/69/00aafdb4e4509c2ca6064646cba9cd4b37933898f426756adb2cb92ebbed/kiwisolver-1.4.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2635d352d67458b66fd0667c14cb1d4145e9560d503219034a18a87e971ce4f3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/dc/51acc6791aa14e5cb6d8a2e28cefb0dc2886d8862795449d021334c0df20/kiwisolver-1.4.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:767c23ad1c58c9e827b649a9ab7809fd5fd9db266a9cf02b0e926ddc2c680d58" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3d/bb/93fa64a81db304ac8a246f834d5094fae4b13baf53c839d6bb6e81177129/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72d0eb9fba308b8311685c2268cf7d0a0639a6cd027d8128659f72bdd8a024b4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/70/e6/6df102916960fb8d05069d4bd92d6d9a8202d5a3e2444494e7cd50f65b7a/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f68e4f3eeca8fb22cc3d731f9715a13b652795ef657a13df1ad0c7dc0e9731df" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7c/47/e142aaa612f5343736b087864dbaebc53ea8831453fb47e7521fa8658f30/kiwisolver-1.4.9-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d84cd4061ae292d8ac367b2c3fa3aad11cb8625a95d135fe93f286f914f3f5a6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/54/89/d641a746194a0f4d1a3670fb900d0dbaa786fb98341056814bc3f058fa52/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:a60ea74330b91bd22a29638940d115df9dc00af5035a9a2a6ad9399ffb4ceca5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/aa/6b/5ee1207198febdf16ac11f78c5ae40861b809cbe0e6d2a8d5b0b3044b199/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ce6a3a4e106cf35c2d9c4fa17c05ce0b180db622736845d4315519397a77beaf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fc/ff/b269eefd90f4ae14dcc74973d5a0f6d28d3b9bb1afd8c0340513afe6b39a/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:77937e5e2a38a7b48eef0585114fe7930346993a88060d0bf886086d2aa49ef5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fc/d4/10303190bd4d30de547534601e259a4fbf014eed94aae3e5521129215086/kiwisolver-1.4.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:24c175051354f4a28c5d6a31c93906dc653e2bf234e8a4bbfb964892078898ce" }, - { url = "https://mirrors.aliyun.com/pypi/packages/28/e0/a9a90416fce5c0be25742729c2ea52105d62eda6c4be4d803c2a7be1fa50/kiwisolver-1.4.9-cp314-cp314-win_amd64.whl", hash = "sha256:0763515d4df10edf6d06a3c19734e2566368980d21ebec439f33f9eb936c07b7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/10/6949958215b7a9a264299a7db195564e87900f709db9245e4ebdd3c70779/kiwisolver-1.4.9-cp314-cp314-win_arm64.whl", hash = "sha256:0e4e2bf29574a6a7b7f6cb5fa69293b9f96c928949ac4a53ba3f525dffb87f9c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ec/79/60e53067903d3bc5469b369fe0dfc6b3482e2133e85dae9daa9527535991/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:d976bbb382b202f71c67f77b0ac11244021cfa3f7dfd9e562eefcea2df711548" }, - { url = "https://mirrors.aliyun.com/pypi/packages/25/d1/4843d3e8d46b072c12a38c97c57fab4608d36e13fe47d47ee96b4d61ba6f/kiwisolver-1.4.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2489e4e5d7ef9a1c300a5e0196e43d9c739f066ef23270607d45aba368b91f2d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8c/ae/29ffcbd239aea8b93108de1278271ae764dfc0d803a5693914975f200596/kiwisolver-1.4.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e2ea9f7ab7fbf18fffb1b5434ce7c69a07582f7acc7717720f1d69f3e806f90c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a1/ae/d7ba902aa604152c2ceba5d352d7b62106bedbccc8e95c3934d94472bfa3/kiwisolver-1.4.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b34e51affded8faee0dfdb705416153819d8ea9250bbbf7ea1b249bdeb5f1122" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f2/41/27c70d427eddb8bc7e4f16420a20fefc6f480312122a59a959fdfe0445ad/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8aacd3d4b33b772542b2e01beb50187536967b514b00003bdda7589722d2a64" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/42/b3799a12bafc76d962ad69083f8b43b12bf4fe78b097b12e105d75c9b8f1/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7cf974dd4e35fa315563ac99d6287a1024e4dc2077b8a7d7cd3d2fb65d283134" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d2/b5/a210ea073ea1cfaca1bb5c55a62307d8252f531beb364e18aa1e0888b5a0/kiwisolver-1.4.9-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:85bd218b5ecfbee8c8a82e121802dcb519a86044c9c3b2e4aef02fa05c6da370" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5f/ce/a829eb8c033e977d7ea03ed32fb3c1781b4fa0433fbadfff29e39c676f32/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0856e241c2d3df4efef7c04a1e46b1936b6120c9bcf36dd216e3acd84bc4fb21" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/4b/b5e97eb142eb9cd0072dacfcdcd31b1c66dc7352b0f7c7255d339c0edf00/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:9af39d6551f97d31a4deebeac6f45b156f9755ddc59c07b402c148f5dbb6482a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/40/be/8eb4cd53e1b85ba4edc3a9321666f12b83113a178845593307a3e7891f44/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:bb4ae2b57fc1d8cbd1cf7b1d9913803681ffa903e7488012be5b76dedf49297f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/99/dd/841e9a66c4715477ea0abc78da039832fbb09dac5c35c58dc4c41a407b8a/kiwisolver-1.4.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:aedff62918805fb62d43a4aa2ecd4482c380dc76cd31bd7c8878588a61bd0369" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0c/28/4b2e5c47a0da96896fdfdb006340ade064afa1e63675d01ea5ac222b6d52/kiwisolver-1.4.9-cp314-cp314t-win_amd64.whl", hash = "sha256:1fa333e8b2ce4d9660f2cda9c0e1b6bafcfb2457a9d259faa82289e73ec24891" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32" }, { url = "https://mirrors.aliyun.com/pypi/packages/a3/0f/36d89194b5a32c054ce93e586d4049b6c2c22887b0eb229c61c68afd3078/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:720e05574713db64c356e86732c0f3c5252818d05f9df320f0ad8380641acea5" }, { url = "https://mirrors.aliyun.com/pypi/packages/52/ba/4ed75f59e4658fd21fe7dde1fee0ac397c678ec3befba3fe6482d987af87/kiwisolver-1.4.9-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:17680d737d5335b552994a2008fab4c851bcd7de33094a82067ef3a576ff02fa" }, { url = "https://mirrors.aliyun.com/pypi/packages/33/01/a8ea7c5ea32a9b45ceeaee051a04c8ed4320f5add3c51bfa20879b765b70/kiwisolver-1.4.9-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:85b5352f94e490c028926ea567fc569c52ec79ce131dadb968d3853e809518c2" }, @@ -1209,28 +996,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/d9/83/b2cfe8e76ff5c1c77f8a53da3d5de62d04b5ebf7cf913e37f8bca43b5d07/librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951" }, { url = "https://mirrors.aliyun.com/pypi/packages/a9/0b/c59d45de56a51bd2d3a401fc63449c0ac163e4ef7f523ea8b0c0dee86ec5/librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34" }, { url = "https://mirrors.aliyun.com/pypi/packages/fc/b9/973455cec0a1ec592395250c474164c4a58ebf3e0651ee920fef1a2623f1/librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1a/73/fa8814c6ce2d49c3827829cadaa1589b0bf4391660bd4510899393a23ebc/librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418" }, - { url = "https://mirrors.aliyun.com/pypi/packages/53/fe/f6c70956da23ea235fd2e3cc16f4f0b4ebdfd72252b02d1164dd58b4e6c3/librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/4d/7a2481444ac5fba63050d9abe823e6bc16896f575bfc9c1e5068d516cdce/librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ac/3c/10901d9e18639f8953f57c8986796cfbf4c1c514844a41c9197cf87cb707/librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea" }, - { url = "https://mirrors.aliyun.com/pypi/packages/db/01/5cbdde0951a5090a80e5ba44e6357d375048123c572a23eecfb9326993a7/librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6a/b4/e80528d2f4b7eaf1d437fcbd6fc6ba4cbeb3e2a0cb9ed5a79f47c7318706/librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c1/ab/938368f8ce31a9787ecd4becb1e795954782e4312095daf8fd22420227c8/librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/10/559c310e7a6e4014ac44867d359ef8238465fb499e7eb31b6bfe3e3f86f5/librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f8/db/a0db7acdb6290c215f343835c6efda5b491bb05c3ddc675af558f50fdba3/librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/72/e0/4f9bdc2a98a798511e81edcd6b54fe82767a715e05d1921115ac70717f6f/librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f9/3d/59c6402e3dec2719655a41ad027a7371f8e2334aa794ed11533ad5f34969/librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4e/9c/2481d80950b83085fb14ba3c595db56330d21bbc7d88a19f20165f3538db/librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/96/79/108df2cfc4e672336765d54e3ff887294c1cc36ea4335c73588875775527/librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde" }, - { url = "https://mirrors.aliyun.com/pypi/packages/46/f2/30179898f9994a5637459d6e169b6abdc982012c0a4b2d4c26f50c06f911/librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/da/f7563db55cebdc884f518ba3791ad033becc25ff68eb70902b1747dc0d70/librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b3/6c/4289acf076ad371471fa86718c30ae353e690d3de6167f7db36f429272f1/librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4a/7f/377521ac25b78ac0a5ff44127a0360ee6d5ddd3ce7327949876a30533daa/librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c5/b1/e1e96c3e20b23d00cf90f4aad48f0deb4cdfec2f0ed8380d0d85acf98bbf/librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/71/0f5d010e92ed9747e14bef35e91b6580533510f1e36a8a09eb79ee70b2f0/librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca" }, - { url = "https://mirrors.aliyun.com/pypi/packages/22/f0/07fb6ab5c39a4ca9af3e37554f9d42f25c464829254d72e4ebbd81da351c/librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365" }, - { url = "https://mirrors.aliyun.com/pypi/packages/24/d4/7e4be20993dc6a782639625bd2f97f3c66125c7aa80c82426956811cfccf/librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fc/85/69f92b2a7b3c0f88ffe107c86b952b397004b5b8ea5a81da3d9c04c04422/librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06" }, ] [[package]] @@ -1317,42 +1082,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/76/04/5c5e2b8577bc936e219becb2e98cdb1aca14a4921a12995b9d0c523502ae/lxml-6.0.2-cp313-cp313-win32.whl", hash = "sha256:e8cd2415f372e7e5a789d743d133ae474290a90b9023197fd78f32e2dc6873e2" }, { url = "https://mirrors.aliyun.com/pypi/packages/fe/0a/4643ccc6bb8b143e9f9640aa54e38255f9d3b45feb2cbe7ae2ca47e8782e/lxml-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:b30d46379644fbfc3ab81f8f82ae4de55179414651f110a1514f0b1f8f6cb2d7" }, { url = "https://mirrors.aliyun.com/pypi/packages/31/ef/dcf1d29c3f530577f61e5fe2f1bd72929acf779953668a8a47a479ae6f26/lxml-6.0.2-cp313-cp313-win_arm64.whl", hash = "sha256:13dcecc9946dca97b11b7c40d29fba63b55ab4170d3c0cf8c0c164343b9bfdcf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/03/15/d4a377b385ab693ce97b472fe0c77c2b16ec79590e688b3ccc71fba19884/lxml-6.0.2-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:b0c732aa23de8f8aec23f4b580d1e52905ef468afb4abeafd3fec77042abb6fe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c8/e8/c128e37589463668794d503afaeb003987373c5f94d667124ffd8078bbd9/lxml-6.0.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4468e3b83e10e0317a89a33d28f7aeba1caa4d1a6fd457d115dd4ffe90c5931d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/00/ce/74903904339decdf7da7847bb5741fc98a5451b42fc419a86c0c13d26fe2/lxml-6.0.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:abd44571493973bad4598a3be7e1d807ed45aa2adaf7ab92ab7c62609569b17d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/d3/131dec79ce61c5567fecf82515bd9bc36395df42501b50f7f7f3bd065df0/lxml-6.0.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:370cd78d5855cfbffd57c422851f7d3864e6ae72d0da615fca4dad8c45d375a5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3a/ea/a43ba9bb750d4ffdd885f2cd333572f5bb900cd2408b67fdda07e85978a0/lxml-6.0.2-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:901e3b4219fa04ef766885fb40fa516a71662a4c61b80c94d25336b4934b71c0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/60/23/6885b451636ae286c34628f70a7ed1fcc759f8d9ad382d132e1c8d3d9bfd/lxml-6.0.2-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:a4bf42d2e4cf52c28cc1812d62426b9503cdb0c87a6de81442626aa7d69707ba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/5b/fc2ddfc94ddbe3eebb8e9af6e3fd65e2feba4967f6a4e9683875c394c2d8/lxml-6.0.2-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b2c7fdaa4d7c3d886a42534adec7cfac73860b89b4e5298752f60aa5984641a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/29/9c/47293c58cc91769130fbf85531280e8cc7868f7fbb6d92f4670071b9cb3e/lxml-6.0.2-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:98a5e1660dc7de2200b00d53fa00bcd3c35a3608c305d45a7bbcaf29fa16e83d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9b/da/ba6eceb830c762b48e711ded880d7e3e89fc6c7323e587c36540b6b23c6b/lxml-6.0.2-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:dc051506c30b609238d79eda75ee9cab3e520570ec8219844a72a46020901e37" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a5/24/7be3f82cb7990b89118d944b619e53c656c97dc89c28cfb143fdb7cd6f4d/lxml-6.0.2-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8799481bbdd212470d17513a54d568f44416db01250f49449647b5ab5b5dccb9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1b/bd/dcfb9ea1e16c665efd7538fc5d5c34071276ce9220e234217682e7d2c4a5/lxml-6.0.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:9261bb77c2dab42f3ecd9103951aeca2c40277701eb7e912c545c1b16e0e4917" }, - { url = "https://mirrors.aliyun.com/pypi/packages/21/04/a60b0ff9314736316f28316b694bccbbabe100f8483ad83852d77fc7468e/lxml-6.0.2-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:65ac4a01aba353cfa6d5725b95d7aed6356ddc0a3cd734de00124d285b04b64f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d6/bd/7d54bd1846e5a310d9c715921c5faa71cf5c0853372adf78aee70c8d7aa2/lxml-6.0.2-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b22a07cbb82fea98f8a2fd814f3d1811ff9ed76d0fc6abc84eb21527596e7cc8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fd/32/5643d6ab947bc371da21323acb2a6e603cedbe71cb4c99c8254289ab6f4e/lxml-6.0.2-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:d759cdd7f3e055d6bc8d9bec3ad905227b2e4c785dc16c372eb5b5e83123f48a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/33/da/34c1ec4cff1eea7d0b4cd44af8411806ed943141804ac9c5d565302afb78/lxml-6.0.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:945da35a48d193d27c188037a05fec5492937f66fb1958c24fc761fb9d40d43c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/82/57/4eca3e31e54dc89e2c3507e1cd411074a17565fa5ffc437c4ae0a00d439e/lxml-6.0.2-cp314-cp314-win32.whl", hash = "sha256:be3aaa60da67e6153eb15715cc2e19091af5dc75faef8b8a585aea372507384b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/e0/c96cf13eccd20c9421ba910304dae0f619724dcf1702864fd59dd386404d/lxml-6.0.2-cp314-cp314-win_amd64.whl", hash = "sha256:fa25afbadead523f7001caf0c2382afd272c315a033a7b06336da2637d92d6ed" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d5/5d/b3f03e22b3d38d6f188ef044900a9b29b2fe0aebb94625ce9fe244011d34/lxml-6.0.2-cp314-cp314-win_arm64.whl", hash = "sha256:063eccf89df5b24e361b123e257e437f9e9878f425ee9aae3144c77faf6da6d8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5e/5c/42c2c4c03554580708fc738d13414801f340c04c3eff90d8d2d227145275/lxml-6.0.2-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:6162a86d86893d63084faaf4ff937b3daea233e3682fb4474db07395794fa80d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bf/4f/12df843e3e10d18d468a7557058f8d3733e8b6e12401f30b1ef29360740f/lxml-6.0.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:414aaa94e974e23a3e92e7ca5b97d10c0cf37b6481f50911032c69eeb3991bba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/0c/9dc31e6c2d0d418483cbcb469d1f5a582a1cd00a1f4081953d44051f3c50/lxml-6.0.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:48461bd21625458dd01e14e2c38dd0aea69addc3c4f960c30d9f59d7f93be601" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e7/2b/9b870c6ca24c841bdd887504808f0417aa9d8d564114689266f19ddf29c8/lxml-6.0.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:25fcc59afc57d527cfc78a58f40ab4c9b8fd096a9a3f964d2781ffb6eb33f4ed" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bf/0c/4f5f2a4dd319a178912751564471355d9019e220c20d7db3fb8307ed8582/lxml-6.0.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5179c60288204e6ddde3f774a93350177e08876eaf3ab78aa3a3649d43eb7d37" }, - { url = "https://mirrors.aliyun.com/pypi/packages/12/64/554eed290365267671fe001a20d72d14f468ae4e6acef1e179b039436967/lxml-6.0.2-cp314-cp314t-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:967aab75434de148ec80597b75062d8123cadf2943fb4281f385141e18b21338" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7a/31/1d748aa275e71802ad9722df32a7a35034246b42c0ecdd8235412c3396ef/lxml-6.0.2-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d100fcc8930d697c6561156c6810ab4a508fb264c8b6779e6e61e2ed5e7558f9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8f/41/2c11916bcac09ed561adccacceaedd2bf0e0b25b297ea92aab99fd03d0fa/lxml-6.0.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ca59e7e13e5981175b8b3e4ab84d7da57993eeff53c07764dcebda0d0e64ecd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/99/05/4e5c2873d8f17aa018e6afde417c80cc5d0c33be4854cce3ef5670c49367/lxml-6.0.2-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:957448ac63a42e2e49531b9d6c0fa449a1970dbc32467aaad46f11545be9af1d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0f/c9/dcc2da1bebd6275cdc723b515f93edf548b82f36a5458cca3578bc899332/lxml-6.0.2-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b7fc49c37f1786284b12af63152fe1d0990722497e2d5817acfe7a877522f9a9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9c/e2/5172e4e7468afca64a37b81dba152fc5d90e30f9c83c7c3213d6a02a5ce4/lxml-6.0.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e19e0643cc936a22e837f79d01a550678da8377d7d801a14487c10c34ee49c7e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a5/b3/15461fd3e5cd4ddcb7938b87fc20b14ab113b92312fc97afe65cd7c85de1/lxml-6.0.2-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:1db01e5cf14345628e0cbe71067204db658e2fb8e51e7f33631f5f4735fefd8d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/05/33/f310b987c8bf9e61c4dd8e8035c416bd3230098f5e3cfa69fc4232de7059/lxml-6.0.2-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:875c6b5ab39ad5291588aed6925fac99d0097af0dd62f33c7b43736043d4a2ec" }, - { url = "https://mirrors.aliyun.com/pypi/packages/70/ff/51c80e75e0bc9382158133bdcf4e339b5886c6ee2418b5199b3f1a61ed6d/lxml-6.0.2-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:cdcbed9ad19da81c480dfd6dd161886db6096083c9938ead313d94b30aadf272" }, - { url = "https://mirrors.aliyun.com/pypi/packages/56/4d/4856e897df0d588789dd844dbed9d91782c4ef0b327f96ce53c807e13128/lxml-6.0.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:80dadc234ebc532e09be1975ff538d154a7fa61ea5031c03d25178855544728f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0f/85/86766dfebfa87bea0ab78e9ff7a4b4b45225df4b4d3b8cc3c03c5cd68464/lxml-6.0.2-cp314-cp314t-win32.whl", hash = "sha256:da08e7bb297b04e893d91087df19638dc7a6bb858a954b0cc2b9f5053c922312" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fe/1a/b248b355834c8e32614650b8008c69ffeb0ceb149c793961dd8c0b991bb3/lxml-6.0.2-cp314-cp314t-win_amd64.whl", hash = "sha256:252a22982dca42f6155125ac76d3432e548a7625d56f5a273ee78a5057216eca" }, - { url = "https://mirrors.aliyun.com/pypi/packages/92/aa/df863bcc39c5e0946263454aba394de8a9084dbaff8ad143846b0d844739/lxml-6.0.2-cp314-cp314t-win_arm64.whl", hash = "sha256:bb4c1847b303835d89d785a18801a883436cdfd5dc3d62947f9c49e24f0f5a2c" }, { url = "https://mirrors.aliyun.com/pypi/packages/0b/11/29d08bc103a62c0eba8016e7ed5aeebbf1e4312e83b0b1648dd203b0e87d/lxml-6.0.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1c06035eafa8404b5cf475bb37a9f6088b0aca288d4ccc9d69389750d5543700" }, { url = "https://mirrors.aliyun.com/pypi/packages/12/b3/52ab9a3b31e5ab8238da241baa19eec44d2ab426532441ee607165aebb52/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c7d13103045de1bdd6fe5d61802565f1a3537d70cd3abf596aa0af62761921ee" }, { url = "https://mirrors.aliyun.com/pypi/packages/a0/33/1eaf780c1baad88224611df13b1c2a9dfa460b526cacfe769103ff50d845/lxml-6.0.2-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0a3c150a95fbe5ac91de323aa756219ef9cf7fde5a3f00e2281e30f33fa5fa4f" }, @@ -1432,28 +1161,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354" }, { url = "https://mirrors.aliyun.com/pypi/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218" }, { url = "https://mirrors.aliyun.com/pypi/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287" }, - { url = "https://mirrors.aliyun.com/pypi/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026" }, - { url = "https://mirrors.aliyun.com/pypi/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe" }, - { url = "https://mirrors.aliyun.com/pypi/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634" }, - { url = "https://mirrors.aliyun.com/pypi/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50" }, - { url = "https://mirrors.aliyun.com/pypi/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523" }, - { url = "https://mirrors.aliyun.com/pypi/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa" }, ] [[package]] @@ -1501,20 +1208,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/c0/3d/8b94a481456dfc9dfe6e39e93b5ab376e50998cddfd23f4ae3b431708f16/matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a" }, { url = "https://mirrors.aliyun.com/pypi/packages/bd/cd/bc06149fe5585ba800b189a6a654a75f1f127e8aab02fd2be10df7fa500c/matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958" }, { url = "https://mirrors.aliyun.com/pypi/packages/e3/de/b22cf255abec916562cc04eef457c13e58a1990048de0c0c3604d082355e/matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/43/9c0ff7a2f11615e516c3b058e1e6e8f9614ddeca53faca06da267c48345d/matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6f/ca/e8ae28649fcdf039fda5ef554b40a95f50592a3c47e6f7270c9561c12b07/matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f1/6f/009d129ae70b75e88cbe7e503a12a4c0670e08ed748a902c2568909e9eb5/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/26/4221a741eb97967bc1fd5e4c52b9aa5a91b2f4ec05b59f6def4d820f9df9/matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/f3/3abf75f38605772cf48a9daf5821cd4f563472f38b4b828c6fba6fa6d06e/matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/93/a5/de89ac80f10b8dc615807ee1133cd99ac74082581196d4d9590bea10690d/matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11" }, - { url = "https://mirrors.aliyun.com/pypi/packages/69/ce/b006495c19ccc0a137b48083168a37bd056392dee02f87dba0472f2797fe/matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/68/d9/b31116a3a855bd313c6fcdb7226926d59b041f26061c6c5b1be66a08c826/matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1e/90/6effe8103f0272685767ba5f094f453784057072f49b393e3ea178fe70a5/matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d7/65/a73188711bea603615fc0baecca1061429ac16940e2385433cc778a9d8e7/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f4/3d/b5c5d5d5be8ce63292567f0e2c43dde9953d3ed86ac2de0a72e93c8f07a1/matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4d/4b/e7beb6bbd49f6bae727a12b270a2654d13c397576d25bd6786e47033300f/matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7c/e6/76f2813d31f032e65f6f797e3f2f6e4aab95b65015924b1c51370395c28a/matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5d/49/d651878698a0b67f23aa28e17f45a6d6dd3d3f933fa29087fa4ce5947b5a/matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f" }, { url = "https://mirrors.aliyun.com/pypi/packages/04/30/3afaa31c757f34b7725ab9d2ba8b48b5e89c2019c003e7d0ead143aabc5a/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1" }, { url = "https://mirrors.aliyun.com/pypi/packages/48/2f/6334aec331f57485a642a7c8be03cb286f29111ae71c46c38b363230063c/matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a" }, { url = "https://mirrors.aliyun.com/pypi/packages/73/e4/6d6f14b2a759c622f191b2d67e9075a3f56aaccb3be4bb9bb6890030d0a0/matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2" }, @@ -1568,6 +1261,12 @@ dependencies = [ ] [package.optional-dependencies] +dev = [ + { name = "mypy" }, + { name = "pytest" }, + { name = "pytest-cov" }, + { name = "ruff" }, +] docs = [ { name = "furo" }, { name = "linkify-it-py" }, @@ -1598,14 +1297,6 @@ web = [ { name = "websockets" }, ] -[package.dev-dependencies] -dev = [ - { name = "mypy" }, - { name = "pytest" }, - { name = "pytest-cov" }, - { name = "ruff" }, -] - [package.metadata] requires-dist = [ { name = "click", specifier = ">=8.1.0" }, @@ -1615,6 +1306,7 @@ requires-dist = [ { name = "linkify-it-py", marker = "extra == 'docs'", specifier = ">=2.0.0" }, { name = "matplotlib", specifier = ">=3.7.0" }, { name = "matplotlib", marker = "extra == 'web'", specifier = ">=3.8.0" }, + { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.5.0" }, { name = "myst-parser", marker = "extra == 'docs'", specifier = ">=2.0.0" }, { name = "numpy", specifier = ">=1.24.0,<2.4" }, { name = "opencv-python", specifier = ">=4.8.0" }, @@ -1623,6 +1315,8 @@ requires-dist = [ { name = "psutil", marker = "extra == 'web'", specifier = ">=5.9.0" }, { name = "pydantic-settings", marker = "extra == 'web'", specifier = ">=2.13.1" }, { name = "pydicom", specifier = ">=3.0.1" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.2" }, + { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=7.0.0" }, { name = "python-docx", marker = "extra == 'web'", specifier = ">=1.1.0" }, { name = "python-dotenv", marker = "extra == 'web'", specifier = ">=1.2.1" }, { name = "python-multipart", marker = "extra == 'web'", specifier = ">=0.0.9" }, @@ -1630,6 +1324,7 @@ requires-dist = [ { name = "pyyaml", specifier = ">=6.0" }, { name = "reportlab", marker = "extra == 'web'", specifier = ">=4.0.0" }, { name = "rich", marker = "extra == 'web'", specifier = ">=13.0.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" }, { name = "scikit-image", specifier = ">=0.21.0" }, { name = "scikit-learn", specifier = ">=1.3.0" }, { name = "scipy", specifier = ">=1.11.0" }, @@ -1647,15 +1342,7 @@ requires-dist = [ { name = "wandb", marker = "extra == 'wandb'", specifier = ">=0.15.0" }, { name = "websockets", marker = "extra == 'web'", specifier = ">=11.0" }, ] -provides-extras = ["wandb", "lightning", "web", "docs"] - -[package.metadata.requires-dev] -dev = [ - { name = "mypy", specifier = ">=1.5.0" }, - { name = "pytest", specifier = ">=9.0.2" }, - { name = "pytest-cov", specifier = ">=7.0.0" }, - { name = "ruff", specifier = ">=0.1.0" }, -] +provides-extras = ["dev", "wandb", "lightning", "web", "docs"] [[package]] name = "mpmath" @@ -1744,42 +1431,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/dc/1d/b31650eab6c5778aceed46ba735bd97f7c7d2f54b319fa916c0f96e7805b/multidict-6.7.1-cp313-cp313t-win32.whl", hash = "sha256:df9f19c28adcb40b6aae30bbaa1478c389efd50c28d541d76760199fc1037c32" }, { url = "https://mirrors.aliyun.com/pypi/packages/ac/5b/2d2d1d522e51285bd61b1e20df8f47ae1a9d80839db0b24ea783b3832832/multidict-6.7.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d54ecf9f301853f2c5e802da559604b3e95bb7a3b01a9c295c6ee591b9882de8" }, { url = "https://mirrors.aliyun.com/pypi/packages/3d/a3/cc409ba012c83ca024a308516703cf339bdc4b696195644a7215a5164a24/multidict-6.7.1-cp313-cp313t-win_arm64.whl", hash = "sha256:5a37ca18e360377cfda1d62f5f382ff41f2b8c4ccb329ed974cc2e1643440118" }, - { url = "https://mirrors.aliyun.com/pypi/packages/91/cc/db74228a8be41884a567e88a62fd589a913708fcf180d029898c17a9a371/multidict-6.7.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d5/22/492f2246bb5b534abd44804292e81eeaf835388901f0c574bac4eeec73c5/multidict-6.7.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f1/4f/733c48f270565d78b4544f2baddc2fb2a245e5a8640254b12c36ac7ac68e/multidict-6.7.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/24/bb/2c0c2287963f4259c85e8bcbba9182ced8d7fca65c780c38e99e61629d11/multidict-6.7.1-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a7/f9/44d4b3064c65079d2467888794dea218d1601898ac50222ab8a9a8094460/multidict-6.7.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8b/13/78f7275e73fa17b24c9a51b0bd9d73ba64bb32d0ed51b02a746eb876abe7/multidict-6.7.1-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/25/8167187f62ae3cbd52da7893f58cb036b47ea3fb67138787c76800158982/multidict-6.7.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a1/e7/69a3a83b7b030cf283fb06ce074a05a02322359783424d7edf0f15fe5022/multidict-6.7.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fe/3b/8ec5074bcfc450fe84273713b4b0a0dd47c0249358f5d82eb8104ffe2520/multidict-6.7.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/5a/d5a99e3acbca0e29c5d9cba8f92ceb15dce78bab963b308ae692981e3a5d/multidict-6.7.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/35/48/e58cd31f6c7d5102f2a4bf89f96b9cf7e00b6c6f3d04ecc44417c00a5a3c/multidict-6.7.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/94/33/1cd210229559cb90b6786c30676bb0c58249ff42f942765f88793b41fdce/multidict-6.7.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/64/f2/6e1107d226278c876c783056b7db43d800bb64c6131cec9c8dfb6903698e/multidict-6.7.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4d/c1/11f664f14d525e4a1b5327a82d4de61a1db604ab34c6603bb3c2cc63ad34/multidict-6.7.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e1/9f/75a9ac888121d0c5bbd4ecf4eead45668b1766f6baabfb3b7f66a410e231/multidict-6.7.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9a/e7/50bf7b004cc8525d80dbbbedfdc7aed3e4c323810890be4413e589074032/multidict-6.7.1-cp314-cp314-win32.whl", hash = "sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/bf/52f25716bbe93745595800f36fb17b73711f14da59ed0bb2eba141bc9f0f/multidict-6.7.1-cp314-cp314-win_amd64.whl", hash = "sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/97/ab/22803b03285fa3a525f48217963da3a65ae40f6a1b6f6cf2768879e208f9/multidict-6.7.1-cp314-cp314-win_arm64.whl", hash = "sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e0/6d/f9293baa6146ba9507e360ea0292b6422b016907c393e2f63fc40ab7b7b5/multidict-6.7.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7a/68/53b5494738d83558d87c3c71a486504d8373421c3e0dbb6d0db48ad42ee0/multidict-6.7.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/37/e8/5284c53310dcdc99ce5d66563f6e5773531a9b9fe9ec7a615e9bc306b05f/multidict-6.7.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/fc/6800d0e5b3875568b4083ecf5f310dcf91d86d52573160834fb4bfcf5e4f/multidict-6.7.1-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/75/4ad0973179361cdf3a113905e6e088173198349131be2b390f9fa4da5fc6/multidict-6.7.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c3/9c/095bb28b5da139bd41fb9a5d5caff412584f377914bd8787c2aa98717130/multidict-6.7.1-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889" }, - { url = "https://mirrors.aliyun.com/pypi/packages/07/d0/c0a72000243756e8f5a277b6b514fa005f2c73d481b7d9e47cd4568aa2e4/multidict-6.7.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c0/6b/f69da15289e384ecf2a68837ec8b5ad8c33e973aa18b266f50fe55f24b8c/multidict-6.7.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a2/76/b9669547afa5a1a25cd93eaca91c0da1c095b06b6d2d8ec25b713588d3a1/multidict-6.7.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7e/a9/a50d2669e506dad33cfc45b5d574a205587b7b8a5f426f2fbb2e90882588/multidict-6.7.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c5/bb/1609558ad8b456b4827d3c5a5b775c93b87878fd3117ed3db3423dfbce1b/multidict-6.7.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d8/59/6f61039d2aa9261871e03ab9dc058a550d240f25859b05b67fd70f80d4b3/multidict-6.7.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a1/29/fdc6a43c203890dc2ae9249971ecd0c41deaedfe00d25cb6564b2edd99eb/multidict-6.7.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a9/14/a153a06101323e4cf086ecee3faadba52ff71633d471f9685c42e3736163/multidict-6.7.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/5f/604ae839e64a4a6efc80db94465348d3b328ee955e37acb24badbcd24d83/multidict-6.7.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5f/60/c3a5187bf66f6fb546ff4ab8fb5a077cbdd832d7b1908d4365c7f74a1917/multidict-6.7.1-cp314-cp314t-win32.whl", hash = "sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0c/f7/addf1087b860ac60e6f382240f64fb99f8bfb532bb06f7c542b83c29ca61/multidict-6.7.1-cp314-cp314t-win_amd64.whl", hash = "sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4c/81/4629d0aa32302ef7b2ec65c75a728cc5ff4fa410c50096174c1632e70b3e/multidict-6.7.1-cp314-cp314t-win_arm64.whl", hash = "sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2" }, { url = "https://mirrors.aliyun.com/pypi/packages/81/08/7036c080d7117f28a4af526d794aab6a84463126db031b007717c1a6676e/multidict-6.7.1-py3-none-any.whl", hash = "sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56" }, ] @@ -1813,12 +1464,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/d1/32/dd260d52babf67bad8e6770f8e1102021877ce0edea106e72df5626bb0ec/mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef" }, { url = "https://mirrors.aliyun.com/pypi/packages/71/d0/5e60a9d2e3bd48432ae2b454b7ef2b62a960ab51292b1eda2a95edd78198/mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75" }, { url = "https://mirrors.aliyun.com/pypi/packages/98/76/d32051fa65ecf6cc8c6610956473abdc9b4c43301107476ac03559507843/mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/de/eb/b83e75f4c820c4247a58580ef86fcd35165028f191e7e1ba57128c52782d/mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/94/28/52785ab7bfa165f87fcbb61547a93f98bb20e7f82f90f165a1f69bce7b3d/mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0a/c6/bdd60774a0dbfb05122e3e925f2e9e846c009e479dcec4821dad881f5b52/mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/32/2a/66ba933fe6c76bd40d1fe916a83f04fed253152f451a877520b3c4a5e41e/mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/da/5055c63e377c5c2418760411fd6a63ee2b96cf95397259038756c042574f/mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957" }, - { url = "https://mirrors.aliyun.com/pypi/packages/cd/09/4ebd873390a063176f06b0dbf1f7783dd87bd120eae7727fa4ae4179b685/mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f" }, { url = "https://mirrors.aliyun.com/pypi/packages/8d/f4/4ce9a05ce5ded1de3ec1c1d96cf9f9504a04e54ce0ed55cfa38619a32b8d/mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247" }, ] @@ -1908,28 +1553,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/80/e9/aff53abbdd41b0ecca94285f325aff42357c6b5abc482a3fcb4994290b18/numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3" }, { url = "https://mirrors.aliyun.com/pypi/packages/d5/81/50613fec9d4de5480de18d4f8ef59ad7e344d497edbef3cfd80f24f98461/numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234" }, { url = "https://mirrors.aliyun.com/pypi/packages/bb/ab/08fd63b9a74303947f34f0bd7c5903b9c5532c2d287bead5bdf4c556c486/numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ba/97/1a914559c19e32d6b2e233cf9a6a114e67c856d35b1d6babca571a3e880f/numpy-2.3.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82" }, - { url = "https://mirrors.aliyun.com/pypi/packages/57/d4/51233b1c1b13ecd796311216ae417796b88b0616cfd8a33ae4536330748a/numpy-2.3.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/45/98/2fe46c5c2675b8306d0b4a3ec3494273e93e1226a490f766e84298576956/numpy-2.3.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ce/0e/0698378989bb0ac5f1660c81c78ab1fe5476c1a521ca9ee9d0710ce54099/numpy-2.3.5-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5e/a6/9ca0eecc489640615642a6cbc0ca9e10df70df38c4d43f5a928ff18d8827/numpy-2.3.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c8/f6/07ec185b90ec9d7217a00eeeed7383b73d7e709dae2a9a021b051542a708/numpy-2.3.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520" }, - { url = "https://mirrors.aliyun.com/pypi/packages/75/37/164071d1dde6a1a84c9b8e5b414fa127981bad47adf3a6b7e23917e52190/numpy-2.3.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/08/3c/f18b82a406b04859eb026d204e4e1773eb41c5be58410f41ffa511d114ae/numpy-2.3.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/40/79/f82f572bf44cf0023a2fe8588768e23e1592585020d638999f15158609e1/numpy-2.3.5-cp314-cp314-win32.whl", hash = "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a3/2e/235b4d96619931192c91660805e5e49242389742a7a82c27665021db690c/numpy-2.3.5-cp314-cp314-win_amd64.whl", hash = "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/07/2b/29fd75ce45d22a39c61aad74f3d718e7ab67ccf839ca8b60866054eb15f8/numpy-2.3.5-cp314-cp314-win_arm64.whl", hash = "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/17/e1/f6a721234ebd4d87084cfa68d081bcba2f5cfe1974f7de4e0e8b9b2a2ba1/numpy-2.3.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5c/1c/baf7ffdc3af9c356e1c135e57ab7cf8d247931b9554f55c467efe2c69eff/numpy-2.3.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad" }, - { url = "https://mirrors.aliyun.com/pypi/packages/74/91/f7f0295151407ddc9ba34e699013c32c3c91944f9b35fcf9281163dc1468/numpy-2.3.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2e/3b/78aebf345104ec50dd50a4d06ddeb46a9ff5261c33bcc58b1c4f12f85ec2/numpy-2.3.5-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20" }, - { url = "https://mirrors.aliyun.com/pypi/packages/02/c6/7c34b528740512e57ef1b7c8337ab0b4f0bddf34c723b8996c675bc2bc91/numpy-2.3.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/35/09d433c5262bc32d725bafc619e095b6a6651caf94027a03da624146f655/numpy-2.3.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7a/ab/6a7b259703c09a88804fa2430b43d6457b692378f6b74b356155283566ac/numpy-2.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c2/88/330da2071e8771e60d1038166ff9d73f29da37b01ec3eb43cb1427464e10/numpy-2.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227" }, - { url = "https://mirrors.aliyun.com/pypi/packages/51/41/851c4b4082402d9ea860c3626db5d5df47164a712cb23b54be028b184c1c/numpy-2.3.5-cp314-cp314t-win32.whl", hash = "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/90/30/d48bde1dfd93332fa557cff1972fbc039e055a52021fbef4c2c4b1eefd17/numpy-2.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2d/fd/4b5eb0b3e888d86aee4d198c23acec7d214baaf17ea93c1adec94c9518b9/numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42" }, { url = "https://mirrors.aliyun.com/pypi/packages/c6/65/f9dea8e109371ade9c782b4e4756a82edf9d3366bca495d84d79859a0b79/numpy-2.3.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310" }, { url = "https://mirrors.aliyun.com/pypi/packages/00/4f/edb00032a8fb92ec0a679d3830368355da91a69cab6f3e9c21b64d0bb986/numpy-2.3.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c" }, { url = "https://mirrors.aliyun.com/pypi/packages/16/a4/e8a53b5abd500a63836a29ebe145fc1ab1f2eefe1cfe59276020373ae0aa/numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18" }, @@ -1976,7 +1599,7 @@ name = "nvidia-cudnn-cu12" version = "9.10.2.21" source = { registry = "https://mirrors.aliyun.com/pypi/simple/" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cublas-cu12" }, ] wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/ba/51/e123d997aa098c61d029f76663dedbfb9bc8dcf8c60cbd6adbe42f76d049/nvidia_cudnn_cu12-9.10.2.21-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:949452be657fa16687d0930933f032835951ef0892b37d2d53824d1a84dc97a8" }, @@ -1987,7 +1610,7 @@ name = "nvidia-cufft-cu12" version = "11.3.3.83" source = { registry = "https://mirrors.aliyun.com/pypi/simple/" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/1f/13/ee4e00f30e676b66ae65b4f08cb5bcbb8392c03f54f2d5413ea99a5d1c80/nvidia_cufft_cu12-11.3.3.83-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4d2dd21ec0b88cf61b62e6b43564355e5222e4a3fb394cac0db101f2dd0d4f74" }, @@ -2014,9 +1637,9 @@ name = "nvidia-cusolver-cu12" version = "11.7.3.90" source = { registry = "https://mirrors.aliyun.com/pypi/simple/" } dependencies = [ - { name = "nvidia-cublas-cu12", marker = "sys_platform == 'linux'" }, - { name = "nvidia-cusparse-cu12", marker = "sys_platform == 'linux'" }, - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-cublas-cu12" }, + { name = "nvidia-cusparse-cu12" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/85/48/9a13d2975803e8cf2777d5ed57b87a0b6ca2cc795f9a4f59796a910bfb80/nvidia_cusolver_cu12-11.7.3.90-py3-none-manylinux_2_27_x86_64.whl", hash = "sha256:4376c11ad263152bd50ea295c05370360776f8c3427b30991df774f9fb26c450" }, @@ -2027,7 +1650,7 @@ name = "nvidia-cusparse-cu12" version = "12.5.8.93" source = { registry = "https://mirrors.aliyun.com/pypi/simple/" } dependencies = [ - { name = "nvidia-nvjitlink-cu12", marker = "sys_platform == 'linux'" }, + { name = "nvidia-nvjitlink-cu12" }, ] wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/c2/f5/e1854cb2f2bcd4280c44736c93550cc300ff4b8c95ebe370d0aa7d2b473d/nvidia_cusparse_cu12-12.5.8.93-py3-none-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ec05d76bbbd8b61b06a80e1eaf8cf4959c3d4ce8e711b65ebd0443bb0ebb13b" }, @@ -2139,19 +1762,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/44/23/78d645adc35d94d1ac4f2a3c4112ab6f5b8999f4898b8cdf01252f8df4a9/pandas-2.3.3-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:900f47d8f20860de523a1ac881c4c36d65efcb2eb850e6948140fa781736e110" }, { url = "https://mirrors.aliyun.com/pypi/packages/53/da/d10013df5e6aaef6b425aa0c32e1fc1f3e431e4bcabd420517dceadce354/pandas-2.3.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a45c765238e2ed7d7c608fc5bc4a6f88b642f2f01e70c0c23d2224dd21829d86" }, { url = "https://mirrors.aliyun.com/pypi/packages/bd/17/e756653095a083d8a37cbd816cb87148debcfcd920129b25f99dd8d04271/pandas-2.3.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c4fc4c21971a1a9f4bdb4c73978c7f7256caa3e62b323f70d6cb80db583350bc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/04/fd/74903979833db8390b73b3a8a7d30d146d710bd32703724dd9083950386f/pandas-2.3.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:ee15f284898e7b246df8087fc82b87b01686f98ee67d85a17b7ab44143a3a9a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/21/00/266d6b357ad5e6d3ad55093a7e8efc7dd245f5a842b584db9f30b0f0a287/pandas-2.3.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1611aedd912e1ff81ff41c745822980c49ce4a7907537be8692c8dbc31924593" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ca/05/d01ef80a7a3a12b2f8bbf16daba1e17c98a2f039cbc8e2f77a2c5a63d382/pandas-2.3.3-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d2cefc361461662ac48810cb14365a365ce864afe85ef1f447ff5a1e99ea81c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/15/b2/0e62f78c0c5ba7e3d2c5945a82456f4fac76c480940f805e0b97fcbc2f65/pandas-2.3.3-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee67acbbf05014ea6c763beb097e03cd629961c8a632075eeb34247120abcb4b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c5/33/dd70400631b62b9b29c3c93d2feee1d0964dc2bae2e5ad7a6c73a7f25325/pandas-2.3.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c46467899aaa4da076d5abc11084634e2d197e9460643dd455ac3db5856b24d6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d3/18/b5d48f55821228d0d2692b34fd5034bb185e854bdb592e9c640f6290e012/pandas-2.3.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6253c72c6a1d990a410bc7de641d34053364ef8bcd3126f7e7450125887dffe3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a6/3d/124ac75fcd0ecc09b8fdccb0246ef65e35b012030defb0e0eba2cbbbe948/pandas-2.3.3-cp314-cp314-win_amd64.whl", hash = "sha256:1b07204a219b3b7350abaae088f451860223a52cfb8a6c53358e7948735158e5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/9c/0e21c895c38a157e0faa1fb64587a9226d6dd46452cac4532d80c3c4a244/pandas-2.3.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:2462b1a365b6109d275250baaae7b760fd25c726aaca0054649286bcfbb3e8ec" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d7/82/b69a1c95df796858777b68fbe6a81d37443a33319761d7c652ce77797475/pandas-2.3.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0242fe9a49aa8b4d78a4fa03acb397a58833ef6199e9aa40a95f027bb3a1b6e7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f9/88/702bde3ba0a94b8c73a0181e05144b10f13f29ebfc2150c3a79062a8195d/pandas-2.3.3-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a21d830e78df0a515db2b3d2f5570610f5e6bd2e27749770e8bb7b524b89b450" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a4/1e/1bac1a839d12e6a82ec6cb40cda2edde64a2013a66963293696bbf31fbbb/pandas-2.3.3-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e3ebdb170b5ef78f19bfb71b0dc5dc58775032361fa188e814959b74d726dd5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/44/91/483de934193e12a3b1d6ae7c8645d083ff88dec75f46e827562f1e4b4da6/pandas-2.3.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d051c0e065b94b7a3cea50eb1ec32e912cd96dba41647eb24104b6c6c14c5788" }, - { url = "https://mirrors.aliyun.com/pypi/packages/70/44/5191d2e4026f86a2a109053e194d3ba7a31a2d10a9c2348368c63ed4e85a/pandas-2.3.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3869faf4bd07b3b66a9f462417d0ca3a9df29a9f6abd5d0d0dbab15dac7abe87" }, ] [[package]] @@ -2216,28 +1826,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/49/6b/00187a044f98255225f172de653941e61da37104a9ea60e4f6887717e2b5/pillow-11.3.0-cp313-cp313t-win32.whl", hash = "sha256:2a3117c06b8fb646639dce83694f2f9eac405472713fcb1ae887469c0d4f6788" }, { url = "https://mirrors.aliyun.com/pypi/packages/e8/5c/6caaba7e261c0d75bab23be79f1d06b5ad2a2ae49f028ccec801b0e853d6/pillow-11.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:857844335c95bea93fb39e0fa2726b4d9d758850b34075a7e3ff4f4fa3aa3b31" }, { url = "https://mirrors.aliyun.com/pypi/packages/f3/7e/b623008460c09a0cb38263c93b828c666493caee2eb34ff67f778b87e58c/pillow-11.3.0-cp313-cp313t-win_arm64.whl", hash = "sha256:8797edc41f3e8536ae4b10897ee2f637235c94f27404cac7297f7b607dd0716e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/73/f4/04905af42837292ed86cb1b1dabe03dce1edc008ef14c473c5c7e1443c5d/pillow-11.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d9da3df5f9ea2a89b81bb6087177fb1f4d1c7146d583a3fe5c672c0d94e55e12" }, - { url = "https://mirrors.aliyun.com/pypi/packages/41/b0/33d79e377a336247df6348a54e6d2a2b85d644ca202555e3faa0cf811ecc/pillow-11.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:0b275ff9b04df7b640c59ec5a3cb113eefd3795a8df80bac69646ef699c6981a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/49/2d/ed8bc0ab219ae8768f529597d9509d184fe8a6c4741a6864fea334d25f3f/pillow-11.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0743841cabd3dba6a83f38a92672cccbd69af56e3e91777b0ee7f4dba4385632" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b5/3d/b932bb4225c80b58dfadaca9d42d08d0b7064d2d1791b6a237f87f661834/pillow-11.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2465a69cf967b8b49ee1b96d76718cd98c4e925414ead59fdf75cf0fd07df673" }, - { url = "https://mirrors.aliyun.com/pypi/packages/09/b5/0487044b7c096f1b48f0d7ad416472c02e0e4bf6919541b111efd3cae690/pillow-11.3.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41742638139424703b4d01665b807c6468e23e699e8e90cffefe291c5832b027" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a8/2d/524f9318f6cbfcc79fbc004801ea6b607ec3f843977652fdee4857a7568b/pillow-11.3.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:93efb0b4de7e340d99057415c749175e24c8864302369e05914682ba642e5d77" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6f/d2/a9a4f280c6aefedce1e8f615baaa5474e0701d86dd6f1dede66726462bbd/pillow-11.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7966e38dcd0fa11ca390aed7c6f20454443581d758242023cf36fcb319b1a874" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fe/54/86b0cd9dbb683a9d5e960b66c7379e821a19be4ac5810e2e5a715c09a0c0/pillow-11.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:98a9afa7b9007c67ed84c57c9e0ad86a6000da96eaa638e4f8abe5b65ff83f0a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e7/95/88efcaf384c3588e24259c4203b909cbe3e3c2d887af9e938c2022c9dd48/pillow-11.3.0-cp314-cp314-win32.whl", hash = "sha256:02a723e6bf909e7cea0dac1b0e0310be9d7650cd66222a5f1c571455c0a45214" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2e/cc/934e5820850ec5eb107e7b1a72dd278140731c669f396110ebc326f2a503/pillow-11.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:a418486160228f64dd9e9efcd132679b7a02a5f22c982c78b6fc7dab3fefb635" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d6/e9/9c0a616a71da2a5d163aa37405e8aced9a906d574b4a214bede134e731bc/pillow-11.3.0-cp314-cp314-win_arm64.whl", hash = "sha256:155658efb5e044669c08896c0c44231c5e9abcaadbc5cd3648df2f7c0b96b9a6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1a/33/c88376898aff369658b225262cd4f2659b13e8178e7534df9e6e1fa289f6/pillow-11.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:59a03cdf019efbfeeed910bf79c7c93255c3d54bc45898ac2a4140071b02b4ae" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/70/d376247fb36f1844b42910911c83a02d5544ebd2a8bad9efcc0f707ea774/pillow-11.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f8a5827f84d973d8636e9dc5764af4f0cf2318d26744b3d902931701b0d46653" }, - { url = "https://mirrors.aliyun.com/pypi/packages/eb/1c/537e930496149fbac69efd2fc4329035bbe2e5475b4165439e3be9cb183b/pillow-11.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ee92f2fd10f4adc4b43d07ec5e779932b4eb3dbfbc34790ada5a6669bc095aa6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bd/57/80f53264954dcefeebcf9dae6e3eb1daea1b488f0be8b8fef12f79a3eb10/pillow-11.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c96d333dcf42d01f47b37e0979b6bd73ec91eae18614864622d9b87bbd5bbf36" }, - { url = "https://mirrors.aliyun.com/pypi/packages/70/ff/4727d3b71a8578b4587d9c276e90efad2d6fe0335fd76742a6da08132e8c/pillow-11.3.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c96f993ab8c98460cd0c001447bff6194403e8b1d7e149ade5f00594918128b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/05/ae/716592277934f85d3be51d7256f3636672d7b1abfafdc42cf3f8cbd4b4c8/pillow-11.3.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41342b64afeba938edb034d122b2dda5db2139b9a4af999729ba8818e0056477" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e7/bb/7fe6cddcc8827b01b1a9766f5fdeb7418680744f9082035bdbabecf1d57f/pillow-11.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:068d9c39a2d1b358eb9f245ce7ab1b5c3246c7c8c7d9ba58cfa5b43146c06e50" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8b/f5/06bfaa444c8e80f1a8e4bff98da9c83b37b5be3b1deaa43d27a0db37ef84/pillow-11.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a1bc6ba083b145187f648b667e05a2534ecc4b9f2784c2cbe3089e44868f2b9b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f0/77/bc6f92a3e8e6e46c0ca78abfffec0037845800ea38c73483760362804c41/pillow-11.3.0-cp314-cp314t-win32.whl", hash = "sha256:118ca10c0d60b06d006be10a501fd6bbdfef559251ed31b794668ed569c87e12" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4a/82/3a721f7d69dca802befb8af08b7c79ebcab461007ce1c18bd91a5d5896f9/pillow-11.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8924748b688aa210d79883357d102cd64690e56b923a186f35a82cbc10f997db" }, - { url = "https://mirrors.aliyun.com/pypi/packages/89/c7/5572fa4a3f45740eaab6ae86fcdf7195b55beac1371ac8c619d880cfe948/pillow-11.3.0-cp314-cp314t-win_arm64.whl", hash = "sha256:79ea0d14d3ebad43ec77ad5272e6ff9bba5b679ef73375ea760261207fa8e0aa" }, { url = "https://mirrors.aliyun.com/pypi/packages/9e/e3/6fa84033758276fb31da12e5fb66ad747ae83b93c67af17f8c6ff4cc8f34/pillow-11.3.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7c8ec7a017ad1bd562f93dbd8505763e688d388cde6e4a010ae1486916e713e6" }, { url = "https://mirrors.aliyun.com/pypi/packages/5b/ee/e8d2e1ab4892970b561e1ba96cbd59c0d28cf66737fc44abb2aec3795a4e/pillow-11.3.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9ab6ae226de48019caa8074894544af5b53a117ccb9d3b3dcb2871464c829438" }, { url = "https://mirrors.aliyun.com/pypi/packages/f2/6d/17f80f4e1f0761f02160fc433abd4109fa1548dcfdca46cfdadaf9efa565/pillow-11.3.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fe27fb049cdcca11f11a7bfda64043c37b30e6b91f10cb5bab275806c32f6ab3" }, @@ -2331,36 +1919,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/92/f7/1d4ec5841505f423469efbfc381d64b7b467438cd5a4bbcbb063f3b73d27/propcache-0.4.1-cp313-cp313t-win32.whl", hash = "sha256:2ad890caa1d928c7c2965b48f3a3815c853180831d0e5503d35cf00c472f4717" }, { url = "https://mirrors.aliyun.com/pypi/packages/48/f0/615c30622316496d2cbbc29f5985f7777d3ada70f23370608c1d3e081c1f/propcache-0.4.1-cp313-cp313t-win_amd64.whl", hash = "sha256:f7ee0e597f495cf415bcbd3da3caa3bd7e816b74d0d52b8145954c5e6fd3ff37" }, { url = "https://mirrors.aliyun.com/pypi/packages/fd/ca/6002e46eccbe0e33dcd4069ef32f7f1c9e243736e07adca37ae8c4830ec3/propcache-0.4.1-cp313-cp313t-win_arm64.whl", hash = "sha256:929d7cbe1f01bb7baffb33dc14eb5691c95831450a26354cd210a8155170c93a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8e/5c/bca52d654a896f831b8256683457ceddd490ec18d9ec50e97dfd8fc726a8/propcache-0.4.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12" }, - { url = "https://mirrors.aliyun.com/pypi/packages/65/9b/03b04e7d82a5f54fb16113d839f5ea1ede58a61e90edf515f6577c66fa8f/propcache-0.4.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/fa/89a8ef0468d5833a23fff277b143d0573897cf75bd56670a6d28126c7d68/propcache-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded" }, - { url = "https://mirrors.aliyun.com/pypi/packages/86/bd/47816020d337f4a746edc42fe8d53669965138f39ee117414c7d7a340cfe/propcache-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/f6/c5fa1357cc9748510ee55f37173eb31bfde6d94e98ccd9e6f033f2fc06e1/propcache-0.4.1-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/1e/e5889652a7c4a3846683401a48f0f2e5083ce0ec1a8a5221d8058fbd1adf/propcache-0.4.1-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/f2/889ad4b2408f72fe1a4f6a19491177b30ea7bf1a0fd5f17050ca08cfc882/propcache-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/27/73/033d63069b57b0812c8bd19f311faebeceb6ba31b8f32b73432d12a0b826/propcache-0.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dc/89/ce24f3dc182630b4e07aa6d15f0ff4b14ed4b9955fae95a0b54c58d66c05/propcache-0.4.1-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a9/24/ef0d5fd1a811fb5c609278d0209c9f10c35f20581fcc16f818da959fc5b4/propcache-0.4.1-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/02/98ec20ff5546f68d673df2f7a69e8c0d076b5abd05ca882dc7ee3a83653d/propcache-0.4.1-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a0/87/492694f76759b15f0467a2a93ab68d32859672b646aa8a04ce4864e7932d/propcache-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ee/36/66367de3575db1d2d3f3d177432bd14ee577a39d3f5d1b3d5df8afe3b6e2/propcache-0.4.1-cp314-cp314-win32.whl", hash = "sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0c/2a/a758b47de253636e1b8aef181c0b4f4f204bf0dd964914fb2af90a95b49b/propcache-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153" }, - { url = "https://mirrors.aliyun.com/pypi/packages/34/5e/63bd5896c3fec12edcbd6f12508d4890d23c265df28c74b175e1ef9f4f3b/propcache-0.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992" }, - { url = "https://mirrors.aliyun.com/pypi/packages/99/85/9ff785d787ccf9bbb3f3106f79884a130951436f58392000231b4c737c80/propcache-0.4.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/90/85/2431c10c8e7ddb1445c1f7c4b54d886e8ad20e3c6307e7218f05922cad67/propcache-0.4.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393" }, - { url = "https://mirrors.aliyun.com/pypi/packages/01/20/b0972d902472da9bcb683fa595099911f4d2e86e5683bcc45de60dd05dc3/propcache-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/e3/7dc89f4f21e8f99bad3d5ddb3a3389afcf9da4ac69e3deb2dcdc96e74169/propcache-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/20/67/89800c8352489b21a8047c773067644e3897f02ecbbd610f4d46b7f08612/propcache-0.4.1-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/a1/b52b055c766a54ce6d9c16d9aca0cad8059acd9637cdf8aa0222f4a026ef/propcache-0.4.1-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/c8/33cee30bd890672c63743049f3c9e4be087e6780906bfc3ec58528be59c1/propcache-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0c/b1/8f08a143b204b418285c88b83d00edbd61afbc2c6415ffafc8905da7038b/propcache-0.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89" }, - { url = "https://mirrors.aliyun.com/pypi/packages/cf/12/96e4664c82ca2f31e1c8dff86afb867348979eb78d3cb8546a680287a1e9/propcache-0.4.1-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726" }, - { url = "https://mirrors.aliyun.com/pypi/packages/18/ed/e7a9cfca28133386ba52278136d42209d3125db08d0a6395f0cba0c0285c/propcache-0.4.1-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/76/16d8bf65e8845dd62b4e2b57444ab81f07f40caa5652b8969b87ddcf2ef6/propcache-0.4.1-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e7/70/c99e9edb5d91d5ad8a49fa3c1e8285ba64f1476782fed10ab251ff413ba1/propcache-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455" }, - { url = "https://mirrors.aliyun.com/pypi/packages/08/02/87b25304249a35c0915d236575bc3574a323f60b47939a2262b77632a3ee/propcache-0.4.1-cp314-cp314t-win32.whl", hash = "sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85" }, - { url = "https://mirrors.aliyun.com/pypi/packages/cb/ef/3c6ecf8b317aa982f309835e8f96987466123c6e596646d4e6a1dfcd080f/propcache-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c4/2d/346e946d4951f37eca1e4f55be0f0174c52cd70720f84029b02f296f4a38/propcache-0.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9" }, { url = "https://mirrors.aliyun.com/pypi/packages/5b/5a/bc7b4a4ef808fa59a816c17b20c4bef6884daebbdf627ff2a161da67da19/propcache-0.4.1-py3-none-any.whl", hash = "sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237" }, ] @@ -2391,12 +1949,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312" }, { url = "https://mirrors.aliyun.com/pypi/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b" }, { url = "https://mirrors.aliyun.com/pypi/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841" }, { url = "https://mirrors.aliyun.com/pypi/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486" }, { url = "https://mirrors.aliyun.com/pypi/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979" }, { url = "https://mirrors.aliyun.com/pypi/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9" }, @@ -2473,34 +2025,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36" }, { url = "https://mirrors.aliyun.com/pypi/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11" }, { url = "https://mirrors.aliyun.com/pypi/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14" }, - { url = "https://mirrors.aliyun.com/pypi/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66" }, - { url = "https://mirrors.aliyun.com/pypi/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375" }, - { url = "https://mirrors.aliyun.com/pypi/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612" }, - { url = "https://mirrors.aliyun.com/pypi/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660" }, - { url = "https://mirrors.aliyun.com/pypi/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa" }, - { url = "https://mirrors.aliyun.com/pypi/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008" }, { url = "https://mirrors.aliyun.com/pypi/packages/11/72/90fda5ee3b97e51c494938a4a44c3a35a9c96c19bba12372fb9c634d6f57/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034" }, { url = "https://mirrors.aliyun.com/pypi/packages/1f/53/8942f884fa33f50794f119012dc6a1a02ac43a56407adaac20463df8e98f/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c" }, { url = "https://mirrors.aliyun.com/pypi/packages/79/c8/ecb9ed9cd942bce09fc888ee960b52654fbdbede4ba6c2d6e0d3b1d8b49c/pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2" }, @@ -2696,24 +2220,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26" }, { url = "https://mirrors.aliyun.com/pypi/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c" }, { url = "https://mirrors.aliyun.com/pypi/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310" }, - { url = "https://mirrors.aliyun.com/pypi/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788" }, - { url = "https://mirrors.aliyun.com/pypi/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35" }, - { url = "https://mirrors.aliyun.com/pypi/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065" }, - { url = "https://mirrors.aliyun.com/pypi/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b" }, ] [[package]] @@ -2862,22 +2368,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/02/94/9f46966fa042b5d57c8cd641045372b4e0df0047dd400e77ea9952674110/scikit_image-0.26.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:20ef4a155e2e78b8ab973998e04d8a361d49d719e65412405f4dadd9155a61d9" }, { url = "https://mirrors.aliyun.com/pypi/packages/5d/b4/2840fe38f10057f40b1c9f8fb98a187a370936bf144a4ac23452c5ef1baf/scikit_image-0.26.0-cp313-cp313t-win_amd64.whl", hash = "sha256:c9087cf7d0e7f33ab5c46d2068d86d785e70b05400a891f73a13400f1e1faf6a" }, { url = "https://mirrors.aliyun.com/pypi/packages/22/ba/73b6ca70796e71f83ab222690e35a79612f0117e5aaf167151b7d46f5f2c/scikit_image-0.26.0-cp313-cp313t-win_arm64.whl", hash = "sha256:27d58bc8b2acd351f972c6508c1b557cfed80299826080a4d803dd29c51b707e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/51/44/6b744f92b37ae2833fd423cce8f806d2368859ec325a699dc30389e090b9/scikit_image-0.26.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:63af3d3a26125f796f01052052f86806da5b5e54c6abef152edb752683075a9c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/40/f5/83590d9355191f86ac663420fec741b82cc547a4afe7c4c1d986bf46e4db/scikit_image-0.26.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ce00600cd70d4562ed59f80523e18cdcc1fae0e10676498a01f73c255774aefd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/72/48/253e7cf5aee6190459fe136c614e2cbccc562deceb4af96e0863f1b8ee29/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6381edf972b32e4f54085449afde64365a57316637496c1325a736987083e2ab" }, - { url = "https://mirrors.aliyun.com/pypi/packages/73/c3/cec6a3cbaadfdcc02bd6ff02f3abfe09eaa7f4d4e0a525a1e3a3f4bce49c/scikit_image-0.26.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6624a76c6085218248154cc7e1500e6b488edcd9499004dd0d35040607d7505" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d4/0d/39a776f675d24164b3a267aa0db9f677a4cb20127660d8bf4fd7fef66817/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f775f0e420faac9c2aa6757135f4eb468fb7b70e0b67fa77a5e79be3c30ee331" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ee/25/2514df226bbcedfe9b2caafa1ba7bc87231a0c339066981b182b08340e06/scikit_image-0.26.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede4d6d255cc5da9faeb2f9ba7fedbc990abbc652db429f40a16b22e770bb578" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8d/5b/0671dc91c0c79340c3fe202f0549c7d3681eb7640fe34ab68a5f090a7c7f/scikit_image-0.26.0-cp314-cp314-win_amd64.whl", hash = "sha256:0660b83968c15293fd9135e8d860053ee19500d52bf55ca4fb09de595a1af650" }, - { url = "https://mirrors.aliyun.com/pypi/packages/65/08/7c4cb59f91721f3de07719085212a0b3962e3e3f2d1818cbac4eeb1ea53e/scikit_image-0.26.0-cp314-cp314-win_arm64.whl", hash = "sha256:b8d14d3181c21c11170477a42542c1addc7072a90b986675a71266ad17abc37f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/49/41/65c4258137acef3d73cb561ac55512eacd7b30bb4f4a11474cad526bc5db/scikit_image-0.26.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:cde0bbd57e6795eba83cb10f71a677f7239271121dc950bc060482834a668ad1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e7/32/76971f8727b87f1420a962406388a50e26667c31756126444baf6668f559/scikit_image-0.26.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:163e9afb5b879562b9aeda0dd45208a35316f26cc7a3aed54fd601604e5cf46f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/37/0d/996febd39f757c40ee7b01cdb861867327e5c8e5f595a634e8201462d958/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:724f79fd9b6cb6f4a37864fe09f81f9f5d5b9646b6868109e1b100d1a7019e59" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/b4/612d354f946c9600e7dea012723c11d47e8d455384e530f6daaaeb9bf62c/scikit_image-0.26.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3268f13310e6857508bd87202620df996199a016a1d281b309441d227c822394" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0a/6e/26c00b466e06055a086de2c6e2145fe189ccdc9a1d11ccc7de020f2591ad/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:fac96a1f9b06cd771cbbb3cd96c5332f36d4efd839b1d8b053f79e5887acde62" }, - { url = "https://mirrors.aliyun.com/pypi/packages/47/88/00a90402e1775634043c2a0af8a3c76ad450866d9fa444efcc43b553ba2d/scikit_image-0.26.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2c1e7bd342f43e7a97e571b3f03ba4c1293ea1a35c3f13f41efdc8a81c1dc8f2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/da/ca/918d8d306bd43beacff3b835c6d96fac0ae64c0857092f068b88db531a7c/scikit_image-0.26.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b702c3bb115e1dcf4abf5297429b5c90f2189655888cbed14921f3d26f81d3a4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dc/cd/4da01329b5a8d47ff7ec3c99a2b02465a8017b186027590dc7425cee0b56/scikit_image-0.26.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0608aa4a9ec39e0843de10d60edb2785a30c1c47819b67866dd223ebd149acaf" }, ] [[package]] @@ -2916,18 +2406,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb" }, { url = "https://mirrors.aliyun.com/pypi/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702" }, { url = "https://mirrors.aliyun.com/pypi/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde" }, - { url = "https://mirrors.aliyun.com/pypi/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c" }, ] [[package]] @@ -2979,26 +2457,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/90/b8/4f0f5cf0c5ea4d7548424e6533e6b17d164f34a6e2fb2e43ffebb6697b06/scipy-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04" }, { url = "https://mirrors.aliyun.com/pypi/packages/f9/cc/2bd59140ed3b2fa2882fb15da0a9cb1b5a6443d67cfd0d98d4cec83a57ec/scipy-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0" }, { url = "https://mirrors.aliyun.com/pypi/packages/13/1b/c87cc44a0d2c7aaf0f003aef2904c3d097b422a96c7e7c07f5efd9073c1b/scipy-1.17.0-cp313-cp313t-win_arm64.whl", hash = "sha256:30509da9dbec1c2ed8f168b8d8aa853bc6723fede1dbc23c7d43a56f5ab72a67" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1a/2d/51006cd369b8e7879e1c630999a19d1fbf6f8b5ed3e33374f29dc87e53b3/scipy-1.17.0-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d6/2e/2349458c3ce445f53a6c93d4386b1c4c5c0c540917304c01222ff95ff317/scipy-1.17.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5e/7c/df525fbfa77b878d1cfe625249529514dc02f4fd5f45f0f6295676a76528/scipy-1.17.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467" }, - { url = "https://mirrors.aliyun.com/pypi/packages/33/11/fcf9d43a7ed1234d31765ec643b0515a85a30b58eddccc5d5a4d12b5f194/scipy-1.17.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/5c/ea5d239cda2dd3d31399424967a24d556cf409fbea7b5b21412b0fd0a44f/scipy-1.17.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b8/7e/8c917cc573310e5dc91cbeead76f1b600d3fb17cf0969db02c9cf92e3cfa/scipy-1.17.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c5/43/176c0c3c07b3f7df324e7cdd933d3e2c4898ca202b090bd5ba122f9fe270/scipy-1.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/44/8c/d1f5f4b491160592e7f084d997de53a8e896a3ac01cd07e59f43ca222744/scipy-1.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9f/ec/42a6657f8d2d087e750e9a5dde0b481fd135657f09eaf1cf5688bb23c338/scipy-1.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061" }, - { url = "https://mirrors.aliyun.com/pypi/packages/27/58/6b89a6afd132787d89a362d443a7bddd511b8f41336a1ae47f9e4f000dc4/scipy-1.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:9244608d27eafe02b20558523ba57f15c689357c85bdcfe920b1828750aa26eb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e9/01/f58916b9d9ae0112b86d7c3b10b9e685625ce6e8248df139d0fcb17f7397/scipy-1.17.0-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/59/8e/2912a87f94a7d1f8b38aabc0faf74b82d3b6c9e22be991c49979f0eceed8/scipy-1.17.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bd/1c/874137a52dddab7d5d595c1887089a2125d27d0601fce8c0026a24a92a0b/scipy-1.17.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3f/f0/7518d171cb735f6400f4576cf70f756d5b419a07fe1867da34e2c2c9c11b/scipy-1.17.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7c/74/3498563a2c619e8a3ebb4d75457486c249b19b5b04a30600dfd9af06bea5/scipy-1.17.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/d1/7b50cedd8c6c9d6f706b4b36fa8544d829c712a75e370f763b318e9638c1/scipy-1.17.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/82/a2d684dfddb87ba1b3ea325df7c3293496ee9accb3a19abe9429bce94755/scipy-1.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ef/5e/e565bd73991d42023eb82bb99e51c5b3d9e2c588ca9d4b3e2cc1d3ca62a6/scipy-1.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/58/a8/a66a75c3d8f1fb2b83f66007d6455a06a6f6cf5618c3dc35bc9b69dd096e/scipy-1.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088" }, - { url = "https://mirrors.aliyun.com/pypi/packages/56/a5/df8f46ef7da168f1bc52cd86e09a9de5c6f19cc1da04454d51b7d4f43408/scipy-1.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:031121914e295d9791319a1875444d55079885bbae5bdc9c5e0f2ee5f09d34ff" }, ] [[package]] @@ -3293,17 +2751,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764" }, { url = "https://mirrors.aliyun.com/pypi/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b" }, { url = "https://mirrors.aliyun.com/pypi/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366" }, - { url = "https://mirrors.aliyun.com/pypi/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863" }, - { url = "https://mirrors.aliyun.com/pypi/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330" }, { url = "https://mirrors.aliyun.com/pypi/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e" }, ] @@ -3432,24 +2879,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86" }, { url = "https://mirrors.aliyun.com/pypi/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87" }, { url = "https://mirrors.aliyun.com/pypi/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66" }, - { url = "https://mirrors.aliyun.com/pypi/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702" }, - { url = "https://mirrors.aliyun.com/pypi/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9" }, - { url = "https://mirrors.aliyun.com/pypi/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087" }, - { url = "https://mirrors.aliyun.com/pypi/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4" }, { url = "https://mirrors.aliyun.com/pypi/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a" }, ] @@ -3503,14 +2932,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/54/fd/b207d1c525cb570ef47f3e9f836b154685011fce11a2f444ba8a4084d042/torch-2.10.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:6021db85958db2f07ec94e1bc77212721ba4920c12a18dc552d2ae36a3eb163f" }, { url = "https://mirrors.aliyun.com/pypi/packages/36/53/0197f868c75f1050b199fe58f9bf3bf3aecac9b4e85cc9c964383d745403/torch-2.10.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff43db38af76fda183156153983c9a096fc4c78d0cd1e07b14a2314c7f01c2c8" }, { url = "https://mirrors.aliyun.com/pypi/packages/0e/13/e76b4d9c160e89fff48bf16b449ea324bda84745d2ab30294c37c2434c0d/torch-2.10.0-cp313-none-macosx_11_0_arm64.whl", hash = "sha256:cdf2a523d699b70d613243211ecaac14fe9c5df8a0b0a9c02add60fb2a413e0f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4f/93/716b5ac0155f1be70ed81bacc21269c3ece8dba0c249b9994094110bfc51/torch-2.10.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:bf0d9ff448b0218e0433aeb198805192346c4fd659c852370d5cc245f602a06a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/69/2b/51e663ff190c9d16d4a8271203b71bc73a16aa7619b9f271a69b9d4a936b/torch-2.10.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:233aed0659a2503b831d8a67e9da66a62c996204c0bba4f4c442ccc0c68a3f60" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5e/cd/4b95ef7f293b927c283db0b136c42be91c8ec6845c44de0238c8c23bdc80/torch-2.10.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:682497e16bdfa6efeec8cde66531bc8d1fbbbb4d8788ec6173c089ed3cc2bfe5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/56/97/078a007208f8056d88ae43198833469e61a0a355abc0b070edd2c085eb9a/torch-2.10.0-cp314-cp314-win_amd64.whl", hash = "sha256:6528f13d2a8593a1a412ea07a99812495bec07e9224c28b2a25c0a30c7da025c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d8/94/71994e7d0d5238393df9732fdab607e37e2b56d26a746cb59fdb415f8966/torch-2.10.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:f5ab4ba32383061be0fb74bda772d470140a12c1c3b58a0cfbf3dae94d164c28" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e2/65/1a05346b418ea8ccd10360eef4b3e0ce688fba544e76edec26913a8d0ee0/torch-2.10.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:716b01a176c2a5659c98f6b01bf868244abdd896526f1c692712ab36dbaf9b63" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1d/b9/5f6f9d9e859fc3235f60578fa64f52c9c6e9b4327f0fe0defb6de5c0de31/torch-2.10.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:d8f5912ba938233f86361e891789595ff35ca4b4e2ac8fe3670895e5976731d6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/66/4d/35352043ee0eaffdeff154fad67cd4a31dbed7ff8e3be1cc4549717d6d51/torch-2.10.0-cp314-cp314t-win_amd64.whl", hash = "sha256:71283a373f0ee2c89e0f0d5f446039bdabe8dbc3c9ccf35f0f784908b0acd185" }, ] [[package]] @@ -3554,14 +2975,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/28/cc/2103149761fdb4eaed58a53e8437b2d716d48f05174fab1d9fcf1e2a2244/torchvision-0.25.0-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:146d02c9876858420adf41f3189fe90e3d6a409cbfa65454c09f25fb33bf7266" }, { url = "https://mirrors.aliyun.com/pypi/packages/76/ad/f4c985ad52ddd3b22711c588501be1b330adaeaf6850317f66751711b78c/torchvision-0.25.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:c4d395cb2c4a2712f6eb93a34476cdf7aae74bb6ea2ea1917f858e96344b00aa" }, { url = "https://mirrors.aliyun.com/pypi/packages/63/cc/0ea68b5802e5e3c31f44b307e74947bad5a38cc655231d845534ed50ddb8/torchvision-0.25.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5e6b449e9fa7d642142c0e27c41e5a43b508d57ed8e79b7c0a0c28652da8678c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9e/1f/fa839532660e2602b7e704d65010787c5bb296258b44fa8b9c1cd6175e7d/torchvision-0.25.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:620a236288d594dcec7634c754484542dc0a5c1b0e0b83a34bda5e91e9b7c3a1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/ed/d51889da7ceaf5ff7a0574fb28f9b6b223df19667265395891f81b364ab3/torchvision-0.25.0-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b5e7f50002a8145a98c5694a018e738c50e2972608310c7e88e1bd4c058f6ce" }, - { url = "https://mirrors.aliyun.com/pypi/packages/90/a5/f93fcffaddd8f12f9e812256830ec9c9ca65abbf1bc369379f9c364d1ff4/torchvision-0.25.0-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:632db02300e83793812eee4f61ae6a2686dab10b4cfd628b620dc47747aa9d03" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1f/eb/d0096eed5690d962853213f2ee00d91478dfcb586b62dbbb449fb8abc3a6/torchvision-0.25.0-cp314-cp314-win_amd64.whl", hash = "sha256:d1abd5ed030c708f5dbf4812ad5f6fbe9384b63c40d6bd79f8df41a4a759a917" }, - { url = "https://mirrors.aliyun.com/pypi/packages/97/36/96374a4c7ab50dea9787ce987815614ccfe988a42e10ac1a2e3e5b60319a/torchvision-0.25.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ad9a8a5877782944d99186e4502a614770fe906626d76e9cd32446a0ac3075f2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b5/e2/7abb10a867db79b226b41da419b63b69c0bd5b82438c4a4ed50e084c552f/torchvision-0.25.0-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:40a122c3cf4d14b651f095e0f672b688dde78632783fc5cd3d4d5e4f6a828563" }, - { url = "https://mirrors.aliyun.com/pypi/packages/08/e6/0927784e6ffc340b6676befde1c60260bd51641c9c574b9298d791a9cda4/torchvision-0.25.0-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:846890161b825b38aa85fc37fb3ba5eea74e7091ff28bab378287111483b6443" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b6/37/e7ca4ec820d434c0f23f824eb29f0676a0c3e7a118f1514f5b949c3356da/torchvision-0.25.0-cp314-cp314t-win_amd64.whl", hash = "sha256:f07f01d27375ad89d72aa2b3f2180f07da95dd9d2e4c758e015c0acb2da72977" }, ] [[package]] @@ -3585,8 +2998,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/ab/a8/cdf8b3e4c98132f965f88c2313a4b493266832ad47fb52f23d14d4f86bb5/triton-3.6.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74caf5e34b66d9f3a429af689c1c7128daba1d8208df60e81106b115c00d6fca" }, { url = "https://mirrors.aliyun.com/pypi/packages/f9/0b/37d991d8c130ce81a8728ae3c25b6e60935838e9be1b58791f5997b24a54/triton-3.6.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:10c7f76c6e72d2ef08df639e3d0d30729112f47a56b0c81672edc05ee5116ac9" }, { url = "https://mirrors.aliyun.com/pypi/packages/35/f8/9c66bfc55361ec6d0e4040a0337fb5924ceb23de4648b8a81ae9d33b2b38/triton-3.6.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d002e07d7180fd65e622134fbd980c9a3d4211fb85224b56a0a0efbd422ab72f" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/3d/9e7eee57b37c80cec63322c0231bb6da3cfe535a91d7a4d64896fcb89357/triton-3.6.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a17a5d5985f0ac494ed8a8e54568f092f7057ef60e1b0fa09d3fd1512064e803" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f6/56/6113c23ff46c00aae423333eb58b3e60bdfe9179d542781955a5e1514cb3/triton-3.6.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:46bd1c1af4b6704e554cad2eeb3b0a6513a980d470ccfa63189737340c7746a7" }, ] [[package]] @@ -3712,18 +3123,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/15/c0/0be24758891ef825f2065cd5db8741aaddabe3e248ee6acc5e8a80f04005/uvloop-0.22.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0530a5fbad9c9e4ee3f2b33b148c6a64d47bbad8000ea63704fa8260f4cf728e" }, { url = "https://mirrors.aliyun.com/pypi/packages/d2/53/8369e5219a5855869bcee5f4d317f6da0e2c669aecf0ef7d371e3d084449/uvloop-0.22.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bc5ef13bbc10b5335792360623cc378d52d7e62c2de64660616478c32cd0598e" }, { url = "https://mirrors.aliyun.com/pypi/packages/f8/ba/d69adbe699b768f6b29a5eec7b47dd610bd17a69de51b251126a801369ea/uvloop-0.22.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1f38ec5e3f18c8a10ded09742f7fb8de0108796eb673f30ce7762ce1b8550cad" }, - { url = "https://mirrors.aliyun.com/pypi/packages/90/cd/b62bdeaa429758aee8de8b00ac0dd26593a9de93d302bff3d21439e9791d/uvloop-0.22.1-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3879b88423ec7e97cd4eba2a443aa26ed4e59b45e6b76aabf13fe2f27023a142" }, - { url = "https://mirrors.aliyun.com/pypi/packages/0d/f8/a132124dfda0777e489ca86732e85e69afcd1ff7686647000050ba670689/uvloop-0.22.1-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:4baa86acedf1d62115c1dc6ad1e17134476688f08c6efd8a2ab076e815665c74" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a3/94/94af78c156f88da4b3a733773ad5ba0b164393e357cc4bd0ab2e2677a7d6/uvloop-0.22.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:297c27d8003520596236bdb2335e6b3f649480bd09e00d1e3a99144b691d2a35" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b5/35/60249e9fd07b32c665192cec7af29e06c7cd96fa1d08b84f012a56a0b38e/uvloop-0.22.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1955d5a1dd43198244d47664a5858082a3239766a839b2102a269aaff7a4e25" }, - { url = "https://mirrors.aliyun.com/pypi/packages/02/62/67d382dfcb25d0a98ce73c11ed1a6fba5037a1a1d533dcbb7cab033a2636/uvloop-0.22.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b31dc2fccbd42adc73bc4e7cdbae4fc5086cf378979e53ca5d0301838c5682c6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f0/7a/f1171b4a882a5d13c8b7576f348acfe6074d72eaf52cccef752f748d4a9f/uvloop-0.22.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93f617675b2d03af4e72a5333ef89450dfaa5321303ede6e67ba9c9d26878079" }, - { url = "https://mirrors.aliyun.com/pypi/packages/79/7b/b01414f31546caf0919da80ad57cbfe24c56b151d12af68cee1b04922ca8/uvloop-0.22.1-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:37554f70528f60cad66945b885eb01f1bb514f132d92b6eeed1c90fd54ed6289" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d4/31/0bb232318dd838cad3fa8fb0c68c8b40e1145b32025581975e18b11fab40/uvloop-0.22.1-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b76324e2dc033a0b2f435f33eb88ff9913c156ef78e153fb210e03c13da746b3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/42/38/c9b09f3271a7a723a5de69f8e237ab8e7803183131bc57c890db0b6bb872/uvloop-0.22.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:badb4d8e58ee08dad957002027830d5c3b06aea446a6a3744483c2b3b745345c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c1/37/945b4ca0ac27e3dc4952642d4c900edd030b3da6c9634875af6e13ae80e5/uvloop-0.22.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b91328c72635f6f9e0282e4a57da7470c7350ab1c9f48546c0f2866205349d21" }, - { url = "https://mirrors.aliyun.com/pypi/packages/97/cc/48d232f33d60e2e2e0b42f4e73455b146b76ebe216487e862700457fbf3c/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:daf620c2995d193449393d6c62131b3fbd40a63bf7b307a1527856ace637fe88" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/16/c1fd27e9549f3c4baf1dc9c20c456cd2f822dbf8de9f463824b0c0357e06/uvloop-0.22.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6cde23eeda1a25c75b2e07d39970f3374105d5eafbaab2a4482be82f272d5a5e" }, ] [[package]] @@ -3813,29 +3212,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77" }, { url = "https://mirrors.aliyun.com/pypi/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef" }, { url = "https://mirrors.aliyun.com/pypi/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b2/7e/5643bfff5acb6539b18483128fdc0ef2cccc94a5b8fbda130c823e8ed636/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7365b92c2e69ee952902e8f70f3ba6360d0d596d9299d55d7d386df84b6941fb" }, - { url = "https://mirrors.aliyun.com/pypi/packages/51/2e/c410993ba5025a9f9357c376f48976ef0e1b1aefb73b97a5ae01a5972755/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bfff9740c69c0e4ed32416f013f3c45e2ae42ccedd1167ef2d805c000b6c71a5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8e/a4/2df3b404469122e8680f0fcd06079317e48db58a2da2950fb45020947734/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b27cf2eb1dda37b2089e3907d8ea92922b673c0c427886d4edc6b94d8dfe5db3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ea/84/4587ba5b1f267167ee715b7f66e6382cca6938e0a4b870adad93e44747e6/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:526e86aced14a65a5b0ec50827c745597c782ff46b571dbfe46192ab9e0b3c33" }, - { url = "https://mirrors.aliyun.com/pypi/packages/6a/0f/c6988c91d06e93cd0bb3d4a808bcf32375ca1904609835c3031799e3ecae/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04e78dd0b6352db95507fd8cb46f39d185cf8c74e4cf1e4fbad1d3df96faf510" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05" }, - { url = "https://mirrors.aliyun.com/pypi/packages/98/e0/8c9bdba88af756a2fce230dd365fab2baf927ba42cd47521ee7498fd5211/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:74d5012b7630714b66be7b7b7a78855ef7ad58e8650c73afc4c076a1f480a8d6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/2a/84/a95db05354bf2d19e438520d92a8ca475e578c647f78f53197f5a2f17aaf/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe85cb3201c7d380d3d0b90e63d520f15d6afe217165d7f98c9c649654db81" }, - { url = "https://mirrors.aliyun.com/pypi/packages/1d/ce/d8acdc8de545de995c339be67711e474c77d643555a9bb74a9334252bd55/watchfiles-1.1.1-cp314-cp314-win32.whl", hash = "sha256:3fa0b59c92278b5a7800d3ee7733da9d096d4aabcfabb9a928918bd276ef9b9b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c4/c9/a74487f72d0451524be827e8edec251da0cc1fcf111646a511ae752e1a3d/watchfiles-1.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:c2047d0b6cea13b3316bdbafbfa0c4228ae593d995030fda39089d36e64fc03a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/b8/8ac000702cdd496cdce998c6f4ee0ca1f15977bba51bdf07d872ebdfc34c/watchfiles-1.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:842178b126593addc05acf6fce960d28bc5fae7afbaa2c6c1b3a7b9460e5be02" }, - { url = "https://mirrors.aliyun.com/pypi/packages/47/a8/e3af2184707c29f0f14b1963c0aace6529f9d1b8582d5b99f31bbf42f59e/watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:88863fbbc1a7312972f1c511f202eb30866370ebb8493aef2812b9ff28156a21" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c0/ec/e47e307c2f4bd75f9f9e8afbe3876679b18e1bcec449beca132a1c5ffb2d/watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:55c7475190662e202c08c6c0f4d9e345a29367438cf8e8037f3155e10a88d5a5" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d5/a0/ad235642118090f66e7b2f18fd5c42082418404a79205cdfca50b6309c13/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f53fa183d53a1d7a8852277c92b967ae99c2d4dcee2bfacff8868e6e30b15f7" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/85/97fa10fd5ff3332ae17e7e40e20784e419e28521549780869f1413742e9d/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6aae418a8b323732fa89721d86f39ec8f092fc2af67f4217a2b07fd3e93c6101" }, - { url = "https://mirrors.aliyun.com/pypi/packages/47/c2/9059c2e8966ea5ce678166617a7f75ecba6164375f3b288e50a40dc6d489/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f096076119da54a6080e8920cbdaac3dbee667eb91dcc5e5b78840b87415bd44" }, - { url = "https://mirrors.aliyun.com/pypi/packages/94/44/d90a9ec8ac309bc26db808a13e7bfc0e4e78b6fc051078a554e132e80160/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/95/68/4e3479b20ca305cfc561db3ed207a8a1c745ee32bf24f2026a129d0ddb6e/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a55f3e9e493158d7bfdb60a1165035f1cf7d320914e7b7ea83fe22c6023b58fc" }, - { url = "https://mirrors.aliyun.com/pypi/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01" }, { url = "https://mirrors.aliyun.com/pypi/packages/d3/8e/e500f8b0b77be4ff753ac94dc06b33d8f0d839377fee1b78e8c8d8f031bf/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db476ab59b6765134de1d4fe96a1a9c96ddf091683599be0f26147ea1b2e4b88" }, { url = "https://mirrors.aliyun.com/pypi/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336" }, { url = "https://mirrors.aliyun.com/pypi/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24" }, @@ -3875,24 +3251,6 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f" }, { url = "https://mirrors.aliyun.com/pypi/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a" }, { url = "https://mirrors.aliyun.com/pypi/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3" }, - { url = "https://mirrors.aliyun.com/pypi/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244" }, - { url = "https://mirrors.aliyun.com/pypi/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8" }, - { url = "https://mirrors.aliyun.com/pypi/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944" }, - { url = "https://mirrors.aliyun.com/pypi/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6" }, - { url = "https://mirrors.aliyun.com/pypi/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd" }, { url = "https://mirrors.aliyun.com/pypi/packages/72/07/c98a68571dcf256e74f1f816b8cc5eae6eb2d3d5cfa44d37f801619d9166/websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d" }, { url = "https://mirrors.aliyun.com/pypi/packages/7e/52/93e166a81e0305b33fe416338be92ae863563fe7bce446b0f687b9df5aea/websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03" }, { url = "https://mirrors.aliyun.com/pypi/packages/56/0c/2dbf513bafd24889d33de2ff0368190a0e69f37bcfa19009ef819fe4d507/websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da" }, @@ -3988,37 +3346,5 @@ wheels = [ { url = "https://mirrors.aliyun.com/pypi/packages/e0/e5/11f140a58bf4c6ad7aca69a892bff0ee638c31bea4206748fc0df4ebcb3a/yarl-1.22.0-cp313-cp313t-win32.whl", hash = "sha256:1834bb90991cc2999f10f97f5f01317f99b143284766d197e43cd5b45eb18d03" }, { url = "https://mirrors.aliyun.com/pypi/packages/31/74/8b74bae38ed7fe6793d0c15a0c8207bbb819cf287788459e5ed230996cdd/yarl-1.22.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ff86011bd159a9d2dfc89c34cfd8aff12875980e3bd6a39ff097887520e60249" }, { url = "https://mirrors.aliyun.com/pypi/packages/69/66/991858aa4b5892d57aef7ee1ba6b4d01ec3b7eb3060795d34090a3ca3278/yarl-1.22.0-cp313-cp313t-win_arm64.whl", hash = "sha256:7861058d0582b847bc4e3a4a4c46828a410bca738673f35a29ba3ca5db0b473b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/46/b3/e20ef504049f1a1c54a814b4b9bed96d1ac0e0610c3b4da178f87209db05/yarl-1.22.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e4/04/3532d990fdbab02e5ede063676b5c4260e7f3abea2151099c2aa745acc4c/yarl-1.22.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683" }, - { url = "https://mirrors.aliyun.com/pypi/packages/11/63/ff458113c5c2dac9a9719ac68ee7c947cb621432bcf28c9972b1c0e83938/yarl-1.22.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/a7/bc/315a56aca762d44a6aaaf7ad253f04d996cb6b27bad34410f82d76ea8038/yarl-1.22.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/3f/3f/08e9b826ec2e099ea6e7c69a61272f4f6da62cb5b1b63590bb80ca2e4a40/yarl-1.22.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590" }, - { url = "https://mirrors.aliyun.com/pypi/packages/e3/9f/90360108e3b32bd76789088e99538febfea24a102380ae73827f62073543/yarl-1.22.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/98/92/ab8d4657bd5b46a38094cfaea498f18bb70ce6b63508fd7e909bd1f93066/yarl-1.22.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f5/e7/d8c5a7752fef68205296201f8ec2bf718f5c805a7a7e9880576c67600658/yarl-1.22.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b6/2e/f4d26183c8db0bb82d491b072f3127fb8c381a6206a3a56332714b79b751/yarl-1.22.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/80/7c/428e5812e6b87cd00ee8e898328a62c95825bf37c7fa87f0b6bb2ad31304/yarl-1.22.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ec/2a/249405fd26776f8b13c067378ef4d7dd49c9098d1b6457cdd152a99e96a9/yarl-1.22.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d" }, - { url = "https://mirrors.aliyun.com/pypi/packages/67/a8/fb6b1adbe98cf1e2dd9fad71003d3a63a1bc22459c6e15f5714eb9323b93/yarl-1.22.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd" }, - { url = "https://mirrors.aliyun.com/pypi/packages/d9/f9/3aa2c0e480fb73e872ae2814c43bc1e734740bb0d54e8cb2a95925f98131/yarl-1.22.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da" }, - { url = "https://mirrors.aliyun.com/pypi/packages/50/3c/af9dba3b8b5eeb302f36f16f92791f3ea62e3f47763406abf6d5a4a3333b/yarl-1.22.0-cp314-cp314-win32.whl", hash = "sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2" }, - { url = "https://mirrors.aliyun.com/pypi/packages/ac/30/ac3a0c5bdc1d6efd1b41fa24d4897a4329b3b1e98de9449679dd327af4f0/yarl-1.22.0-cp314-cp314-win_amd64.whl", hash = "sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79" }, - { url = "https://mirrors.aliyun.com/pypi/packages/df/0a/227ab4ff5b998a1b7410abc7b46c9b7a26b0ca9e86c34ba4b8d8bc7c63d5/yarl-1.22.0-cp314-cp314-win_arm64.whl", hash = "sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33" }, - { url = "https://mirrors.aliyun.com/pypi/packages/06/5e/a15eb13db90abd87dfbefb9760c0f3f257ac42a5cac7e75dbc23bed97a9f/yarl-1.22.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1" }, - { url = "https://mirrors.aliyun.com/pypi/packages/18/82/9665c61910d4d84f41a5bf6837597c89e665fa88aa4941080704645932a9/yarl-1.22.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5d/9a/2f65743589809af4d0a6d3aa749343c4b5f4c380cc24a8e94a3c6625a808/yarl-1.22.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53" }, - { url = "https://mirrors.aliyun.com/pypi/packages/b0/ab/5b13d3e157505c43c3b43b5a776cbf7b24a02bc4cccc40314771197e3508/yarl-1.22.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/fb/76/242a5ef4677615cf95330cfc1b4610e78184400699bdda0acb897ef5e49a/yarl-1.22.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf" }, - { url = "https://mirrors.aliyun.com/pypi/packages/8c/96/475509110d3f0153b43d06164cf4195c64d16999e0c7e2d8a099adcd6907/yarl-1.22.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face" }, - { url = "https://mirrors.aliyun.com/pypi/packages/c9/66/59db471aecfbd559a1fd48aedd954435558cd98c7d0da8b03cc6c140a32c/yarl-1.22.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b" }, - { url = "https://mirrors.aliyun.com/pypi/packages/03/1f/c5d94abc91557384719da10ff166b916107c1b45e4d0423a88457071dd88/yarl-1.22.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486" }, - { url = "https://mirrors.aliyun.com/pypi/packages/5f/97/aa6a143d3afba17b6465733681c70cf175af89f76ec8d9286e08437a7454/yarl-1.22.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138" }, - { url = "https://mirrors.aliyun.com/pypi/packages/43/3c/45a2b6d80195959239a7b2a8810506d4eea5487dce61c2a3393e7fc3c52e/yarl-1.22.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a" }, - { url = "https://mirrors.aliyun.com/pypi/packages/86/a0/c2ab48d74599c7c84cb104ebd799c5813de252bea0f360ffc29d270c2caa/yarl-1.22.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529" }, - { url = "https://mirrors.aliyun.com/pypi/packages/32/75/f8919b2eafc929567d3d8411f72bdb1a2109c01caaab4ebfa5f8ffadc15b/yarl-1.22.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093" }, - { url = "https://mirrors.aliyun.com/pypi/packages/cf/72/6a85bba382f22cf78add705d8c3731748397d986e197e53ecc7835e76de7/yarl-1.22.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c" }, - { url = "https://mirrors.aliyun.com/pypi/packages/35/18/55e6011f7c044dc80b98893060773cefcfdbf60dfefb8cb2f58b9bacbd83/yarl-1.22.0-cp314-cp314t-win32.whl", hash = "sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e" }, - { url = "https://mirrors.aliyun.com/pypi/packages/f9/86/0f0dccb6e59a9e7f122c5afd43568b1d31b8ab7dda5f1b01fb5c7025c9a9/yarl-1.22.0-cp314-cp314t-win_amd64.whl", hash = "sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27" }, - { url = "https://mirrors.aliyun.com/pypi/packages/48/b7/503c98092fb3b344a179579f55814b613c1fbb1c23b3ec14a7b008a66a6e/yarl-1.22.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1" }, { url = "https://mirrors.aliyun.com/pypi/packages/73/ae/b48f95715333080afb75a4504487cbe142cae1268afc482d06692d605ae6/yarl-1.22.0-py3-none-any.whl", hash = "sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff" }, ] diff --git a/web/test_backend.py b/web/test_backend.py index 0480cd5..1a77055 100644 --- a/web/test_backend.py +++ b/web/test_backend.py @@ -3,6 +3,7 @@ 测试工作流执行引擎和训练服务 """ + import asyncio import sys from pathlib import Path @@ -26,46 +27,25 @@ async def test_workflow_engine(): { "id": "node1", "type": "dataset_loader", - "data": { - "config": { - "data_path": "/path/to/data" - } - } + "data": {"config": {"data_path": "/path/to/data"}}, }, { "id": "node2", "type": "backbone_selector", - "data": { - "config": { - "backbone_type": "resnet18", - "pretrained": True - } - } + "data": {"config": {"backbone_type": "resnet18", "pretrained": True}}, }, { "id": "node3", "type": "trainer", "data": { - "config": { - "epochs": 2, - "batch_size": 32, - "learning_rate": 0.001 - } - } - } + "config": {"epochs": 2, "batch_size": 32, "learning_rate": 0.001} + }, + }, ], "edges": [ - { - "id": "e1", - "source": "node1", - "target": "node3" - }, - { - "id": "e2", - "source": "node2", - "target": "node3" - } - ] + {"id": "e1", "source": "node1", "target": "node3"}, + {"id": "e2", "source": "node2", "target": "node3"}, + ], } # 创建执行引擎 @@ -85,7 +65,7 @@ async def progress_callback(node_id, status, execution, progress): print(f" 状态: {result['status']}") print(f" 执行节点数: {len(result['executions'])}") - if result['status'] == 'success': + if result["status"] == "success": print(" 统计信息:") print(f" 总节点: {result['statistics']['total_nodes']}") print(f" 完成节点: {result['statistics']['completed_nodes']}") @@ -95,7 +75,7 @@ async def progress_callback(node_id, status, execution, progress): print(f" 错误: {result.get('error')}") print("\n❌ 工作流执行引擎测试失败!") - return result['status'] == 'success' + return result["status"] == "success" async def test_training_service(): @@ -112,7 +92,7 @@ async def test_training_service(): "backbone": "resnet18", "num_classes": 10, "pretrained": False, # 不使用预训练以加快测试 - "feature_dim": 128 + "feature_dim": 128, }, "data_config": { "num_samples": 100 # 少量数据用于测试 @@ -125,8 +105,8 @@ async def test_training_service(): "use_amp": False, # 不使用混合精度以兼容 CPU "gradient_checkpointing": False, "use_scheduler": False, - "save_model": False - } + "save_model": False, + }, } # 创建训练服务 @@ -173,9 +153,9 @@ async def progress_callback(data): print(f" Epoch: {status['current_epoch']}/{status['total_epochs']}") print(f" 耗时: {status['duration']:.2f}s") - if status['status'] == 'completed': + if status["status"] == "completed": print(" 最终指标:") - metrics = status['metrics'] + metrics = status["metrics"] print(f" Train Loss: {metrics.get('train_loss', 0):.4f}") print(f" Train Acc: {metrics.get('train_acc', 0):.2f}%") print(f" Val Loss: {metrics.get('val_loss', 0):.4f}") @@ -190,6 +170,7 @@ async def progress_callback(data): except Exception as e: print(f"\n❌ 训练服务测试失败: {e}") import traceback + traceback.print_exc() return False @@ -208,6 +189,7 @@ async def main(): except Exception as e: print(f"\n❌ 工作流执行引擎测试异常: {e}") import traceback + traceback.print_exc() results.append(("工作流执行引擎", False)) @@ -218,6 +200,7 @@ async def main(): except Exception as e: print(f"\n❌ 训练服务测试异常: {e}") import traceback + traceback.print_exc() results.append(("训练服务", False)) diff --git a/web/test_optimizations.py b/web/test_optimizations.py index 1bb57fc..b46d496 100644 --- a/web/test_optimizations.py +++ b/web/test_optimizations.py @@ -2,12 +2,14 @@ """ 快速测试脚本 - 验证所有优化功能 """ + import os import sys from datetime import UTC # 添加 backend 到 Python 路径 -sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'backend')) +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "backend")) + def test_auth(): """测试认证模块""" @@ -37,6 +39,7 @@ def test_auth(): except Exception as e: print(f" ❌ 认证模块测试失败: {e}") import traceback + traceback.print_exc() return False @@ -63,7 +66,6 @@ def test_database(): """测试数据库配置""" print("\n💾 测试数据库配置...") try: - from app.core.database import engine from app.models.database import utc_now @@ -118,7 +120,7 @@ def test_workflow_engine(): ], "edges": [ {"source": "node1", "target": "node2"}, - ] + ], } engine = WorkflowEngine(workflow) @@ -160,7 +162,7 @@ def main(): print(f"{name:20s} {status}") print("-" * 60) - print(f"总计: {passed}/{total} 通过 ({passed/total*100:.0f}%)") + print(f"总计: {passed}/{total} 通过 ({passed / total * 100:.0f}%)") print("=" * 60) if passed == total: