Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env perl
- use strict;
- use warnings;
- # This script is a (probably naive) attempt at writing a recursive dependency resolver for the Python package index (PyPi)
- # A list of (space seperated) Python Package names provided on the command line are the starting point
- # Each package in that list is added to a graph, then every node(vertex) in that graph has edges defined between the node itself
- # and each of it's dependencies (which become their own nodes as a result)
- # Every node in the graph is iterated through, has it's dependencies(edges) defined, and the process is repeated until
- # the graph stops changing. Once there are no more dependencies to find, it prints out a (alphabetically sorted) list
- # of every package that would be required to install every package given as an argument to this script. Note that this list
- # WILL INCLUDE the packages that were initially provided as part of the list.
- use JSON;
- use Graph;
- # Our main dependency graph objects
- # We need two so we can check if the graph changed between dependency runs
- # When the two graphs stay the same after a dependency run, we know our graph is complete
- my $Agraph = Graph->new();
- my $Bgraph = Graph->new();
- # Accepts a list of python packages to check dependencies for
- # Returns a list of python packages the arguments depend upon
- # Note that this function is NOT RECURSIVE. It ONLY provides the direct dependencies.
- sub get_deps {
- my $ret = [];
- my $json = JSON->new;
- foreach my $package ( @_ ) {
- my $curl = `curl -s "https://pypi.org/pypi/$package/json"`;
- my $reqs = $json->decode($curl)->{info}->{requires_dist};
- if (defined($reqs)) {
- foreach my $dep (@$reqs) {
- $dep =~ s/[^a-zA-Z0-9-].*$//;
- push(@$ret, $dep);
- }
- }
- }
- return $ret;
- }
- # @ARGV is a list of packages we need to find all dependencies for and is the roots of our dependency graph
- foreach my $package (@ARGV) {
- $Agraph->add_vertex($package);
- }
- # A list of packages we have already gotten dependnecies for so we don't check twice
- my $checked = [];
- # Loop until our graphs stop changing between dependency runs
- while ( $Agraph ne $Bgraph ) {
- $Bgraph = $Agraph->deep_copy();
- # Check every single vertice in our graph
- my @vertlist = $Agraph->vertices;
- foreach my $package (@vertlist) {
- # If we haven't checked this package before, get it added to the graph with all of it's dependencies
- if (! grep( /^$package$/, @$checked )) {
- my $deplist = get_deps($package);
- foreach my $dep (@$deplist) {
- $Agraph->add_edge($package, $dep);
- }
- # Add this package to our list of already checked packages so we don't waste time
- push(@$checked, $package);
- }
- }
- }
- my @fulldeplist = sort $Agraph->vertices;
- foreach my $package (@fulldeplist) {
- print "$package\n";
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement