license_finder 5.11.1 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/CHANGELOG.md +25 -0
- data/CONTRIBUTING.md +1 -1
- data/Dockerfile +9 -14
- data/LICENSE +1 -1
- data/README.md +18 -18
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/license_finder_pip.py +6 -2
- data/ci/pipelines/pull-request.yml.erb +14 -0
- data/ci/pipelines/release.yml.erb +24 -0
- data/lib/license_finder/cli.rb +2 -2
- data/lib/license_finder/cli/approvals.rb +1 -0
- data/lib/license_finder/cli/dependencies.rb +3 -2
- data/lib/license_finder/cli/main.rb +8 -8
- data/lib/license_finder/cli/makes_decisions.rb +3 -0
- data/lib/license_finder/cli/permitted_licenses.rb +32 -0
- data/lib/license_finder/cli/restricted_licenses.rb +32 -0
- data/lib/license_finder/core.rb +1 -1
- data/lib/license_finder/decision_applier.rb +6 -6
- data/lib/license_finder/decisions.rb +19 -19
- data/lib/license_finder/license_aggregator.rb +2 -2
- data/lib/license_finder/package.rb +15 -15
- data/lib/license_finder/package_manager.rb +1 -0
- data/lib/license_finder/package_managers/bundler.rb +3 -1
- data/lib/license_finder/package_managers/composer.rb +1 -1
- data/lib/license_finder/package_managers/pip.rb +11 -19
- data/lib/license_finder/package_managers/pipenv.rb +63 -0
- data/lib/license_finder/package_utils/pypi.rb +41 -0
- data/lib/license_finder/packages/merged_package.rb +2 -2
- data/lib/license_finder/reports/templates/html_report.erb +2 -2
- data/lib/license_finder/reports/templates/markdown_report.erb +2 -2
- data/lib/license_finder/scanner.rb +4 -2
- data/lib/license_finder/shared_helpers/common_path.rb +3 -1
- data/license_finder.gemspec +5 -6
- metadata +15 -14
- data/lib/license_finder/cli/blacklist.rb +0 -32
- data/lib/license_finder/cli/whitelist.rb +0 -32
| @@ -8,9 +8,10 @@ module LicenseFinder | |
| 8 8 |  | 
| 9 9 | 
             
                  method_option :approve, type: :boolean, desc: 'Approve the added dependency'
         | 
| 10 10 | 
             
                  method_option :homepage, type: :string, desc: 'Source of the added dependency'
         | 
| 11 | 
            +
             | 
| 11 12 | 
             
                  auditable
         | 
| 12 | 
            -
                  desc 'add DEPENDENCY LICENSE  | 
