PyRadar: Towards Automatically Retrieving and Validating Source Code Repository Information for PyPI Packages
Kai Gao Weiwei Xu Wenhao Yang Minghui Zhou


: Towards Automatically Retrieving and Validating PyPI Packages' Source Code Repository Information]: Towards Automatically Retrieving and Validating Source Code Repository Information for PyPI Packages


gaokai19@pku.edu.cn
0000-0002-0942-7890

  School of Software & Microelectronics, Peking University
  Beijing
  China



xuww@stu.pku.edu.cn
0009-0004-3493-102X

Yangwh@stu.pku.edu.cn
0000-0002-1005-1974

Corresponding Author
zhmh@pku.edu.cn
0000-0001-6324-3964

  School of Computer Science, Peking University
  Beijing
  China




A package's source code repository records the package's development history, which is critical for the use and risk monitoring of the package. 
However, a package release often misses its source code repository due to the separation of the package's development platform from its distribution platform. 
To establish the link, existing tools retrieve the release's repository information from its metadata, which suffers from two limitations: the metadata may not contain or contain wrong information. 
Our analysis shows that existing tools can only retrieve repository information for up to 70.5% of PyPI releases. 
To address the limitations, this paper proposes , a novel framework that utilizes the metadata and source distribution to retrieve and validate the repository information for PyPI releases. 
We start with an empirical study to compare four existing tools on 4,227,425 PyPI releases and analyze phantom files (files appearing in the release's distribution but not in the release's repository) in 14,375 correct and 2,064 incorrect package-repository links. 
Based on the findings, we design   with three components, i.e., Metadata-based Retriever, Source Code Repository Validator, and Source Code-based Retriever, that progressively retrieves correct source code repository information for PyPI releases. 
In particular, the Metadata-based Retriever combines best practices of existing tools and successfully retrieves repository information from the metadata for 72.1% of PyPI releases. 
The Source Code Repository Validator applies common machine learning algorithms on six crafted features and achieves an AUC of up to 0.995. 
The Source Code-based Retriever queries World of Code with the SHA-1 hashes of all Python files in the release's source distribution and retrieves repository information for 90.2% of packages in our dataset with an accuracy of 0.970. 
Both practitioners and researchers can employ the   to better use PyPI packages. 




acmlicensed
PACMSE
2024 1 FSE 115 710.1145/3660822


<ccs2012>
   <concept>
       <concept_id>10011007.10011006.10011072</concept_id>
       <concept_desc>Software and its engineering Software libraries and repositories</concept_desc>
       <concept_significance>500</concept_significance>
       </concept>
   <concept>
       <concept_id>10011007.10011074.10011111.10011696</concept_id>
       <concept_desc>Software and its engineering Maintaining software</concept_desc>
       <concept_significance>500</concept_significance>
       </concept>
   <concept>
       <concept_id>10003120.10003130.10003233.10003597</concept_id>
       <concept_desc>Human-centered computing Open source software</concept_desc>
       <concept_significance>500</concept_significance>
       </concept>
 </ccs2012>


[500]Software and its engineering Software libraries and repositories
[500]Software and its engineering Maintaining software
[500]Human-centered computing Open source software



