From d74b4f2af358a21ab875de15d2d08367f666360e Mon Sep 17 00:00:00 2001 From: fleizean <66090171+fleizean@users.noreply.github.com> Date: Mon, 19 Oct 2026 19:33:21 +0300 Subject: [PATCH 1/2] fix(pypi): find the repository in the README when project_urls has none Selenium lists only www.selenium.dev in its metadata; its GitHub repository appears only in the package description. A repository named after the package is taken from there when no project link points at GitHub. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../Services/PyPIService.cs | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs b/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs index 2e863a0..5f8e53c 100644 --- a/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs +++ b/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs @@ -163,9 +163,29 @@ private static bool IsGitHubUrl(string? url) .Concat(links.Where(l => !NotRepositoryKeys.Any(k => l.Key.Contains(k, StringComparison.OrdinalIgnoreCase))) .Select(l => l.Value)); - return candidates.Select(RepositoryRoot).FirstOrDefault(url => url != null); + return candidates.Select(RepositoryRoot).FirstOrDefault(url => url != null) + ?? RepositoryFromDescription(info); } + // Some packages link only their website (selenium: www.selenium.dev) and name the repository in the + // README alone. Only a repository named after the package counts there: READMEs link other projects too. + private static string? RepositoryFromDescription(PyPIPackageInfo info) + { + if (string.IsNullOrEmpty(info.Description) || string.IsNullOrEmpty(info.Name)) + return null; + + var name = NormalizeName(info.Name); + return System.Text.RegularExpressions.Regex.Matches(info.Description, + @"https?://(?:www\.)?github\.com/[\w.-]+/[\w.-]+", + System.Text.RegularExpressions.RegexOptions.IgnoreCase) + .Select(m => RepositoryRoot(m.Value.TrimEnd('.'))) + .FirstOrDefault(url => url != null && NormalizeName(url[(url.LastIndexOf('/') + 1)..]) == name); + } + + // PEP 503: names compare case-insensitively with runs of "-", "_" and "." as one "-" + private static string NormalizeName(string name) => + System.Text.RegularExpressions.Regex.Replace(name, @"[-_.]+", "-").ToLowerInvariant(); + // https://github.com/{owner}/{repo} of a GitHub link (issues, a changelog file, releases), keeping a // /tree/{ref}/{folder} part that names the package folder of a monorepo; null for any other link private static string? RepositoryRoot(string? url) @@ -245,6 +265,9 @@ private class PyPIPackageInfo [JsonPropertyName("project_urls")] public Dictionary? ProjectUrls { get; set; } + + [JsonPropertyName("description")] + public string? Description { get; set; } } private class PyPIReleaseFile From ab7370907de54e46bd7fbe9061be24379f811a59 Mon Sep 17 00:00:00 2001 From: fleizean <66090171+fleizean@users.noreply.github.com> Date: Mon, 19 Oct 2026 19:33:48 +0300 Subject: [PATCH 2/2] refactor(pypi): drop the comments on the README repository lookup Co-Authored-By: Claude Opus 5.5 (1M context) --- src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs b/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs index 5f8e53c..7f376ac 100644 --- a/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs +++ b/src/backend/PkgDiff.Infrastructure/Services/PyPIService.cs @@ -167,8 +167,6 @@ private static bool IsGitHubUrl(string? url) ?? RepositoryFromDescription(info); } - // Some packages link only their website (selenium: www.selenium.dev) and name the repository in the - // README alone. Only a repository named after the package counts there: READMEs link other projects too. private static string? RepositoryFromDescription(PyPIPackageInfo info) { if (string.IsNullOrEmpty(info.Description) || string.IsNullOrEmpty(info.Name)) @@ -182,7 +180,6 @@ private static bool IsGitHubUrl(string? url) .FirstOrDefault(url => url != null && NormalizeName(url[(url.LastIndexOf('/') + 1)..]) == name); } - // PEP 503: names compare case-insensitively with runs of "-", "_" and "." as one "-" private static string NormalizeName(string name) => System.Text.RegularExpressions.Regex.Replace(name, @"[-_.]+", "-").ToLowerInvariant();