| 13 | 
            -
                  def add(name, license, version | 
| 13 | 
            +
                  desc 'add DEPENDENCY LICENSE VERSION [--homepage=HOMEPAGE] [--approve]', 'Add a dependency that is not managed by a package manager, optionally approving it at the same time'
         | 
| 14 | 
            +
                  def add(name, license, version)
         | 
| 14 15 | 
             
                    modifying do
         | 
| 15 16 | 
             
                      decisions
         | 
| 16 17 | 
             
                        .add_package(name, version, txn)
         | 
| @@ -107,7 +107,7 @@ module LicenseFinder | |
| 107 107 | 
             
                    finder = LicenseAggregator.new(config, aggregate_paths)
         | 
| 108 108 | 
             
                    any_packages = finder.any_packages?
         | 
| 109 109 | 
             
                    unapproved = finder.unapproved
         | 
| 110 | 
            -
                     | 
| 110 | 
            +
                    restricted = finder.restricted
         | 
| 111 111 |  | 
| 112 112 | 
             
                    # Ensure to start output on a new line even with dot progress indicators.
         | 
| 113 113 | 
             
                    say "\n"
         | 
| @@ -120,12 +120,12 @@ module LicenseFinder | |
| 120 120 | 
             
                    if unapproved.empty?
         | 
| 121 121 | 
             
                      say 'All dependencies are approved for use', :green
         | 
| 122 122 | 
             
                    else
         | 
| 123 | 
            -
                      unless  | 
| 124 | 
            -
                        say ' | 
| 125 | 
            -
                        say report_of( | 
| 123 | 
            +
                      unless restricted.empty?
         | 
| 124 | 
            +
                        say 'Restricted dependencies:', :red
         | 
| 125 | 
            +
                        say report_of(restricted)
         | 
| 126 126 | 
             
                      end
         | 
| 127 127 |  | 
| 128 | 
            -
                      other_unapproved = unapproved -  | 
| 128 | 
            +
                      other_unapproved = unapproved - restricted
         | 
| 129 129 | 
             
                      unless other_unapproved.empty?
         | 
| 130 130 | 
             
                        say 'Dependencies that need approval:', :yellow
         | 
| 131 131 | 
             
                        say report_of(other_unapproved)
         | 
| @@ -165,11 +165,11 @@ module LicenseFinder | |
| 165 165 |  | 
| 166 166 | 
             
                  subcommand 'dependencies', Dependencies, 'Add or remove dependencies that your package managers are not aware of'
         | 
| 167 167 | 
             
                  subcommand 'licenses', Licenses, "Set a dependency's licenses, if the licenses found by license_finder are missing or wrong"
         | 
| 168 | 
            -
                  subcommand 'approvals', Approvals, 'Manually approve dependencies, even if their licenses are not  | 
| 168 | 
            +
                  subcommand 'approvals', Approvals, 'Manually approve dependencies, even if their licenses are not permitted'
         | 
| 169 169 | 
             
                  subcommand 'ignored_groups', IgnoredGroups, 'Exclude test and development dependencies from action items and reports'
         | 
| 170 170 | 
             
                  subcommand 'ignored_dependencies', IgnoredDependencies, 'Exclude individual dependencies from action items and reports'
         | 
| 171 | 
            -
                  subcommand ' | 
| 172 | 
            -
                  subcommand ' | 
| 171 | 
            +
                  subcommand 'permitted_licenses', PermittedLicenses, 'Automatically approve any dependency that has a permitted license'
         | 
| 172 | 
            +
                  subcommand 'restricted_licenses', RestrictedLicenses, 'Forbid approval of any dependency whose licenses are all restricted'
         | 
| 173 173 | 
             
                  subcommand 'project_name', ProjectName, 'Set the project name, for display in reports'
         | 
| 174 174 |  | 
| 175 175 | 
             
                  private
         | 
| @@ -11,6 +11,9 @@ module LicenseFinder | |
| 11 11 | 
             
                    def auditable
         | 
| 12 12 | 
             
                      method_option :who, desc: 'The person making this decision'
         | 
| 13 13 | 
             
                      method_option :why, desc: 'The reason for making this decision'
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    def approvable
         | 
| 14 17 | 
             
                      method_option :version, desc: 'The version that will be approved'
         | 
| 15 18 | 
             
                    end
         | 
| 16 19 | 
             
                  end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LicenseFinder
         | 
| 4 | 
            +
              module CLI
         | 
| 5 | 
            +
                class PermittedLicenses < Base
         | 
| 6 | 
            +
                  extend Subcommand
         | 
| 7 | 
            +
                  include MakesDecisions
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  desc 'list', 'List all the permitted licenses'
         | 
| 10 | 
            +
                  def list
         | 
| 11 | 
            +
                    say 'Permitted Licenses:', :blue
         | 
| 12 | 
            +
                    say_each(decisions.permitted, &:name)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  auditable
         | 
| 16 | 
            +
                  desc 'add LICENSE...', 'Add one or more licenses to the permitted licenses'
         | 
| 17 | 
            +
                  def add(*licenses)
         | 
| 18 | 
            +
                    assert_some licenses
         | 
| 19 | 
            +
                    modifying { licenses.each { |l| decisions.permit(l, txn) } }
         | 
| 20 | 
            +
                    say "Added #{licenses.join(', ')} to the permitted licenses"
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  auditable
         | 
| 24 | 
            +
                  desc 'remove LICENSE...', 'Remove one or more licenses from the permitted licenses'
         | 
| 25 | 
            +
                  def remove(*licenses)
         | 
| 26 | 
            +
                    assert_some licenses
         | 
| 27 | 
            +
                    modifying { licenses.each { |l| decisions.unpermit(l, txn) } }
         | 
| 28 | 
            +
                    say "Removed #{licenses.join(', ')} from the license permitted licenses"
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module LicenseFinder
         | 
| 4 | 
            +
              module CLI
         | 
| 5 | 
            +
                class RestrictedLicenses < Base
         | 
| 6 | 
            +
                  extend Subcommand
         | 
| 7 | 
            +
                  include MakesDecisions
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  desc 'list', 'List all the restricted licenses'
         | 
| 10 | 
            +
                  def list
         | 
| 11 | 
            +
                    say 'Restricted Licenses:', :blue
         | 
| 12 | 
            +
                    say_each(decisions.restricted, &:name)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  auditable
         | 
| 16 | 
            +
                  desc 'add LICENSE...', 'Add one or more licenses to the restricted licenses'
         | 
| 17 | 
            +
                  def add(*licenses)
         | 
| 18 | 
            +
                    assert_some licenses
         | 
| 19 | 
            +
                    modifying { licenses.each { |l| decisions.restrict(l, txn) } }
         | 
| 20 | 
            +
                    say "Added #{licenses.join(', ')} to the restricted licenses"
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  auditable
         | 
| 24 | 
            +
                  desc 'remove LICENSE...', 'Remove one or more licenses from the restricted licenses'
         | 
| 25 | 
            +
                  def remove(*licenses)
         | 
| 26 | 
            +
                    assert_some licenses
         | 
| 27 | 
            +
                    modifying { licenses.each { |l| decisions.unrestrict(l, txn) } }
         | 
| 28 | 
            +
                    say "Removed #{licenses.join(', ')} from the restricted licenses"
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/license_finder/core.rb
    CHANGED
    
    | @@ -42,7 +42,7 @@ module LicenseFinder | |
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 44 | 
             
                extend Forwardable
         | 
| 45 | 
            -
                def_delegators :decision_applier, :acknowledged, :unapproved, : | 
| 45 | 
            +
                def_delegators :decision_applier, :acknowledged, :unapproved, :restricted, :any_packages?
         | 
| 46 46 |  | 
| 47 47 | 
             
                def project_name
         | 
| 48 48 | 
             
                  decisions.project_name || config.project_path.basename.to_s
         | 
| @@ -14,8 +14,8 @@ module LicenseFinder | |
| 14 14 | 
             
                  acknowledged.reject(&:approved?)
         | 
| 15 15 | 
             
                end
         | 
| 16 16 |  | 
| 17 | 
            -
                def  | 
| 18 | 
            -
                  acknowledged.select(&: | 
| 17 | 
            +
                def restricted
         | 
| 18 | 
            +
                  acknowledged.select(&:restricted?)
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 21 | 
             
                def any_packages?
         | 
| @@ -53,12 +53,12 @@ module LicenseFinder | |
| 53 53 | 
             
                end
         | 
| 54 54 |  | 
| 55 55 | 
             
                def with_approval(package)
         | 
| 56 | 
            -
                  if package.licenses.all? { |license| decisions. | 
| 57 | 
            -
                    package. | 
| 56 | 
            +
                  if package.licenses.all? { |license| decisions.restricted?(license) }
         | 
| 57 | 
            +
                    package.restricted!
         | 
| 58 58 | 
             
                  elsif decisions.approved?(package.name, package.version)
         | 
| 59 59 | 
             
                    package.approved_manually!(decisions.approval_of(package.name, package.version))
         | 
| 60 | 
            -
                  elsif package.licenses.any? { |license| decisions. | 
| 61 | 
            -
                    package. | 
| 60 | 
            +
                  elsif package.licenses.any? { |license| decisions.permitted?(license) }
         | 
| 61 | 
            +
                    package.permitted!
         | 
| 62 62 | 
             
                  end
         | 
| 63 63 | 
             
                  package
         | 
| 64 64 | 
             
                end
         | 
| @@ -6,7 +6,7 @@ module LicenseFinder | |
| 6 6 | 
             
                # READ
         | 
| 7 7 | 
             
                ######
         | 
| 8 8 |  | 
| 9 | 
            -
                attr_reader :packages, : | 
| 9 | 
            +
                attr_reader :packages, :permitted, :restricted, :ignored, :ignored_groups, :project_name
         | 
| 10 10 |  | 
| 11 11 | 
             
                def licenses_of(name)
         | 
| 12 12 | 
             
                  @licenses[name]
         | 
| @@ -36,12 +36,12 @@ module LicenseFinder | |
| 36 36 | 
             
                  end
         | 
| 37 37 | 
             
                end
         | 
| 38 38 |  | 
| 39 | 
            -
                def  | 
| 40 | 
            -
                  @ | 
| 39 | 
            +
                def permitted?(lic)
         | 
| 40 | 
            +
                  @permitted.include?(lic)
         | 
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 | 
            -
                def  | 
| 44 | 
            -
                  @ | 
| 43 | 
            +
                def restricted?(lic)
         | 
| 44 | 
            +
                  @restricted.include?(lic)
         | 
| 45 45 | 
             
                end
         | 
| 46 46 |  | 
| 47 47 | 
             
                def ignored?(name)
         | 
| @@ -68,8 +68,8 @@ module LicenseFinder | |
| 68 68 | 
             
                  @licenses = Hash.new { |h, k| h[k] = Set.new }
         | 
| 69 69 | 
             
                  @homepages = {}
         | 
| 70 70 | 
             
                  @approvals = {}
         | 
| 71 | 
            -
                  @ | 
| 72 | 
            -
                  @ | 
| 71 | 
            +
                  @permitted = Set.new
         | 
| 72 | 
            +
                  @restricted = Set.new
         | 
| 73 73 | 
             
                  @ignored = Set.new
         | 
| 74 74 | 
             
                  @ignored_groups = Set.new
         | 
| 75 75 | 
             
                end
         | 
| @@ -120,27 +120,27 @@ module LicenseFinder | |
| 120 120 | 
             
                  self
         | 
| 121 121 | 
             
                end
         | 
| 122 122 |  | 
| 123 | 
            -
                def  | 
| 124 | 
            -
                  @decisions << [: | 
| 125 | 
            -
                  @ | 
| 123 | 
            +
                def permit(lic, txn = {})
         | 
| 124 | 
            +
                  @decisions << [:permit, lic, txn]
         | 
| 125 | 
            +
                  @permitted << License.find_by_name(lic)
         | 
| 126 126 | 
             
                  self
         | 
| 127 127 | 
             
                end
         | 
| 128 128 |  | 
| 129 | 
            -
                def  | 
| 130 | 
            -
                  @decisions << [: | 
| 131 | 
            -
                  @ | 
| 129 | 
            +
                def unpermit(lic, txn = {})
         | 
| 130 | 
            +
                  @decisions << [:unpermit, lic, txn]
         | 
| 131 | 
            +
                  @permitted.delete(License.find_by_name(lic))
         | 
| 132 132 | 
             
                  self
         | 
| 133 133 | 
             
                end
         | 
| 134 134 |  | 
| 135 | 
            -
                def  | 
| 136 | 
            -
                  @decisions << [: | 
| 137 | 
            -
                  @ | 
| 135 | 
            +
                def restrict(lic, txn = {})
         | 
| 136 | 
            +
                  @decisions << [:restrict, lic, txn]
         | 
| 137 | 
            +
                  @restricted << License.find_by_name(lic)
         | 
| 138 138 | 
             
                  self
         | 
| 139 139 | 
             
                end
         | 
| 140 140 |  | 
| 141 | 
            -
                def  | 
| 142 | 
            -
                  @decisions << [: | 
| 143 | 
            -
                  @ | 
| 141 | 
            +
                def unrestrict(lic, txn = {})
         | 
| 142 | 
            +
                  @decisions << [:unrestrict, lic, txn]
         | 
| 143 | 
            +
                  @restricted.delete(License.find_by_name(lic))
         | 
| 144 144 | 
             
                  self
         | 
| 145 145 | 
             
                end
         | 
| 146 146 |  | 
| @@ -48,8 +48,8 @@ module LicenseFinder | |
| 48 48 | 
             
                  @groups = options[:groups] || []
         | 
| 49 49 |  | 
| 50 50 | 
             
                  ## APPROVAL
         | 
| 51 | 
            -
                  @ | 
| 52 | 
            -
                  @ | 
| 51 | 
            +
                  @permitted = false
         | 
| 52 | 
            +
                  @restricted = false
         | 
| 53 53 | 
             
                  @manual_approval = nil
         | 
| 54 54 |  | 
| 55 55 | 
             
                  ## LICENSING
         | 
| @@ -78,26 +78,26 @@ module LicenseFinder | |
| 78 78 | 
             
                end
         | 
| 79 79 |  | 
| 80 80 | 
             
                def approved?
         | 
| 81 | 
            -
                  # Question: is `! | 
| 82 | 
            -
                  # DecisionApplier does not call ` | 
| 83 | 
            -
                  # if a Package has been  | 
| 84 | 
            -
                  (approved_manually? ||  | 
| 81 | 
            +
                  # Question: is `!restricted?` redundant?
         | 
| 82 | 
            +
                  # DecisionApplier does not call `permitted!` or `approved_manually!`
         | 
| 83 | 
            +
                  # if a Package has been restricted.
         | 
| 84 | 
            +
                  (approved_manually? || permitted?) && !restricted?
         | 
| 85 85 | 
             
                end
         | 
| 86 86 |  | 
| 87 | 
            -
                def  | 
| 88 | 
            -
                  @ | 
| 87 | 
            +
                def permitted!
         | 
| 88 | 
            +
                  @permitted = true
         | 
| 89 89 | 
             
                end
         | 
| 90 90 |  | 
| 91 | 
            -
                def  | 
| 92 | 
            -
                  @ | 
| 91 | 
            +
                def permitted?
         | 
| 92 | 
            +
                  @permitted
         | 
| 93 93 | 
             
                end
         | 
| 94 94 |  | 
| 95 | 
            -
                def  | 
| 96 | 
            -
                  @ | 
| 95 | 
            +
                def restricted!
         | 
| 96 | 
            +
                  @restricted = true
         | 
| 97 97 | 
             
                end
         | 
| 98 98 |  | 
| 99 | 
            -
                def  | 
| 100 | 
            -
                  @ | 
| 99 | 
            +
                def restricted?
         | 
| 100 | 
            +
                  @restricted
         | 
| 101 101 | 
             
                end
         | 
| 102 102 |  | 
| 103 103 | 
             
                attr_reader :manual_approval
         | 
| @@ -125,7 +125,7 @@ module LicenseFinder | |
| 125 125 | 
             
                attr_reader :install_path # checked in tests, otherwise private
         | 
| 126 126 |  | 
| 127 127 | 
             
                def licenses
         | 
| 128 | 
            -
                  @licenses ||= activations.map(&:license).to_set
         | 
| 128 | 
            +
                  @licenses ||= activations.map(&:license).sort_by(&:name).to_set
         | 
| 129 129 | 
             
                end
         | 
| 130 130 |  | 
| 131 131 | 
             
                def activations
         | 
| @@ -152,6 +152,7 @@ require 'license_finder/package_managers/bundler' | |
| 152 152 | 
             
            require 'license_finder/package_managers/npm'
         | 
| 153 153 | 
             
            require 'license_finder/package_managers/yarn'
         | 
| 154 154 | 
             
            require 'license_finder/package_managers/pip'
         | 
| 155 | 
            +
            require 'license_finder/package_managers/pipenv'
         | 
| 155 156 | 
             
            require 'license_finder/package_managers/maven'
         | 
| 156 157 | 
             
            require 'license_finder/package_managers/mix'
         | 
| 157 158 | 
             
            require 'license_finder/package_managers/cocoa_pods'
         | 
| @@ -24,7 +24,9 @@ module LicenseFinder | |
| 24 24 | 
             
                end
         | 
| 25 25 |  | 
| 26 26 | 
             
                def prepare_command
         | 
| 27 | 
            -
                  ' | 
| 27 | 
            +
                  ignored_groups_argument = !ignored_groups.empty? ? "--without #{ignored_groups.to_a.join(' ')}" : ''
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  "bundle install #{ignored_groups_argument}".strip
         | 
| 28 30 | 
             
                end
         | 
| 29 31 |  | 
| 30 32 | 
             
                def possible_package_paths
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            require 'json'
         | 
| 4 | 
            -
            require 'net/http'
         | 
| 5 4 |  | 
| 6 5 | 
             
            module LicenseFinder
         | 
| 7 6 | 
             
              class Pip < PackageManager
         | 
| @@ -17,7 +16,7 @@ module LicenseFinder | |
| 17 16 | 
             
                    PipPackage.new(
         | 
| 18 17 | 
             
                      name,
         | 
| 19 18 | 
             
                      version,
         | 
| 20 | 
            -
                       | 
| 19 | 
            +
                      PyPI.definition(name, version),
         | 
| 21 20 | 
             
                      logger: logger,
         | 
| 22 21 | 
             
                      children: children,
         | 
| 23 22 | 
             
                      install_path: Pathname(location).join(name)
         | 
| @@ -57,24 +56,17 @@ module LicenseFinder | |
| 57 56 | 
             
                private
         | 
| 58 57 |  | 
| 59 58 | 
             
                def pip_output
         | 
| 60 | 
            -
                   | 
| 61 | 
            -
                   | 
| 62 | 
            -
                    package.values_at('name', 'version', 'dependencies', 'location')
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
                end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                def pypi_def(name, version)
         | 
| 67 | 
            -
                  response = pypi_request("https://pypi.org/pypi/#{name}/#{version}/json")
         | 
| 68 | 
            -
                  response.is_a?(Net::HTTPSuccess) ? JSON.parse(response.body).fetch('info', {}) : {}
         | 
| 69 | 
            -
                end
         | 
| 59 | 
            +
                  command = "python#{@python_version == '2' ? '' : '3'} #{LicenseFinder::BIN_PATH.join('license_finder_pip.py')} #{detected_package_path}"
         | 
| 60 | 
            +
                  stdout, stderr, status = Cmd.run(command)
         | 
| 70 61 |  | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
                   | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 62 | 
            +
                  if status.success?
         | 
| 63 | 
            +
                    JSON(stdout).map do |package|
         | 
| 64 | 
            +
                      package.values_at('name', 'version', 'dependencies', 'location')
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                  else
         | 
| 67 | 
            +
                    log_errors "LicenseFinder command '#{command}' failed:\n\t#{stderr}"
         | 
| 68 | 
            +
                    []
         | 
| 69 | 
            +
                  end
         | 
| 78 70 | 
             
                end
         | 
| 79 71 | 
             
              end
         | 
| 80 72 | 
             
            end
         | 
| @@ -0,0 +1,63 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'json'
         | 
| 4 | 
            +
            require 'license_finder/package_utils/pypi'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module LicenseFinder
         | 
| 7 | 
            +
              class Pipenv < PackageManager
         | 
| 8 | 
            +
                def initialize(options = {})
         | 
| 9 | 
            +
                  super
         | 
| 10 | 
            +
                  @lockfile = Pathname('Pipfile.lock')
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                def current_packages
         | 
| 14 | 
            +
                  @current_packages ||=
         | 
| 15 | 
            +
                    begin
         | 
| 16 | 
            +
                      packages = {}
         | 
| 17 | 
            +
                      each_dependency(groups: allowed_groups) do |name, data, group|
         | 
| 18 | 
            +
                        version = canonicalize(data['version'])
         | 
| 19 | 
            +
                        package = packages.fetch(key_for(name, version)) do |key|
         | 
| 20 | 
            +
                          packages[key] = build_package_for(name, version)
         | 
| 21 | 
            +
                        end
         | 
| 22 | 
            +
                        package.groups << group
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                      packages.values
         | 
| 25 | 
            +
                    end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def possible_package_paths
         | 
| 29 | 
            +
                  project_path ? [project_path.join(@lockfile)] : [@lockfile]
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                private
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                def each_dependency(groups: [])
         | 
| 35 | 
            +
                  dependencies = JSON.parse(IO.read(detected_package_path))
         | 
| 36 | 
            +
                  groups.each do |group|
         | 
| 37 | 
            +
                    dependencies[group].each do |name, data|
         | 
| 38 | 
            +
                      yield name, data, group
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                def canonicalize(version)
         | 
| 44 | 
            +
                  version.sub(/^==/, '')
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def build_package_for(name, version)
         | 
| 48 | 
            +
                  PipPackage.new(name, version, PyPI.definition(name, version))
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                def key_for(name, version)
         | 
| 52 | 
            +
                  "#{name}-#{version}"
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                def allowed_groups
         | 
| 56 | 
            +
                  %w[default develop] - ignored_groups.to_a
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def ignored_groups
         | 
| 60 | 
            +
                  @ignored_groups || []
         | 
| 61 | 
            +
                end
         | 
| 62 | 
            +
              end
         | 
| 63 | 
            +
            end
         |