[
    Minghui Zhou
    April 29, 2024
==================





§ INTRODUCTION

In order to boost productivity and reduce cost, developers widely reuse “the wheels” <cit.>, i.e., reusing existing third-party packages rather than implementing the functionality from scratch. Many programming language (PL) communities provide centralized package registries (such as PyPI for Python and NPM for JavaScript) to facilitate the sharing and reuse of third-party packages, which host a substantially growing number of packages. As of September 2023, over 480 thousand Python packages have been published in PyPI.

Despite the benefits, reusing third-party packages also poses unique challenges to software development. First, given so many packages available, selecting the right one is laborious for developers <cit.>. Second, even if the right package is selected, how to estimate, monitor, and mitigate risks of the package, e.g., stop-of-maintenance <cit.> and vulnerabilities <cit.>, is important yet challenging.
Merely using source code in the package's distribution is often insufficient in mitigating the above challenges. Practitioners and researchers commonly turn to the package's source code repository. On the one hand, development activity data recorded in the repository can help identify and mitigate some risks in the package.
For example, the number of stars is a critical factor when selecting third-party packages <cit.>; the number of commits, contributors, and issues are popular indicators of the package's maintenance state <cit.>; researchers also mine undisclosed vulnerabilities from issues <cit.> and track patches for known vulnerabilities <cit.>.
On the other hand, the package's source code repository provides package users a place that the package registry lacks, allowing them to report bugs <cit.>, make contributions <cit.>, and seek community help <cit.>.
Therefore, a package's source code repository not only complements the role of its distribution in estimating and mitigating risks of the package but also plays a crucial role in its usage. Locating the source code repository is vital for every package.

However, many major PL communities (Python, JavaScript, Java, etc.) follow the common practice of separating the code repository and distribution artifact of the package.
The separation offers numerous benefits, e.g. reducing the package's installation size <cit.> and streamlining the build process <cit.>, but disconnects the artifact from its source code repository.
The good news is, that developers usually use build tools to manage and publish distribution artifacts, and most build tools provide mechanisms empowering developers to declare the source code repository in the package metadata.
For example, setuptools, the de facto build tool in the Python community, provides several optional keyword arguments (e.g., url, project_urls) in the setup function for package developers to declare package-related URLs in the package specification file such as setup.py <cit.>. Then based on the package specification file, setuptools automatically generates release metadata <cit.> in the packaging process.
However, repository information in the metadata is still not the final answer to the package-repository linking problem.
First, since the package's source code repository information is not mandatory for build tools, package developers may not declare such information in the package specification file. As shown in this paper, about 30% of PyPI releases' metadata do not contain repository information.
Consequently, it is impossible to mine insights from source code repositories for these packages.
Second, package developers may declare wrong repository information in the package specification file intentionally or unintentionally.
An extreme case is the prevalent typosquatting attack <cit.>.
Malicious package developers usually copy the metadata (including the repository information) of popular packages they masquerade as.
Another case is that developers did not change the placeholder repository URL.
https://github.com/pypa/sampleprojectgh:pypa/sampleproject is a sample project that guides developers on packaging and distributing Python projects, but we find that 3,212 PyPI packages declare it as their source code repository.
Wrong source code repository information tends to mislead existing package monitoring tools such as Libraries.io <cit.> and open source insights <cit.>, and consequently, bias users' decisions.

Practitioners and researchers have implemented various tools  <cit.> to locate the repository for packages. However, these tools typically use the package metadata, which inevitably traps them into the two limitations mentioned above, i.e. wrong or unavailable repository information (that indicates where the repository is). To address the limitations, it is necessary to validate the repository information retrieved from the metadata and to utilize source code in the package to locate its repository when such information is unavailable in metadata.
To that end, we begin with a large-scale empirical study in PyPI and then leverage the discovered insights to design a tool to retrieve the correct repository location for PyPI releases. Specifically, the empirical study explores two research questions:


    
  * RQ1: To what extent can existing tools retrieve source code repository information from the metadata and what are their differences? Despite the plethora of metadata-based tools, there remains a lack of understanding about their capabilities. Thus, we propose this RQ to understand the status quo of techniques used to retrieve repository information from the metadata.
    
  * RQ2: What are the phantom file differences between correct package-repository links and incorrect links? Phantom files are files appearing in the release's distribution but not in the release's repository, possibly indicating whether a release is built from a repository. Assuming the package-repository link is correct, prior work <cit.> investigated phantom files and found that Python files were rarely phantom files in these links. However, to what extent phantom files differ between correct and incorrect package-repository links has not been investigated. Such understanding is vital for designing the tool that uses source code to validate and locate a package's repository.


We collect ecosystem-scale metadata of 4,227,425 PyPI releases to answer the questions.
We find that existing tools retrieve repository information from the metadata for up to 70.5% of releases. We also identify several best practices such as URL redirection and searching from multiple information sources to locate the repository.
We propose a heuristic approach to collect 14,375 correct and 2,064 incorrect package-repository links, and a novel Git repository traversal algorithm to accurately identify phantom files. We find that the number of phantom files in incorrect links is significantly higher and incorrect links are more likely to contain phantom package specification files.

Inspired by the empirical findings, we propose , a novel framework that utilizes the release's metadata and source distribution to automatically retrieve and validate the source code repository information for PyPI releases.   consists of three components: a Metadata-based Retriever similar to existing tools and two novel components to address the two limitations of existing tools, i.e., a Source Code Repository Validator to deal with the limitation of incorrect repository information in the metadata, and a Source Code-based Retriever to address the limitation of missing repository information in the metadata.
Specifically, the Metadata-based Retriever combines best practices of existing tools and retrieves repository information for 72.1% of PyPI releases.
The Source Code Repository Validator validates the correctness of the repository information retrieved by the Metadata-based Retriever. It contributes six crafted features, two of which are derived from the findings of RQ2. Common machine learning algorithms can achieve an AUC of up to 0.995 on these features, demonstrating their effectiveness.
The Source Code-based Retriever uses source code in a release's source distribution to retrieve its repository from World of Code (WoC) <cit.>, an infrastructure that collects almost all public Git repositories. Inspired by the findings of RQ2, we propose an efficient file hash-based repository retrieval algorithm. It retrieves repository information for 90.2% of packages in our dataset with an accuracy of 0.970 and completes a retrieval in an average of 40 seconds, demonstrating its effectiveness and efficiency.

In summary, the major contributions of this paper are:

    
  * We conduct the first large-scale empirical study to compare existing metadata-based tools and investigate phantom file differences between correct and incorrect package-repository links.
    
  * We propose a heuristic approach to automatically and accurately collect correct and incorrect package-repository links to facilitate future research on this problem.
    
  * We propose and evaluate , a novel framework that utilizes the metadata and source distribution to automatically retrieve and validate repository information for PyPI releases. It works for all PyPI releases (about 88% of all PyPI releases) that provide source distributions.


Figure <ref> demonstrates the overview of this study, including the data collection (Section <ref>), the empirical study (Section <ref>), and the   framework addressing the two limitations (Section <ref>).





§ BACKGROUND AND RELATED WORK




 §.§ Terminology

Based on the official Python Packaging Glossary <cit.> and prior work <cit.>, we define the following terminologies for the convenience of discussion.


    
  * Package is a project registered on PyPI that `is intended to be packaged into a distribution'. A package can be considered as a folder consisting of a collection of files, with package specification files at the top-level folder. A package has one or more releases.

    
  * Release is a snapshot of a package at a certain time point and is identified by a version identifier. A release consists of one or more distributions.

    
  * Distribution is a versioned archive file that contains the Python package. Distribution is what the user will download from the package registries and install. There are two types of distributions: source distribution and built distribution.

    
  * Source distribution is a distribution format that contains package specification files and all essential files needed to generate built distributions.

    
  * Built distribution is another distribution format containing only metadata and files that will be copied to the correct location on the user's system at installation time. It contains pre-compiled files such as .pyc files and .so/.dll binary modules. However, Python files are not precompiled <cit.>. Therefore, built distributions also contain Python source code.

    
  * Package specification file specifies build system information and release metadata. Currently, there exist multiple package specification files including pyproject.toml, setup.py, and setup.cfg. Multiple package specification files can coexist in a package.

    
  * Metadata contains descriptive information of a package such as name, version, and relevant URLs.





 §.§ World of Code

World of Code (WoC) is an infrastructure for mining version control system data across the entire open source software ecosystem.
It collects Git objects including commits, trees, and blobs <cit.> from nearly exhaustive public Git repositories on dozens of code hosting platforms such as GitHub, Bitbucket, and GitLab.
Based on the collected Git objects, WoC provides several key-value databases for efficiently querying relationships between blobs, commits, repositories, and other relevant entities. For example, the blob-to-commit database maps a blob to all commits that introduced it; the commit-to-repository database maps a commit to all repositories that contain it. It is regularly updated and versioned. At the time of experimentation in this paper, the latest version of WoC was labeled as U and the data was collected in October 2021, containing over 173 million Git repositories, 3.1 billion commits, 12.5 billion trees, and 12.4 billion blobs <cit.>.



 §.§ Software Provenance

Software provenance refers to the origin and history of a software artifact such as code snippets and files <cit.>.
In this sense, finding the package's source code repository is a kind of software provenance task.
Rousseau et al. <cit.> investigated the problem of file provenance in Software Heritage <cit.>, an infrastructure for preserving software source code.
Hata et al. <cit.> studied how the same file evolves in different source code repositories.
Reid et al. <cit.> developed a tool VDiOS based on WoC to detect vulnerabilities induced by file reuse.
Wyss et al. <cit.> proposed unwrapper to detect shrinkwrapped clones in NPM where a package duplicates or near-duplicates the code of another package.
However, all these works are conducted at file-level granularity, different from the distribution-level granularity (i.e., a collection of files) required by finding the package's repository.

Sun et al. <cit.> proposed an identifier-based approach to map Debian source packages written in Python to PyPI packages. They indexed identifiers (classes and method/function names) in all PyPI packages and found that 76% of identifiers exist only in one package. Then they proposed an approach that randomly selects three non-frequent identifiers and queries the PyPI identifier corpus to locate the most probable PyPI packages. However, this work was conducted on the PyPI package corpus, which is different from and much smaller than the source code repository corpus.



There are also some tools that automatically retrieve the package's source code repository information as summarized in Table <ref>.

    
  * PyPI GitHub Statistics <cit.> is provided by the PyPI website. Specifically, it detects GitHub repository URLs from the release's metadata and presents statistics for the retrieved GitHub repository such as the number of stars and forks in the sidebar of the package's PyPI page.
    
  * OSSGadget <cit.> is a collection of software supply chain tools released by Microsoft, one of which is OSS Find Source which attempts to locate a release's source code repository on GitHub. Similar to PyPI GitHub Statistics, OSS Find Source retrieves the release's source code repository information from the metadata.
    
  * Libraries.io <cit.> is an open source project maintained by Tidelift that collects package information from 32 package registries including PyPI. It also retrieves each package release's repository information from the metadata. Different from the above two tools, it detects repositories from multiple platforms.
    
  *  <cit.> is a tool proposed by a researcher from the University of Trento. It retrieves GitHub repository URLs from multiple information sources, including the package metadata and the websites referenced by the metadata (i.e., the package's homepage and Readthedocs page). Then it returns the GitHub URL with the most occurrences.
    
  * Open Source Insights <cit.> is a service developed and hosted by Google. It presents comprehensive information about the package such as vulnerabilities, dependencies, licenses, and the package's OpenSSF scorecard <cit.> information based on the GitHub repository it detects. Since this tool is not open source <cit.>, we have little information about its implementation. But it claimed that the detected repository information is not guaranteed to be authoritative as the package owner may list a link to any source code repository <cit.>.
    
  * Snyk Advisor <cit.> is a service provided by the Snyk platform. It presents the package's maintenance and community information based on development activity data in the package's source code repository. It is also not open source. After manually inspecting several packages, we speculate this tool also retrieves repository information from the metadata and only extracts GitHub repository URLs.


To summarize, existing tools mainly retrieve the release's source code repository information from the metadata and do not validate the correctness of the retrieved repository information.



§ DATA COLLECTION


We build two datasets to conduct this study: 1) the Metadata dataset for comparing existing metadata-based tools (RQ1) and providing necessary information for the rest part of this study; 2) the Package-Repository Link dataset, which is used to investigate phantom file differences between correct package-repository links and incorrect links (RQ2) and lay a foundation on the design and evaluation of the Source Code Repository Validator and the Source Code-based Retriever.

Metadata dataset. We build this dataset with PyPI API <cit.> in March 2023. Specifically, we use the XML-RPC API to retrieve all packages registered on PyPI. We first get all its releases for each package and then get the metadata for each release using the JSON API. In total, we obtain metadata for 4,227,425 releases of 423,726 packages.

Package-Repository Link dataset. To validate the retrieved repository information of a release is correct or not, we need to build a dataset consisting of correct package-repository links and incorrect links. However, since the repository information in the metadata may be incorrect, it is challenging to collect correct and incorrect package-repository links. We, therefore, propose a heuristic approach to collect such data where we first collect correct package-repository links and then collect incorrect links based on the correct links.

We turn to the GitHub dependency graph <cit.> (GDG for short) to collect correct links. GDG identifies the packages associated with a GitHub repository, as shown in Figure <ref>.
However, there are some problems when using GDG:
1) most GitHub repositories do not publish packages;
2) GDG detects packages across multiple packaging ecosystems, therefore packages published by different repositories may share the same name.
For example, https://github.com/dmontagu/fastapi_client/network/dependentsdmontagu/fastapi_client and https://github.com/kevinastone/django-api-rest-and-angular/network/dependentskevinastone/django-api-rest-and-angular both publish the example package with the former as a Python package and the latter as a JavaScript package;
3) packages published by a repository may not be registered on PyPI and may even have the same name as PyPI packages. E.g., the teras package published by https://github.com/chantera/teras/network/dependentschantera/teras collides with the https://pypi.org/project/Teras/teras package on PyPI.



To address these problems, we first collect all source code repositories with at least 100 stars and written in Python using GitHub search API <cit.> (to tackle the first and second problem), since popular repositories are more likely to publish packages <cit.>. We obtain 50,359 repositories in total.
Then we collect packages published by these repositories by crawling each repository's dependency graph page, resulting in 14,471 packages.
Next, we only keep packages registered on PyPI by aligning GitHub package names with those in the Metadata dataset (to tackle the third problem), leaving 12,463 packages published by 11,803 GitHub repositories.
We also add the top 4,000 most downloaded packages with their source code repository information retrieved by the Metadata-based Retriever to further enrich the dataset. We consider these packages' source code repository information correct since they have a high impact on the Python community and have been widely studied in prior work <cit.>. In total, we collect 14,375 correct links.

To evaluate the effectiveness of the approach to collecting correct links, we randomly sample 374 links (95% confidence level and 5% confidence interval).
For each link, we check:
1) if the package name is declared in any package specification file in the repository;
2) if the package's PyPI maintainer <cit.> (presented in the sidebar of the package's PyPI page) is a contributor to the repository (using common name abbreviation rules and user avatars);
3) if the repository or the documentation website referenced by the repository contains a link to the package's PyPI page or pip install commands with the package name.
It is non-trivial to automate the three conditions accurately. Specifically, package developers can declare package names in the package specification file setup.py in various ways, posing challenges in automating the first condition. The second condition, linking PyPI accounts and GitHub accounts, involves a trade-off between precision and recall due to incomplete and inconsistent information on different platforms <cit.>. The challenge of automating the third condition (searching for explicit mutual links between packages and repositories) is that relevant information is scattered and buried deep within repositories and related websites. Therefore, we choose manual checking over automated checking as it allows us to check the correct links with 100% accuracy, which is important for verifying the validity of collected correct links.
We label a link as correct if it satisfies the first condition and one of the last two conditions. In total, 373, 369, and 349 links satisfy the three conditions respectively and 373 (99.7%) links are labeled as correct. The remaining link is not labeled as correct due to the complex packaging process of the ansible package <cit.>. It is noteworthy that the checking process is only a sufficient condition for a link to be correct. If a link does not meet the checking criteria, we can not assert it as incorrect. Overall, the manual inspection indicates the validity of the collected links.

Based on the correct links, we collect incorrect links as follows.
We presume that the maintainers of PyPI packages are developers in the package's source code repository responsible for publishing releases.
If two packages declare the same source code repository but have different maintainers, it is likely that one package's source code repository information is incorrect.
Under this assumption, we select packages that have the same source code repository as packages in the correct links but have different PyPI maintainers. In this way, we obtain 1,721 links. As noted in Section <ref>, over 3,000 packages declare their source code repository as gh:pypa/sampleproject by mistake. Therefore, we expand the incorrect link data with these packages. Considering the large number of such packages, we randomly select 343 packages (95% confidence level and 5% confidence interval) to avoid them skewing the dataset. In total, we collect 2,064 incorrect package-repository links.

We verify the validity of incorrect links as follows. Since we are sure the incorrect correspondence between the 343 sampled packages and the gh:pypa/sampleproject repository, we sample 314 links (95% confidence level and 5% confidence interval) from the rest of 1,721 links. For each link, we manually check if the package name is specified in the source code repository. If not, we label it as incorrect. In total, 312 (99.4%) links are labeled as incorrect. The rest two links are correct due to the move of the package's source code repository <cit.> and package renaming <cit.>. Overall, the inspection results suggest that the collected incorrect links are valid.



§ EMPIRICAL STUDY




 §.§ RQ1: Existing Tool Analysis

Given the many metadata-based tools available, a clear understanding of their effectiveness and discrepancies can help better retrieve the release's repository information from the metadata. Specifically, we aim to understand the number of PyPI releases for which existing tools can retrieve repository information and the differences in the retrieved repository information.



  §.§.§ Method

We select PyPI GitHub Statistics, OSS Find Source, Libraries.io, and   for this RQ since they are open source, which enables us to make comparisons on the complete PyPI releases.
However, since these tools are tightly tied to their contexts and used in different ways, it is difficult to deploy them on our Metadata dataset. We, therefore, choose to carefully reimplement them to facilitate the evaluation of their capabilities on the metadata of 4,227,425 PyPI releases. To ensure that the reimplemented tools are consistent with the original ones, we test them with test cases from the original tools. Then, we deploy them on our dataset and obtain the repository information retrieved by these tools for each release.
To understand the discrepancies between these tools, we perform a stratified sampling of the differences in the retrieved repository information of the four tools and identify reasons for the differences based on the implementation of these tools. The number of sampled data for each pair of tools is shown in the parentheses of Table <ref>.





  §.§.§ Results

Table <ref> presents the percentage of releases and packages for which the four reimplemented tools retrieve repository information.
It is worth noting that the retrieved repository information may be incorrect.
We can observe that existing tools can retrieve repository information for about 3/4 of releases and 70% of packages, suggesting that substantial releases' metadata does not contain repository information. Libraries.io and   retrieve repository information for more releases since Libraries.io takes more code hosting platforms into account and   considers more information sources such as the homepage and Readthedocs page. The repository URLs retrieved by Libraries.io come from GitHub (3,032,984), GitLab (68,670), Bitbucket (53,668), SourceForge (5,918), ASF Subversion Server (2), and ASF GitBox Services (1). In the following, we only analyze the differences in the retrieved GitHub repository URLs.

The four tools retrieve different GitHub repository URLs for 511,480 (12.1%) releases.
Table <ref> presents the percentage of releases for which the four tools retrieve different GitHub repository URLs.
The difference between PyPI GitHub Statistics and OSS Find Source is the least (0.16%) since they only differ in how the GitHub repository URL is extracted. PyPI GitHub Statistics uses the URL scheme while OSS Find Source uses the regular expression.
  differs from the remaining three tools a lot (10.47% ∼ 11.86%).



Table <ref> presents the seven identified reasons for the differences in the retrieved repository information of the four tools. URL redirection is the most common reason for the differences. Only   deals with URL redirection when retrieving repository URLs from some information sources.
We also present the adjusted percentage of releases and packages for which the four tools retrieve repository information after URL redirection in Table <ref> (in parentheses). We can observe that existing tools can retrieve repository information for up to 70.5% of releases and 63.1% of packages. It suggests that URL redirection should be considered when retrieving repository information from the metadata due to the URL decay.
The strategy of searching project_urls field accounts for the second most differences. This field is an arbitrary map of names to URLs.
Libraries.io takes a rather conservative approach by searching only URLs whose names are in a predefined list, thus omitting repository URLs with other names.
The badge URL, Readthedocs page, and Homepage searched by  account for about 1/4 of the differences.
Different URL extraction methods also lead to different retrieved repository information. Specifically, PyPI GitHub Statistics and   extract repository URLs according to the URL scheme while OSS Find Source and Libraries.io rely on regular expressions. We find that regular expressions are more robust since the URL information provided by developers may not strictly observe the URL scheme. It is noteworthy that these reasons may contribute to inaccuracies when retrieving repository information from the metadata. For example, when the metadata contains multiple URLs linking to repositories on code hosting platforms, these tools may select different URLs due to different retrieval strategies, leading to incorrect repository information retrieved by certain tools.




Answers for RQ1:
The four reimplemented tools can retrieve repository information from the metadata for up to 70.5% of releases and 63.1% of packages. The percentage of differences in the repository information retrieved by the four tools ranges from 0.16% to 11.86%. Seven reasons induce the differences such as URL redirection and the project_urls searching strategy.



0.8pt

Implications:
When retrieving repository information from the metadata, it is necessary to take the following elements into account: URL redirection, multiple code hosting platforms, multiple information sources that are contained in the metadata, and badges, homepage, and Readthedocs page that are referred by the metadata.




 §.§ RQ2: Phantom File Analysis

Prior work has revealed that most Python files in the release distribution also exist in the release's repository <cit.>, which sheds light on how to validate the correctness of the release's repository information retrieved from the metadata and how to retrieve the release's repository using source code in the release's distribution.
Thus, our second research question aims to understand the differences in phantom files (files appearing in the release's distribution but not in the release's repository) between correct package-repository links and incorrect links.



  §.§.§ Method

The basic idea of obtaining phantom files is to traverse all files in the release's distribution and the release's source code repository, calculate their hashes, and find the files whose hashes appear in the distribution but not in the repository.

As noted in Section <ref>, a release consists of one or more distributions and there are two kinds of distributions in a release: source distribution and built distribution.
We choose source distribution to obtain phantom files for two reasons:

    
  * The number of releases providing source distributions is much higher than the number of releases providing built distributions (3,719,068 vs. 2,892,007). Therefore, the source distribution enables us to analyze more releases.
    
  * For the 2,419,223 releases providing both source distributions and built distributions, we randomly select one release for each package, resulting in 243,518 releases. For each release, we compare files in the source distribution and built distribution. We find that files in the built distribution are all included in the source distribution for 216,741 (89.0%) releases. Among the remaining releases, the built distributions mostly contain pre-compiled files (such as .pyc files, .so binary modules), which are usually not included in the repository.


It is straightforward to get hashes for all files in the distribution. We download the distribution, open it with the Python standard library tarfile (for .tar.gz distribution files) or zipfile (for .zip distribution files) <cit.>, traverse files in it, and calculate each file's blob SHA-1 hash <cit.>. We choose the blob SHA-1 hash because Git uses it to index files so that we don't have to calculate hashes for files in the repository.

However, it is challenging to traverse all files in the repository due to the complex Git-based development <cit.>, especially the adoption of Git submodules <cit.>. Submodules, which are configured in the .gitmodules file, allow developers to add a Git repository as a subfolder of another Git repository. We find submodules also popular in PyPI releases' repositories. Specifically, among the 3,047,112 releases for which the Metadata-based Retriever retrieves repository information, 159,360 (5.2%) releases' repository use submodules such as numpy and scipy. Files in submodules are also packaged into distributions. If not considering submodules when traversing files in the repository, many false positive phantom files will be identified. To make things more complicated, submodules are updated over time. To properly deal with Git submodules and accurately identify phantom files, we propose a novel Git repository traversal algorithm (Algorithm <ref>).





This algorithm traverses all commits to obtain a complete list of files in the repository. We use the Git command: git cat-file --batch-check --batch-all-objects --unordered (line 4) to ensure that all commits are traversed. For each commit, we obtain the tree object it points (line 6) and traverse the tree in a recursive way (traverse_tree) to obtain all files in the commit snapshot (line 7). Specifically, we first list all entries in the tree object, where each entry consists of the SHA-1 hash of a blob, tree, or commit object with its associated mode, type, and filename. We process each entry as follows:

    
  * If the entry points to a blob object, we simply record its name and SHA-1 hash (line 14-15). If the blob's filename is ".gitmodules", we parse the path and URL of submodules configured in this file with the Python standard library configparser (line 16-17).
    
  * If the entry points to a tree object, we traverse files in it and merge the result (line 18-19).
    
  * If the entry points to a commit object, which indicates a submodule, we get the submodule's Git URL, obtain the tree object pointed by the commit object, and traverse files in the tree object of the submodule (line 20-24).


We implement this algorithm with as many operations provided by Git as possible to ensure a correct implementation. We make a simple comparison with LastPyMile proposed in prior work <cit.>, which did not consider submodules when traversing the repository, on four popular packages, two of which do not use submodules in their repositories and the other two of which use submodules in their repositories. The comparison results (Table <ref>) indicate that our algorithm can properly deal with submodules and identify more accurate phantom files.



We use the Package-Repository Link dataset to conduct this RQ. Specifically, for each (correct and incorrect) link in the dataset, we first download the source distribution of the package's latest release and obtain the blob SHA-1 hashes of files in the distribution. Then we clone the source code repository and obtain all blob SHA-1 hashes following Algorithm <ref>. Finally, we get phantom files by comparing SHA-1 hashes in the distribution and the repository.



  §.§.§ Results

Figure <ref> demonstrates the distribution of the number of phantom files and phantom Python files in the correct and incorrect links. It can be clearly observed that the number of phantom files and phantom Python files in the correct links is much lower than that in the incorrect links, with the significance confirmed by the Mann-Whitney U test <cit.>. Specifically, the median number of phantom files in the correct and incorrect links is 1 and 5 respectively, and the median number of phantom Python files is 0 and 3 respectively. It is also noteworthy that 75.3% of the correct links do not have phantom Python files whereas 96.2% of the incorrect links have at least one phantom Python file, suggesting that the number of phantom Python files may be useful to validate the correctness of a release's repository information and Python file in the release's source distribution may be used to retrieve the release's repository from WoC.





Table <ref> presents the 10 most common files and Python files in source distributions of incorrect links. To derive effective features for identifying as much incorrect repository information for the release as possible, we calculate the inclusion rates and phantom rates of the files. The inclusion rate of a file is defined as the proportion of correct (incorrect) links that include the file in the source distribution compared to the total number of correct (incorrect) links. The phantom rate of a file is defined as the proportion of correct (incorrect) links in which the file is a phantom file compared to the number of correct (incorrect) links that include the file in the source distribution. Almost every correct link and incorrect link include the package specification file setup.py or pyproject.toml in the source distribution, as revealed by the inclusion rates in correct links (99.5%) and incorrect links (99.2%). However, the phantom rate of setup.py or pyproject.toml differs greatly between correct (16.6%) and incorrect (97.0%) links. The results indicate that the presence of a phantom package specification file (setup.py or pyproject.toml) could serve as an effective feature in identifying incorrect repository information for the release: an inclusion rate close to 1 indicates that it is calculable for almost every package-repository link and the high phantom rate in incorrect links indicates that it achieves a high recall in identifying incorrect repository information. Despite the high phantom rate of README (README.md or README.rst) or LICENSE in incorrect links compared to correct links, the presence of a phantom README or LICENSE is not effective in identifying incorrect repository information for two reasons: 1) the relatively low inclusion rates (91.0% in correct links and 91.9% in incorrect links) suggest that it is incalculable for nearly 10% of links; 2) the low phantom rate (51.6%) in incorrect links indicates its low recall.
Notably, the phantom rates of setup.cfg (another package specification file) in correct and incorrect links are both close to 1. We manually inspect 10 correct links with the phantom setup.cfg file and find that 7 of them do not contain the setup.cfg file in the repository, indicating that most of the phantom setup.cfg files are generated in the build process.
Overall, the results indicate that whether the package specification file setup.py or pyproject.toml is a phantom file may be used to identify incorrect repository information for the release.



Answers for RQ2:
The number of phantom files and phantom Python files in the incorrect links is significantly higher than in the correct links. Python files are generally not phantom files in the correct links. The percentage of phantom package specification files (setup.py or pyproject.toml) in the incorrect links is much higher than in the correct links.



0.8pt

Implications:
The number of phantom Python files and whether the package specification file setup.py or pyproject.toml is a phantom file may be useful features to validate the correctness of a release's repository information. Retrieving a release's repository from WoC using only Python files in the release's source distribution may be sufficient and efficient.




§ THE   APPROACH


Inspired by the empirical findings from Section <ref>, we propose , a framework that utilizes the release's metadata and source code to automatically retrieve and validate the release's source code repository information. As shown in Figure <ref>,   consists of three components:

    
  * Metadata-based Retriever. It retrieves repository information from the release's metadata.
    
  * Source Code Repository Validator. It validates the correctness of the release's repository information retrieved by the Metadata-based Retriever. If the repository information is validated as correct, it will then be output.
    
  * Source Code-based Retriever. If the Metadata-based Retriever fails to retrieve repository information from the release metadata or the Source Code Repository Validator concludes that the release's repository information retrieved from the metadata is incorrect, this component retrieves the release's repository from WoC using files in the release's source distribution. If this component fails to retrieve a repository, the output is empty.


In this section, we elaborate on the design and evaluation of each component.





 §.§ Metadata-based Retriever



  §.§.§ Design

We design this component following the best practices learned from existing metadata-based tools (Section <ref>).
It first searches for repository URLs with regular expressions from the url, download_url, and project_urls fields in the release metadata sequentially. If any repository URL is found, it returns the redirected repository URL.
Otherwise, it searches the description field in the release metadata for repository URLs and badge URLs. It only returns the redirected URL whose repository name is exactly the same as the package name after removing non-alphanumeric characters.
If still no repository URL is found, it searches for the homepage URL and documentation page URL in the project_urls field, scrapes the homepage and documentation page, extracts repository URLs in them, and returns the redirected URL with the repository name exactly the same as the package name after removing non-alphanumeric characters.
In the current implementation, it considers repositories on the three most popular code hosting platforms, i.e., GitHub, GitLab, and Bitbucket.
It resolves URL redirections for GitHub repositories via the GitHub Repository API and for Bitbucket and GitLab repositories via HTTP requests.



  §.§.§ Evaluation

We implement this component in Python and run it on the entire Metadata dataset. It successfully retrieves source code repository information for 72.1% of the releases (79.1% before URL redirection), 1.6% higher than the existing state-of-the-art tool . The improvement of the Metadata-based Retriever over existing tools is minor, possibly because only about 70% of the releases' metadata contain repository information. Similar to other metadata-based tools, our Metadata-based Retriever will retrieve incorrect links when 1) the metadata does not contain a correct repository URL, or 2) the metadata contains a correct repository URL but the retriever selects another URL. Therefore, we design the Source Code Repository Validator to validate the correctness of the repository information retrieved by the Metadata-based Retriever.



 §.§ Source Code Repository Validator



  §.§.§ Design

The goal of this component is to validate the correctness of the repository information retrieved from the metadata. We design it as a classifier where the input is a pair of a release and a repository and the output is the probability of the input being an incorrect link.
Inspired by the findings of RQ2 (Section <ref>) and prior work <cit.>, we derive six crafted features (Table <ref>).

    
  * According to Section <ref>, the correct link and incorrect link differ a lot on the number of phantom Python files and whether the package specification file setup.py or pyproject.toml changes. Therefore, we propose the #phantom_pyfiles and pkg_spec_change feature.
    
  * Prior work <cit.> manually checked the alignment of the repository tags and PyPI releases' version identifiers to determine a reliable repository for a release. After manually inspecting the release's version identifier and the repository's tag in some correct links, we find that the repository tags usually end with the release's version identifier (e.g., v1.2.1 and 1.2.1). Therefore, we propose the tag_alignment feature which is set to 1 if any tag in the repository ends with the release's version identifier otherwise 0.
    
  * Name similarity is also used to determine a release's reliable repository <cit.> and identify typosquatting packages <cit.>. Therefore, we consider the name_similarity feature useful for validating the correctness of the release's repository information as well. This feature is measured by the normalized Levenshtein similarity <cit.> between the package name and the repository name, ranging from [0, 1].
    
  * We also take the release's maintainer information into account, i.e., the #maintainers and #maintainer_pkgs feature. Intuitively, if a package is maintained by more experienced developers, it is less likely to declare incorrect repository information.




We collect the six features for each link in the Package-Repository Link dataset,[We only select the latest release for each package.] including 14,375 correct links (labeled as 0) and 2,064 incorrect links (labeled as 1). Then we train machine learning models on the collected features. Specifically, we try seven commonly used models including Logistic Regression, SVM, Decision Tree, Random Forest, AdaBoost <cit.>, Gradient Boosting Decision Tree <cit.>, and XGBoost <cit.>. Due to the imbalanced distribution of correct and incorrect links in the dataset, we employ resampling techniques on the training set for all models, which is a common practice to address the issue of unbalanced samples <cit.>. We tune hyperparameters for each model with grid searching and select the best-performing model. Since the dataset is imbalanced and the relative ranking of incorrect links matters more, we choose AUC (Area under the ROC Curve) <cit.> as the performance metric. AUC provides an evaluation of the model's performance across various classification thresholds and quantifies the probability that a random positive sample will have a higher ranking than a random negative sample <cit.>.





  §.§.§ Evaluation

Table <ref> presents the optimal performance of each model in identifying the incorrect link. We also present the accuracy, precision, and recall at a threshold of 0.5 as a reference.
From Table <ref>, we can observe that either model archives an AUC higher than 0.95, possibly indicating the effectiveness of the six features. Random Forest outperforms the other models with an AUC of 0.995. It also achieves the highest recall score (0.989), suggesting that it can discover the most incorrect links in the test set. So we choose it as the classification model of this component. We also perform feature importance analysis to demonstrate how important each feature is for the fitted Random Forest model. Specifically, we use the permutation importance <cit.>, a well-known technique to measure the contribution of each feature to the fitted model. It is calculated by randomly shuffling the values of a feature and observing the resulting degradation of the model’s score. The results show that name_similarity is the most predictive feature (importance value: 0.117) followed by pkg_spec_change (importance value: 0.028) and #phantom_pyfiles (importance value: 0.026). The importance scores for the remaining three features are all below 0.010.



We then use this component to validate the repository information retrieved by the Metadata-based Retriever. The Metadata-based Retriever successfully retrieves repository information for 3,047,112 releases (273,273 packages). We exclude packages in the Package-Repository Link dataset and select the latest release that provides the source distribution for each package, resulting in 228,448 releases.
We then use the trained Random Forest model to output the probability of the link between the release and the retrieved repository being an incorrect link.
We manually inspect the top 100 links with the highest probability and find that 85 (85%) of these links are indeed incorrect. For the remaining 15 correct links, we find the package name differs a lot from the repository name (name_similarity < 0.25), which may lead to a high probability.



 §.§ Source Code-based Retriever



  §.§.§ Design

This component relies on the World of Code (WoC) <cit.> infrastructure due to its extensive collection of public repositories and convenient APIs. However, the millions of repositories in WoC pose a great challenge in efficiently locating a release's correct repository based on source code. To tackle this challenge, we propose a simple and efficient file hash-based algorithm based on the findings of RQ2. Specifically, this component retrieves a release's repository from WoC using Python files in its source distribution. We only use Python files since most of them are present in both the release's source distribution and the release's repository (Section <ref>), thus establishing a good link between the release and the repository. We use correct links in the Package-Repository Link dataset to design and evaluate this component. Among the 14,375 correct links, the repositories of 12,375 (86.1%) links are indexed by WoC.

This component first retrieves candidate repositories from WoC following the get_candidate function in Algorithm <ref>. For each Python file in the release's source distribution, it gets the first commit that introduces this file via the blob-to-commit database (line 4-5). Then it gets all repositories containing this commit (thus the file) via the commit-to-repository database (line 6).
To speed up the retrieval and reduce the candidate set, we only consider files that do not exist in many repositories controlled by a threshold blob_uniqueness (line 7-8). Finally, we rank candidate repositories by the number of Python files in the source distribution that they contain.



To select the correct candidate, we manually inspect 373 links (95% confidence level and 5% confidence interval) from the 12,375 links and find that the top-ranked candidates are either the correct repository or forks of the correct repository in most (360, 96.5%) links. Therefore, we choose the topn candidate repositories, find their upstream forked repository, and select the most common repository.
To ensure the correctness of the retrieved repository, we only return the repository whose name similarity with the release's package name is above a threshold name_similarity.
Increasing the threshold improves the accuracy but reduces the percentage of releases for which this component can retrieve repositories from WoC (i.e., the coverage), while decreasing it increases the coverage but reduces the accuracy.
We heuristically set blob_uniqueness = 500, topn = 5, name_similarity = 0.5, which we find produce satisfactory results.




  §.§.§ Evaluation

We evaluate the algorithm on the 12,375 correct links.[For each link, we use the package's latest release before October 2021, the time when the WoC version U data was collected.] The algorithm can successfully retrieve repository information from WoC for 11,165 releases (i.e., coverage: 0.902) with an accuracy of 0.970.
Table <ref> shows the retrieval accuracy and coverage under different name_similarity setting.
When setting name_similarity as 1, the accuracy increases to 0.986 but the coverage decreases to 0.757; when setting name_similarity as 0, the coverage increases to 0.986 but the accuracy decreases to 0.930. Therefore, we set name_similarity as 0.5 to strike a balance between retrieval coverage and accuracy.
We run this component on the rest releases for which the Metadata-based Retriever can not retrieve repositories. We only select the latest release before October 2021 for each package, resulting in 81,751 releases. This component successfully retrieves repository information for 32,139 (39.3%) releases from WoC. The relatively low ratio may be attributed to the fact that many releases have repositories that are either not public or not indexed by WoC.
We manually inspect 100 releases and find that this component correctly retrieves repository information for 90 releases, yielding an accuracy of 90%. On average, it takes 40 seconds to complete a repository retrieval, suggesting its high efficiency.

The Metadata-based Retriever and Source Code-based Retriever retrieve repository information using the release's metadata and source distribution, respectively. Therefore, we compare their retrieval results to further validate the two components. Specifically, the Metadata-based Retriever finds repository URLs for 3,047,112 releases of 273,273 packages. To conduct the comparison, we first select the most recent release before October 2021 (the time of WoC U version data collection) for each package. Then, we keep releases that 1) provide a source distribution for the Source Code-based Retriever to use and 2) have their repository retrieved by the Metadata-based Retriever indexed by WoC. Finally, we obtain 173,809 releases. The Source Code-based Retriever successfully retrieves repository URLs for 143,035 (82.3%) of the selected releases, with 131,710 (92.1%) the same as the repository URLs retrieved by the Metadata-based Retriever, indicating a high consistency between the results of the two components.






 §.§ Overall Evaluation


We evaluate PyRadar on the Package-Repository Link dataset with 14,375 correct and 2,064 incorrect links. For a release in the correct link, the expected output is the repository URL in the link. For a release in the incorrect link, the expected output is empty since there is no sufficient information to manually pinpoint its exact repository. As a result, PyRadar achieves an accuracy of 0.88.



§ LIMITATIONS


Several limitations pertain to the Package-Repository Link dataset. First, we rely on the black-box GitHub Dependency Graph to collect correct links. Therefore, we can not guarantee the accuracy of GDG data.
To alleviate this threat, we carefully select popular Python repositories and conduct a manual evaluation to confirm the validity of the collected data.
Second, the correct links are skewed towards popular packages and popular repositories, which may compromise the representativeness of the data. However, considering the number (14 375, 3.4% of all PyPI packages) and the monthly downloads (ranging from 28 to 1.02 million) of the collected packages, we believe the collected data are sufficiently representative.
Third, we assume a link is incorrect where the package is linked to a repository that is the same as the repository in the correct link but with a different maintainer.
The assumption has not been systematically tested and may threaten the validity of the collected data. We conduct a manual evaluation of the collected data to alleviate this threat.

In terms of the empirical study, its main threat is the reimplementation of the four tools. To alleviate this threat, we borrow test cases from the original tools to ensure the consistency of the reimplemented tools with the original ones. Also, due to the complexity of Git, the implementation of the repository traversal algorithm may threaten the internal validity. We use as many git native operations as possible to ensure the correctness of the implementation. Therefore, we believe the empirical study is conducted on a solid basis of correct implementation.

Despite the three most popular code hosting platforms considered by the Metadata-based Retriever, the package's source code repository may be hosted on other platforms such as SourceForge and other self-hosted platforms, e.g., https://gitlab.inria.fr/GitLab at Inria. However, this component can be easily extended by adding new regular expressions to match repositories on these platforms.
The major limitation of the Source Code-based Retriever is the dependence on the external infrastructure, WoC. Despite the relatively complete collection of open source Git repositories in WoC, it is impossible for WoC to contain all repositories.
Besides, the several-month update delay of WoC means that the Source Code-based Retriever can only be run periodically to retrieve repository information for releases uploaded to PyPI during the update interval. Despite these limitations, we believe WoC is still the most suitable infrastructure for our tool.
Finally,   fails to retrieve a package's repository when 1) the package's repository is not public, e.g., hosted locally or privately. 2) the package's repository is public but is neither declared in the metadata nor indexed by WoC.

Due to the different usage scenarios and the challenge of automatically and accurately collecting ground truth, i.e., correct and incorrect package-repository links, the components are evaluated on different datasets, which may induce the overfitting issue. To evaluate the generalization of the second and third components, we run the second component against 228,448 package-repository links from the first component and run the third component against 81,751 releases for which the first component fails to retrieve repository information, which align with their practical usage scenarios. The manual inspection reveals that the two components achieve an accuracy of 85% and 90% respectively, suggesting the overfitting issue induced by different evaluation datasets is minor.

In terms of external validity, the dataset collection approach is dedicated to PyPI. We believe the correct link collection part can be generalized to other package registries since GDG supports multiple packaging tools. However, the incorrect link collection needs further research due to the differences in the package management practices adopted by different package registries <cit.>.
The empirical findings can not be generalized to other package registries, too. However, the repository traversal algorithm can be applied to any repository, laying a foundation for future work on other package registries. Despite the specific design of   for PyPI packages, the framework is general and can be adapted to other package registries similar to PyPI (e.g., providing metadata and source distributions).



§ DISCUSSION




 §.§ Comparison with Related Work

The most similar work to ours is <cit.>. There are two noteworthy differences between our approach and theirs. First, our approach and <cit.> serve different purposes.  <cit.> targets the problem of mapping Debian source packages written in Python to PyPI packages, and our approach targets the problem of locating a PyPI package's code repository, which is more intricate due to the sophisticated Git-based software development <cit.> and a significantly larger retrieval corpus (244 thousand PyPI packages vs. 173 million repositories).

Second, due to different goals,  <cit.> and the Source Code-based Retriever in our approach adopt different means but overlap in some particular steps in the whole process. Specifically,  <cit.> involves three steps: 1) index: indexing global identifiers (i.e., class names and function names) defined in PyPI packages; 2) retrieval: retrieving candidate PyPI packages with three random identifiers from a random Python file in the Debian package; 3) selection: selecting the most popular candidate using the SourceRank metric. Our Source Code-based Retriever also has the retrieval and selection steps, but is superior in three aspects related to our problem:


    
  * Our retriever does not require the time-consuming identifier indexing step. The phantom file analysis reveals that Python files are rarely phantom files in correct package-repository links. It suggests that querying candidate repositories with the hashes of Python files in the package is sufficient and does not require the time-consuming identifier indexing step that would take months for the 12.4 billion blobs in WoC.
    
  * Our retriever utilizes more information to retrieve candidates. First, querying with a Python file's hash, as conducted in our retriever, is equivalent to querying with all identifiers in it, while  <cit.> only queries with three identifiers. Second, our retriever uses all Python files, while  <cit.> uses only a random Python file.
    
  * Our approach selects the final candidate more suitably. First, the SourceRank metric used by <cit.> is unsuitable for ranking repositories due to its inclusion of many package-specific factors, such as the presence of a link to the source code. Therefore, the approach in  <cit.> does not apply to our problem. Second,  <cit.> selects the most popular candidate, whereas our retriever selects the most similar candidate to the package (measured by the number of matched Python files), which better suits our retrieval problem.




 §.§ The Feasibility of Name-matching Approach

Although the package name and repository name are the same in 11,408 (79.36%) correct links, the name-matching approach is still insufficient for validating and locating a release's repository for three reasons.
First, it is common that a package name differs from its repository name, as evidenced by the 20.64% of correct links, where the name-matching approach fails to retrieve the correct repository as a candidate.
Second, even if the correct repository is retrieved as a candidate, the presence of many repositories with the same name necessitates further selection of the correct one. Specifically, the median number of repositories in WoC that have the same name as packages in the 14,375 correct links is 24.
Third, when validating the correctness of the remaining 5,031 links, the AUC of using only the name_similarity feature is 0.563, while using all six features yields an AUC of 0.979, suggesting the effectiveness and necessity of the remaining five features.



 §.§ Implication

Our research highlights the following future improvements in retrieving and validating the release's repository information.

Facilitate account linking between code hosting platforms and package registries. Cross-linking accounts can largely alleviate the problem of unavailable or incorrect repository information. On the one hand, package registries and code hosting platforms may collaboratively establish account binding or account authorization login mechanisms. On the other hand, to the best of our knowledge, account cross-linking tools between code hosting platforms and package registries are still lacking. Future work can bridge this gap.

Alert users to potentially incorrect repository information of the release. Package registries can integrate repository information validation mechanisms and display validation results on the package's PyPI page and in the metadata, which can be consumed by package managers and related package monitoring tools to alert users when searching for, assessing, or installing packages.

Conduct code analysis to identify package names built from a repository. As discussed in Section <ref>, our validator does not perform well in cases where the package name differs from the repository name greatly. To alleviate this issue, future work may explore code analysis techniques to precisely parse the package names built from the repository, which will benefit both the validation and retrieval of the release's repository information.




§ CONCLUSION

A package's source code repository is critical for the use and risk monitoring of the package. However, the package's metadata may not contain or contain wrong repository information. In this paper, we collect 4,227,425 PyPI releases' metadata, 14,375 correct package-repository links, and 2,064 incorrect links. Then we systematically compare four existing metadata-based tools and investigate phantom file differences between correct and incorrect links. Inspired by the empirical findings, we propose , a novel framework that utilizes the PyPI release's metadata and source distribution to automatically retrieve and validate the release's repository information. We believe our work can help both practitioners and researchers better use PyPI packages. We provide a replication package at <https://github.com/gaokai320/PyRadar>.


This work is sponsored by the National Natural Science Foundation of China 61825201 and 62332001.


ACM-Reference-Format


