| 544 | } |
| 545 | |
| 546 | bool QmitkPipInstaller::ParseResolveReport(const QString& reportPath, int groupIndex) |
| 547 | { |
| 548 | QFile file(reportPath); |
| 549 | |
| 550 | if (!file.open(QIODevice::ReadOnly)) |
| 551 | { |
| 552 | MITK_ERROR << "Could not open report file: " << reportPath.toStdString(); |
| 553 | emit ErrorOccurred("Could not open pip resolve report."); |
| 554 | return false; |
| 555 | } |
| 556 | |
| 557 | const auto data = file.readAll(); |
| 558 | file.close(); |
| 559 | |
| 560 | // The report format is specified at |
| 561 | // https://pip.pypa.io/en/stable/reference/installation-report/. We rely |
| 562 | // on the outer catch to surface any deviation - every field we access |
| 563 | // here is required by that spec (plus PEP 426 for name / version). |
| 564 | // `requested` is the one genuinely optional field. |
| 565 | try |
| 566 | { |
| 567 | const auto report = nlohmann::json::parse(data.constData(), data.constData() + data.size()); |
| 568 | const auto& group = m_Groups[groupIndex]; |
| 569 | |
| 570 | for (const auto& entry : report.at("install")) |
| 571 | { |
| 572 | mitk::PipPackageInfo info; |
| 573 | |
| 574 | const auto& metadata = entry.at("metadata"); |
| 575 | info.name = metadata.at("name").get<std::string>(); |
| 576 | info.version = metadata.at("version").get<std::string>(); |
| 577 | info.requested = entry.value("requested", false); |
| 578 | info.group = groupIndex; |
| 579 | |
| 580 | // Match the resolved package against this group's requirements using |
| 581 | // PEP 503-canonicalized comparison so e.g. "scikit_learn", "scikit-learn" |
| 582 | // and "Scikit-Learn" all match the same resolved name. |
| 583 | const auto canonicalName = CanonicalizePackageName(info.name); |
| 584 | |
| 585 | for (const auto& req : group.requirements) |
| 586 | { |
| 587 | const auto reqName = CanonicalizePackageName(ExtractPackageName(req)); |
| 588 | if (reqName == canonicalName) |
| 589 | { |
| 590 | info.specifier = req; |
| 591 | break; |
| 592 | } |
| 593 | } |
| 594 | |
| 595 | // Bare VCS URLs (git+https://...) have no extractable package name, so |
| 596 | // the loop above cannot match them. Fall back to matching requested |
| 597 | // packages against unclaimed direct-reference requirements. |
| 598 | if (info.specifier.empty() && info.requested) |
| 599 | { |
| 600 | for (const auto& req : group.requirements) |
| 601 | { |
| 602 | if (!IsDirectReference(req)) |
| 603 | continue; |
no test coverage detected