diff options
| author | mo khan <mo.khan@gmail.com> | 2020-06-22 20:55:28 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-06-22 20:55:28 -0600 |
| commit | 1cb18873b502a5e37d4d34d91244695c98670ea6 (patch) | |
| tree | c8552e7ee0338fd38e61fca14f23cd254ec92425 | |
| parent | f4452bdfe65b8f3c943c73f66f94f78dff59cb7f (diff) | |
| parent | 2b496d743ec311f2749a6c96cab0397bf954f323 (diff) | |
Merge pull request #29 from spandx/streaming
Stream results to stdout
39 files changed, 439 insertions, 309 deletions
diff --git a/.github/licensed/bundler/oj.dep.yml b/.github/licensed/bundler/oj.dep.yml new file mode 100644 index 0000000..622bb0d --- /dev/null +++ b/.github/licensed/bundler/oj.dep.yml @@ -0,0 +1,32 @@ +--- +name: oj +version: 3.10.6 +type: bundler +summary: A fast JSON parser and serializer. +homepage: http://www.ohler.com/oj +license: mit +licenses: +- sources: LICENSE + text: | + The MIT License (MIT) + + Copyright (c) 2012 Peter Ohler + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +notices: [] diff --git a/.github/licensed/bundler/nanospinner.dep.yml b/.github/licensed/bundler/tty-cursor.dep.yml index cc6f56f..177d1c6 100644 --- a/.github/licensed/bundler/nanospinner.dep.yml +++ b/.github/licensed/bundler/tty-cursor.dep.yml @@ -1,14 +1,16 @@ --- -name: nanospinner -version: 1.0.0 +name: tty-cursor +version: 0.7.1 type: bundler -summary: A tiny commandline spinner -homepage: http://github.com/julik/nanospinner +summary: Terminal cursor positioning, visibility and text manipulation. +homepage: https://ttytoolkit.org license: mit licenses: - sources: LICENSE.txt text: | - Copyright (c) 2014 Julik Tarkhanov + Copyright (c) 2015 Piotr Murach + + MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/.github/licensed/bundler/tty-screen.dep.yml b/.github/licensed/bundler/tty-spinner.dep.yml index 1f592d7..417d94d 100644 --- a/.github/licensed/bundler/tty-screen.dep.yml +++ b/.github/licensed/bundler/tty-spinner.dep.yml @@ -1,9 +1,8 @@ --- -name: tty-screen -version: 0.7.1 +name: tty-spinner +version: 0.9.3 type: bundler -summary: Terminal screen size detection which works on Linux, OS X and Windows/Cygwin - platforms and supports MRI, JRuby and Rubinius interpreters. +summary: A terminal spinner for tasks that have non-deterministic time frame. homepage: https://ttytoolkit.org license: mit licenses: diff --git a/.rubocop.yml b/.rubocop.yml index b8ea25c..54503f6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -22,6 +22,9 @@ Layout/EndOfLine: Layout/FirstArrayElementIndentation: EnforcedStyle: consistent +Layout/FirstHashElementIndentation: + EnforcedStyle: consistent + Layout/MultilineMethodCallIndentation: Enabled: true EnforcedStyle: indented diff --git a/CHANGELOG.md b/CHANGELOG.md index db120de..8f592fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Fixed +- Process PyPI package urls with single digit versions. +- Remove unsupported `hash` report from help text. + +### Changed +- Stream output to output stream as soon as results are available. +- Switch to `Oj` for JSON parsing. +- Run spinner on background thread. ## [0.13.4] - 2020-05-26 ### Added @@ -1,6 +1,6 @@ FROM alpine:latest WORKDIR /scan -ENV PACKAGES build-base bash ruby ruby-dev ruby-json ruby-rdoc git libxml2-dev openssl-dev +ENV PACKAGES build-base bash ruby ruby-bigdecimal ruby-dev ruby-json ruby-rdoc git libxml2-dev openssl-dev COPY . /opt/spandx/ RUN apk update && \ apk add $PACKAGES && \ diff --git a/Gemfile.lock b/Gemfile.lock index 139dfba..a9dc845 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -4,13 +4,13 @@ PATH spandx (0.13.4) addressable (~> 2.7) bundler (>= 1.16, < 3.0.0) - nanospinner (~> 1.0.0) net-hippie (~> 0.3) nokogiri (~> 1.10) + oj (~> 3.10) parslet (~> 2.0) terminal-table (~> 1.8) thor - tty-screen (~> 0.7) + tty-spinner (~> 0.9) zeitwerk (~> 2.3) GEM @@ -18,7 +18,7 @@ GEM specs: addressable (2.7.0) public_suffix (>= 2.0.2, < 5.0) - ast (2.4.0) + ast (2.4.1) benchmark-ips (2.8.2) benchmark-malloc (0.2.0) benchmark-perf (0.6.0) @@ -34,7 +34,7 @@ GEM faraday (1.0.1) multipart-post (>= 1.2, < 3) hashdiff (1.0.1) - licensed (2.10.0) + licensed (2.11.1) bundler (>= 1.10) licensee (>= 9.14.0, < 10.0.0) parallel (>= 0.18.0) @@ -51,15 +51,15 @@ GEM thor (>= 0.19, < 2.0) mini_portile2 (2.4.0) multipart-post (2.1.1) - nanospinner (1.0.0) net-hippie (0.3.2) nokogiri (1.10.9) mini_portile2 (~> 2.4.0) octokit (4.18.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) + oj (3.10.6) parallel (1.19.1) - parser (2.7.1.2) + parser (2.7.1.3) ast (~> 2.4.0) parslet (2.0.0) pathname-common_prefix (0.0.1) @@ -68,6 +68,7 @@ GEM rake (13.0.1) rake-compiler (1.1.0) rake + regexp_parser (1.7.1) reverse_markdown (1.4.0) nokogiri rexml (3.2.4) @@ -89,14 +90,18 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-support (3.9.3) - rubocop (0.83.0) + rubocop (0.85.1) parallel (~> 1.10) parser (>= 2.7.0.1) rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.7) rexml + rubocop-ast (>= 0.0.3) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-rspec (1.39.0) + rubocop-ast (0.0.3) + parser (>= 2.7.0.1) + rubocop-rspec (1.40.0) rubocop (>= 0.68.1) ruby-prof (1.4.1) ruby-progressbar (1.10.1) @@ -110,9 +115,11 @@ GEM unicode-display_width (~> 1.1, >= 1.1.1) thor (0.20.3) tomlrb (1.3.0) - tty-screen (0.7.1) + tty-cursor (0.7.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) unicode-display_width (1.7.0) - vcr (5.1.0) + vcr (6.0.0) webmock (3.8.3) addressable (>= 2.3.6) crack (>= 0.3.2) @@ -135,7 +142,7 @@ DEPENDENCIES rubocop-rspec (~> 1.22) ruby-prof (~> 1.3) spandx! - vcr (~> 5.0) + vcr (~> 6.0) webmock (~> 3.7) BUNDLED WITH diff --git a/bin/json-benchmark b/bin/json-benchmark new file mode 100755 index 0000000..c678823 --- /dev/null +++ b/bin/json-benchmark @@ -0,0 +1,29 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'bundler/inline' + +gemfile do + source 'https://rubygems.org' + + gem 'benchmark-ips', '~> 2.8' + gem 'oj' +end + +require 'benchmark/ips' +require 'json' +require 'oj' + +Oj.default_options = { mode: :strict } + +json = JSON.pretty_generate({ + string: 'spandx', + number: 1234, + array: ['MIT'] +}) + +Benchmark.ips do |x| + x.report('JSON.parse') { JSON.parse(json) } + x.report('OJ.load') { Oj.load(json) } + x.compare! +end @@ -4,7 +4,6 @@ require 'spandx' Signal.trap('INT') do - warn("\n#{caller.join("\n")}: interrupted") exit(1) end diff --git a/lib/spandx.rb b/lib/spandx.rb index b7a5bfa..78fbdcb 100644 --- a/lib/spandx.rb +++ b/lib/spandx.rb @@ -8,11 +8,11 @@ require 'json' require 'logger' require 'net/hippie' require 'nokogiri' +require 'oj' require 'parslet' require 'pathname' require 'yaml' require 'zeitwerk' -require 'terminal-table' require 'spandx/spandx' loader = Zeitwerk::Loader.for_gem diff --git a/lib/spandx/cli.rb b/lib/spandx/cli.rb index 817ff89..e5a8d76 100644 --- a/lib/spandx/cli.rb +++ b/lib/spandx/cli.rb @@ -1,8 +1,8 @@ # frozen_string_literal: true -require 'nanospinner' require 'thor' -require 'tty-screen' +require 'tty-spinner' +require 'terminal-table' module Spandx module Cli diff --git a/lib/spandx/cli/commands/scan.rb b/lib/spandx/cli/commands/scan.rb index 9e874f3..22420fc 100644 --- a/lib/spandx/cli/commands/scan.rb +++ b/lib/spandx/cli/commands/scan.rb @@ -4,51 +4,49 @@ module Spandx module Cli module Commands class Scan - attr_reader :scan_path, :spinner + include Spandx::Core + attr_reader :scan_path def initialize(scan_path, options) @scan_path = ::Pathname.new(scan_path) @options = options - @spinner = options[:show_progress] ? ::Spandx::Core::Spinner.new : ::Spandx::Core::Spinner::NULL require(options[:require]) if options[:require] end def execute(output: $stdout) - report = ::Spandx::Core::Report.new - each_file do |file| - spinner.spin(file) - each_dependency_from(file) do |dependency| - spinner.spin(file) - report.add(dependency) + with_printer(output) do |printer| + each_dependency do |dependency| + printer.print_line(Plugin.enhance(dependency), output) end end - spinner.stop - output.puts(format(report.to(@options[:format]))) end private def each_file - Spandx::Core::PathTraversal + PathTraversal .new(scan_path, recursive: @options[:recursive]) .each { |file| yield file } end - def each_dependency_from(file) - ::Spandx::Core::Parser - .parse(file) - .map { |x| enhance(x) } - .each { |dependency| yield dependency } + def each_dependency + each_file do |file| + Parser.parse(file).each do |dependency| + yield dependency + end + end end def format(output) Array(output).map(&:to_s) end - def enhance(dependency) - ::Spandx::Core::Plugin - .all - .inject(dependency) { |memo, plugin| plugin.enhance(memo) } + def with_printer(output) + printer = ::Spandx::Cli::Printer.for(@options[:format]) + printer.print_header(output) + yield printer + ensure + printer.print_footer(output) end end end diff --git a/lib/spandx/cli/main.rb b/lib/spandx/cli/main.rb index f22dd34..bb27f83 100644 --- a/lib/spandx/cli/main.rb +++ b/lib/spandx/cli/main.rb @@ -8,14 +8,14 @@ module Spandx method_option :recursive, aliases: '-R', type: :boolean, desc: 'Perform recursive scan', default: false method_option :airgap, aliases: '-a', type: :boolean, desc: 'Disable network connections', default: false method_option :logfile, aliases: '-l', type: :string, desc: 'Path to a logfile', default: '/dev/null' - method_option :format, aliases: '-f', type: :string, desc: 'Format of report. (table, csv, json, hash)', default: 'table' + method_option :format, aliases: '-f', type: :string, desc: 'Format of report. (table, csv, json)', default: 'table' method_option :pull, aliases: '-p', type: :boolean, desc: 'Pull the latest cache before the scan', default: false method_option :require, aliases: '-r', type: :string, desc: 'Causes spandx to load the library using require.', default: nil - method_option :show_progress, aliases: '-sp', type: :boolean, desc: 'Shows a progress bar', default: true def scan(lockfile = Pathname.pwd) if options[:help] invoke :help, ['scan'] else + Oj.default_options = { mode: :strict } Spandx.airgap = options[:airgap] Spandx.logger = Logger.new(options[:logfile]) pull if options[:pull] diff --git a/lib/spandx/cli/printer.rb b/lib/spandx/cli/printer.rb new file mode 100644 index 0000000..f21be93 --- /dev/null +++ b/lib/spandx/cli/printer.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Spandx + module Cli + class Printer + def match?(_format) + raise ::Spandx::Error, :match? + end + + def print_header(io); end + + def print_line(dependency, io) + io.puts(dependency.to_s) + end + + def print_footer(io); end + + class << self + include Core::Registerable + + def for(format) + find { |x| x.match?(format) } || new + end + end + end + end +end diff --git a/lib/spandx/cli/printers/csv.rb b/lib/spandx/cli/printers/csv.rb new file mode 100644 index 0000000..ab73960 --- /dev/null +++ b/lib/spandx/cli/printers/csv.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Spandx + module Cli + module Printers + class Csv < Printer + def match?(format) + format.to_sym == :csv + end + + def print_line(dependency, io) + io.puts(CSV.generate_line(dependency.to_a)) + end + end + end + end +end diff --git a/lib/spandx/cli/printers/json.rb b/lib/spandx/cli/printers/json.rb new file mode 100644 index 0000000..b796d89 --- /dev/null +++ b/lib/spandx/cli/printers/json.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module Spandx + module Cli + module Printers + class Json < Printer + def match?(format) + format.to_sym == :json + end + + def print_line(dependency, io) + io.puts(Oj.dump(dependency.to_h)) + end + end + end + end +end diff --git a/lib/spandx/cli/printers/table.rb b/lib/spandx/cli/printers/table.rb new file mode 100644 index 0000000..931b739 --- /dev/null +++ b/lib/spandx/cli/printers/table.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Spandx + module Cli + module Printers + class Table < Printer + HEADINGS = ['Name', 'Version', 'Licenses', 'Location'].freeze + + def initialize + @spinner = TTY::Spinner.new(output: $stderr) + end + + def match?(format) + format.to_sym == :table + end + + def print_header(_io) + @dependencies = SortedSet.new + @spinner.auto_spin + end + + def print_line(dependency, _io) + @dependencies << dependency + end + + def print_footer(io) + @spinner.stop + io.puts(to_table(@dependencies.map(&:to_a))) + end + + private + + def to_table(rows) + Terminal::Table.new(headings: HEADINGS) do |table| + rows.each { |row| table.add_row(row) } + end + end + end + end + end +end diff --git a/lib/spandx/core/git.rb b/lib/spandx/core/git.rb index f98734d..25716ab 100644 --- a/lib/spandx/core/git.rb +++ b/lib/spandx/core/git.rb @@ -11,9 +11,8 @@ module Spandx end def read(path) - full_path = File.join(root, path) - - IO.read(full_path) if File.exist?(full_path) + full_path = root.join(path) + full_path.read if full_path.exist? end def update! @@ -25,15 +24,16 @@ module Spandx def path_for(url) uri = URI.parse(url) name = uri.path.gsub(/\.git$/, '') - File.expand_path(File.join(Dir.home, '.local', 'share', name)) + Pathname(File.expand_path(File.join(Dir.home, '.local', 'share', name))) end def dotgit? - File.directory?(File.join(root, '.git')) + root.join('.git').directory? end def clone! - system('git', 'clone', '--quiet', '--depth=1', '--single-branch', '--branch', 'master', url, root) + system('rm', '-rf', root.to_s) if root.exist? + system('git', 'clone', '--quiet', '--depth=1', '--single-branch', '--branch', 'master', url, root.to_s) end def pull! diff --git a/lib/spandx/core/plugin.rb b/lib/spandx/core/plugin.rb index f4841cf..6564c60 100644 --- a/lib/spandx/core/plugin.rb +++ b/lib/spandx/core/plugin.rb @@ -9,6 +9,12 @@ module Spandx class << self include Registerable + + def enhance(dependency) + Plugin.all.inject(dependency) do |memo, plugin| + plugin.enhance(memo) + end + end end end end diff --git a/lib/spandx/core/report.rb b/lib/spandx/core/report.rb deleted file mode 100644 index dc57f6e..0000000 --- a/lib/spandx/core/report.rb +++ /dev/null @@ -1,54 +0,0 @@ -# frozen_string_literal: true - -module Spandx - module Core - class Report - attr_reader :dependencies - - FORMATS = { - csv: :to_csv, - hash: :to_h, - json: :to_json, - table: :to_table, - }.freeze - - def initialize - @dependencies = SortedSet.new - end - - def add(dependency) - @dependencies << dependency - end - - def to(format, formats: FORMATS) - public_send(formats.fetch(format&.to_sym, :to_json)) - end - - def to_table - Terminal::Table.new(headings: ['Name', 'Version', 'Licenses', 'Location']) do |t| - dependencies.each do |d| - t.add_row d.to_a - end - end - end - - def to_h - { version: '1.0', dependencies: [] }.tap do |report| - dependencies.each do |dependency| - report[:dependencies].push(dependency.to_h) - end - end - end - - def to_json(*_args) - JSON.pretty_generate(to_h) - end - - def to_csv - dependencies.map do |dependency| - CSV.generate_line(dependency.to_a) - end - end - end - end -end diff --git a/lib/spandx/core/spinner.rb b/lib/spandx/core/spinner.rb deleted file mode 100644 index af3c7a7..0000000 --- a/lib/spandx/core/spinner.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true - -module Spandx - module Core - class Spinner - NULL = Class.new do - def self.spin(*args); end - - def self.stop(*args); end - end - - attr_reader :columns, :spinner - - def initialize(columns: TTY::Screen.columns, output: $stderr) - @columns = columns - @spinner = Nanospinner.new(output) - @queue = Queue.new - @thread = Thread.new { work } - end - - def spin(message) - @queue.enq(justify(message)) - yield if block_given? - end - - def stop - @queue.clear - @queue.enq(:stop) - @thread.join - end - - private - - def justify(message) - message.to_s.ljust(columns - 3) - end - - def work - last_message = justify('') - loop do - message = @queue.empty? ? last_message : @queue.deq - break if message == :stop - - spinner.spin(message) - last_message = message - sleep 0.1 - end - end - end - end -end diff --git a/lib/spandx/core/thread_pool.rb b/lib/spandx/core/thread_pool.rb new file mode 100644 index 0000000..fdbced5 --- /dev/null +++ b/lib/spandx/core/thread_pool.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Spandx + module Core + class ThreadPool + def initialize(size: 1) + @size = size + @queue = Queue.new + @pool = size.times.map { start_worker_thread(@queue) } + end + + def run(*args, &job) + @queue.enq([job, args]) + end + + def done? + @queue.empty? + end + + def shutdown + @size.times do + run { throw :exit } + end + + @pool.map(&:join) + end + + def self.open(**args) + pool = new(**args) + yield pool + ensure + pool.shutdown + end + + private + + def start_worker_thread(queue) + Thread.new(queue) do |q| + catch(:exit) do + loop do + job, args = q.deq + job.call(args) + end + end + end + end + end + end +end diff --git a/lib/spandx/dotnet/nuget_gateway.rb b/lib/spandx/dotnet/nuget_gateway.rb index 6776553..089d2bb 100644 --- a/lib/spandx/dotnet/nuget_gateway.rb +++ b/lib/spandx/dotnet/nuget_gateway.rb @@ -69,7 +69,7 @@ module Spandx def fetch_json(url) response = http.get(url) - http.ok?(response) ? JSON.parse(response.body) : {} + http.ok?(response) ? Oj.load(response.body) : {} end def fetch_xml(url) diff --git a/lib/spandx/js/parsers/npm.rb b/lib/spandx/js/parsers/npm.rb index b92e1a2..2402454 100644 --- a/lib/spandx/js/parsers/npm.rb +++ b/lib/spandx/js/parsers/npm.rb @@ -18,8 +18,8 @@ module Spandx private - def each_metadata(file_path) - package_lock = JSON.parse(IO.read(file_path)) + def each_metadata(path) + package_lock = Oj.load(path.read) package_lock['dependencies'].each do |name, metadata| yield metadata.merge('name' => name) end diff --git a/lib/spandx/js/yarn_pkg.rb b/lib/spandx/js/yarn_pkg.rb index 19a8dd3..bb479b4 100644 --- a/lib/spandx/js/yarn_pkg.rb +++ b/lib/spandx/js/yarn_pkg.rb @@ -27,7 +27,7 @@ module Spandx response = http.get(uri, escape: false) if http.ok?(response) - json = JSON.parse(response.body) + json = Oj.load(response.body) json['versions'] ? json['versions'][dependency.version] : json else {} diff --git a/lib/spandx/php/packagist_gateway.rb b/lib/spandx/php/packagist_gateway.rb index 88ec6d3..8580072 100644 --- a/lib/spandx/php/packagist_gateway.rb +++ b/lib/spandx/php/packagist_gateway.rb @@ -17,7 +17,7 @@ module Spandx response = http.get("https://repo.packagist.org/p/#{dependency.name}.json") return [] unless http.ok?(response) - json = JSON.parse(response.body) + json = Oj.load(response.body) json['packages'][dependency.name][dependency.version]['license'] end end diff --git a/lib/spandx/php/parsers/composer.rb b/lib/spandx/php/parsers/composer.rb index 61c29a8..e1bb240 100644 --- a/lib/spandx/php/parsers/composer.rb +++ b/lib/spandx/php/parsers/composer.rb @@ -10,7 +10,7 @@ module Spandx def parse(path) items = Set.new - composer_lock = JSON.parse(path.read) + composer_lock = Oj.load(path.read) composer_lock['packages'].concat(composer_lock['packages-dev']).each do |dependency| items.add(map_from(path, dependency)) end diff --git a/lib/spandx/python/parsers/pipfile_lock.rb b/lib/spandx/python/parsers/pipfile_lock.rb index 08b8644..e3ea58d 100644 --- a/lib/spandx/python/parsers/pipfile_lock.rb +++ b/lib/spandx/python/parsers/pipfile_lock.rb @@ -19,7 +19,7 @@ module Spandx private def dependencies_from(lockfile) - json = JSON.parse(lockfile.read) + json = Oj.load(lockfile.read) each_dependency(json) do |name, version| yield ::Spandx::Core::Dependency.new( path: lockfile, diff --git a/lib/spandx/python/pypi.rb b/lib/spandx/python/pypi.rb index 7849f29..ef3080a 100644 --- a/lib/spandx/python/pypi.rb +++ b/lib/spandx/python/pypi.rb @@ -49,19 +49,26 @@ module Spandx end def version_from(url) - path = SUBSTITUTIONS.inject(URI.parse(url).path.split('/')[-1]) do |memo, item| - memo.gsub(item, '') - end - + path = cleanup(url) return if path.rindex('-').nil? - path.scan(/-\d+\..*/)[-1][1..-1] + section = path.scan(/-\d+\..*/) + section = path.scan(/-\d+\.?.*/) if section.empty? + section[-1][1..-1] + rescue StandardError => error + warn([url, error].inspect) end private attr_reader :http + def cleanup(url) + SUBSTITUTIONS.inject(URI.parse(url).path.split('/')[-1]) do |memo, item| + memo.gsub(item, '') + end + end + def sources_for(dependency) return default_sources if dependency.meta.empty? @@ -76,7 +83,7 @@ module Spandx sources.each do |source| html_from(source, '/simple/').css('a[href*="/simple"]').each do |node| each_version(source, node[:href]) do |dependency| - definition = source.lookup(dependency[:name], dependency[:version]) + definition = source.lookup(dependency[:name], dependency[:version], http: http) yield dependency.merge(license: definition['license']) end end @@ -93,7 +100,12 @@ module Spandx def html_from(source, path) url = URI.join(source.uri.to_s, path).to_s - Nokogiri::HTML(http.get(url).body) + response = http.get(url) + if http.ok?(response) + Nokogiri::HTML(response.body) + else + Nokogiri::HTML('<html><head></head><body></body></html>') + end end end end diff --git a/lib/spandx/python/source.rb b/lib/spandx/python/source.rb index af0cbbb..2379c16 100644 --- a/lib/spandx/python/source.rb +++ b/lib/spandx/python/source.rb @@ -22,7 +22,7 @@ module Spandx def lookup(name, version, http: Spandx.http) response = http.get(uri_for(name, version)) if http.ok?(response) - JSON.parse(response.body) + Oj.load(response.body) else {} end diff --git a/lib/spandx/ruby/gateway.rb b/lib/spandx/ruby/gateway.rb index 54e8107..208eb9e 100644 --- a/lib/spandx/ruby/gateway.rb +++ b/lib/spandx/ruby/gateway.rb @@ -27,7 +27,7 @@ module Spandx end def parse(json) - JSON.parse(json) + Oj.load(json) end end end diff --git a/spandx.gemspec b/spandx.gemspec index 3f36023..100db55 100644 --- a/spandx.gemspec +++ b/spandx.gemspec @@ -34,13 +34,13 @@ Gem::Specification.new do |spec| spec.add_dependency 'addressable', '~> 2.7' spec.add_dependency 'bundler', '>= 1.16', '< 3.0.0' - spec.add_dependency 'nanospinner', '~> 1.0.0' spec.add_dependency 'net-hippie', '~> 0.3' spec.add_dependency 'nokogiri', '~> 1.10' + spec.add_dependency 'oj', '~> 3.10' spec.add_dependency 'parslet', '~> 2.0' spec.add_dependency 'terminal-table', '~> 1.8' spec.add_dependency 'thor' - spec.add_dependency 'tty-screen', '~> 0.7' + spec.add_dependency 'tty-spinner', '~> 0.9' spec.add_dependency 'zeitwerk', '~> 2.3' spec.add_development_dependency 'benchmark-ips', '~> 2.8' @@ -54,6 +54,6 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'rubocop', '~> 0.52' spec.add_development_dependency 'rubocop-rspec', '~> 1.22' spec.add_development_dependency 'ruby-prof', '~> 1.3' - spec.add_development_dependency 'vcr', '~> 5.0' + spec.add_development_dependency 'vcr', '~> 6.0' spec.add_development_dependency 'webmock', '~> 3.7' end diff --git a/spec/fixtures/help-scan.expected b/spec/fixtures/help-scan.expected index e9b1c5a..d1c7f56 100644 --- a/spec/fixtures/help-scan.expected +++ b/spec/fixtures/help-scan.expected @@ -2,16 +2,14 @@ Usage: spandx scan LOCKFILE Options: - -h, [--help], [--no-help] # Display usage information - -R, [--recursive], [--no-recursive] # Perform recursive scan - -a, [--airgap], [--no-airgap] # Disable network connections - -l, [--logfile=LOGFILE] # Path to a logfile - # Default: /dev/null - -f, [--format=FORMAT] # Format of report. (table, csv, json, hash) - # Default: table - -p, [--pull], [--no-pull] # Pull the latest cache before the scan - -r, [--require=REQUIRE] # Causes spandx to load the library using require. - -sp, [--show-progress], [--no-show-progress] # Shows a progress bar - # Default: true + -h, [--help], [--no-help] # Display usage information + -R, [--recursive], [--no-recursive] # Perform recursive scan + -a, [--airgap], [--no-airgap] # Disable network connections + -l, [--logfile=LOGFILE] # Path to a logfile + # Default: /dev/null + -f, [--format=FORMAT] # Format of report. (table, csv, json) + # Default: table + -p, [--pull], [--no-pull] # Pull the latest cache before the scan + -r, [--require=REQUIRE] # Causes spandx to load the library using require. Scan a lockfile and list dependencies/licenses diff --git a/spec/integration/cli/scan_spec.rb b/spec/integration/cli/scan_spec.rb index c92ea29..1a6b3f2 100644 --- a/spec/integration/cli/scan_spec.rb +++ b/spec/integration/cli/scan_spec.rb @@ -7,27 +7,27 @@ RSpec.describe '`spandx scan` command', type: :cli do end it 'executes `spandx scan Gemfile.lock`' do - output = `spandx scan #{fixture_file('bundler/Gemfile.lock')} --no-show-progress` + output = `spandx scan #{fixture_file('bundler/Gemfile.lock')} 2> /dev/null` expect(output).to eq(fixture_file_content('bundler/Gemfile.lock.expected')) end it 'executes `spandx scan gems.lock' do - output = `spandx scan #{fixture_file('bundler/gems.lock')} --no-show-progress` + output = `spandx scan #{fixture_file('bundler/gems.lock')} 2> /dev/null` expect(output).to eq(fixture_file_content('bundler/gems.lock.expected')) end it 'executes `spandx scan Pipfile.lock`' do - output = `spandx scan #{fixture_file('pip/Pipfile.lock')} --no-show-progress` + output = `spandx scan #{fixture_file('pip/Pipfile.lock')} 2> /dev/null` expect(output).to eq(fixture_file_content('pip/Pipfile.lock.expected')) end it 'executes `spandx scan yarnfile.lock`' do - output = `spandx scan #{fixture_file('js/yarn.lock')} --no-show-progress` + output = `spandx scan #{fixture_file('js/yarn.lock')} 2> /dev/null` expect(output).to eq(fixture_file_content('js/yarn.lock.expected')) end it 'executes `spandx scan composer.lock`' do - output = `spandx scan #{fixture_file('composer/composer.lock')} --no-show-progress` + output = `spandx scan #{fixture_file('composer/composer.lock')} 2> /dev/null` expect(output).to eq(fixture_file_content('composer/composer.lock.expected')) end end diff --git a/spec/integration/core/git_spec.rb b/spec/integration/core/git_spec.rb index 186c5b7..63bb4d8 100644 --- a/spec/integration/core/git_spec.rb +++ b/spec/integration/core/git_spec.rb @@ -17,15 +17,17 @@ RSpec.describe Spandx::Core::Git do describe '#root' do let(:expected_path) { File.expand_path(File.join(ENV['HOME'], '.local', 'share', 'spdx', 'license-list-data')) } - it { expect(subject.root).to eql(expected_path) } + it { expect(subject.root.to_s).to eql(expected_path) } end describe 'update!' do let(:expected_path) { File.expand_path(File.join(ENV['HOME'], '.local', 'share', 'spdx', 'license-list-data')) } context 'when the repository has not been cloned' do + let(:git_path) { instance_double(Pathname, directory?: false) } + before do - allow(File).to receive(:directory?).with(File.join(expected_path, '.git')).and_return(false) + allow(subject.root).to receive(:join).with('.git').and_return(git_path) subject.update! end @@ -34,9 +36,11 @@ RSpec.describe Spandx::Core::Git do end context 'when the repository has already been cloned' do + let(:git_path) { instance_double(Pathname, directory?: true) } + before do - allow(File).to receive(:directory?).with(File.join(expected_path, '.git')).and_return(true) - allow(Dir).to receive(:chdir).with(expected_path).and_yield + allow(subject.root).to receive(:join).with('.git').and_return(git_path) + allow(Dir).to receive(:chdir).with(Pathname(expected_path)).and_yield subject.update! end diff --git a/spec/unit/cli/scan_spec.rb b/spec/unit/cli/scan_spec.rb index 7e33e7f..a11842d 100644 --- a/spec/unit/cli/scan_spec.rb +++ b/spec/unit/cli/scan_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Spandx::Cli::Commands::Scan do let(:lockfile) { fixture_file(path) } let(:output) { StringIO.new } - let(:options) { { format: 'table', show_progress: false, recursive: true } } + let(:options) { { format: 'table', recursive: true } } before do stub_request(:get, Spandx::Spdx::Gateway::URL) diff --git a/spec/unit/core/report_spec.rb b/spec/unit/core/report_spec.rb deleted file mode 100644 index d543087..0000000 --- a/spec/unit/core/report_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe Spandx::Core::Report do - def build(name, version, path) - Spandx::Core::Dependency.new(name: name, version: version, path: path) - end - - describe '#dependencies' do - before do - subject.add(build('spandx', '0.1.0', Pathname('./Gemfile.lock'))) - subject.add(build('spandx', '0.1.0', Pathname('./Gemfile.lock'))) - end - - specify { expect(subject.dependencies.count).to be(1) } - specify { expect(subject.dependencies.to_a).to eql([build('spandx', '0.1.0', Pathname('./Gemfile.lock'))]) } - end -end diff --git a/spec/unit/python/pypi_spec.rb b/spec/unit/python/pypi_spec.rb index cb09c4a..a0617bd 100644 --- a/spec/unit/python/pypi_spec.rb +++ b/spec/unit/python/pypi_spec.rb @@ -28,107 +28,108 @@ RSpec.describe Spandx::Python::Pypi do describe '#version_from' do [ - { url: 'https://files.pythonhosted.org/packages/8c/e6/83748ba1e232167de61f2bf31ec53f4b7acdd1ced52bdf3ea3366ea48132/0-0.0.0-py2.py3-none-any.whl#sha256=d8c8aeb13d410f713ea132d4268ef3dc1e113be6ec3ef2c31420df5c44e8e634', version: '0.0.0' }, - { url: 'https://files.pythonhosted.org/packages/ff/b9/6246538b88db7272f62d4eb0bd1afbb5ec402b24866be95059cc037d6970/00000a-0.0.2.tar.gz#sha256=3c1a3cdcc6cd2ca9a8dd44009509039dfa84928a4293069a74d5fc5c39e4b7a1', version: '0.0.2' }, - { url: 'https://files.pythonhosted.org/packages/a3/b4/61ad204de90c962698982b0e4aac34d4db9737041396b2c6c6860276cdf0/0.0.1-0.0.1.tar.gz#sha256=b5ebdc3ae6be725b4e8c4959790022b431e183b275dfa673a7521c2acf851d40', version: '0.0.1' }, - { url: 'https://files.pythonhosted.org/packages/79/29/f31b78d51b59eafae5b7a876e5d18870c597ca8913436f0ab4b16bc3b9fa/007-0.0.1.tar.gz#sha256=570f9b3c06b04d1e53cc9304e2a3b127731e31e7c8636df5a02aba664e618a88', version: '0.0.1' }, - { url: 'https://files.pythonhosted.org/packages/fd/49/c01735a9c8d028f22356f8e3086b412530a2f288b072945e0c079ef29bd6/007-0.0.2.tar.gz#sha256=a5f7fe73035bcd3944ac30843a595dc47a0e5d20110d70c9998f0396d104ee6c', version: '0.0.2' }, - { url: 'https://files.pythonhosted.org/packages/28/77/b367493f392d23b5e91220a92ec87aa94ca0ef4ee82b7baacc13ca48c585/00print_lol-1.0.0.tar.gz#sha256=03a146dc09b0076f2e82d39563a5b8ba93c64536609d9806be7b5b3ea87a4162', version: '1.0.0' }, - { url: 'https://files.pythonhosted.org/packages/c6/ab/4a317ae0d0c7c911f1c77719c553fc46a12d981899ceb5d47220fc3d535c/00print_lol-1.1.0.tar.gz#sha256=c452b0cc78f3a5edecbc6d160d2fa14c012d78403b0206558bcf1444eb5d1e2e', version: '1.1.0' }, - { url: 'https://files.pythonhosted.org/packages/99/b1/8329b44e81c794ebe8772531fbb94df3afb107102d183c1b0a17abb49471/0121-0.0.1.tar.gz#sha256=c340f511c652c50e67fac4e85528064f4253f5850446c9258949574a5d541f92', version: '0.0.1' }, - { url: 'https://files.pythonhosted.org/packages/95/47/2444989f005f7f3f892fc2bd375946072c23325becde4a5e2bae729579f3/01d61084-d29e-11e9-96d1-7c5cf84ffe8e-0.1.0.tar.gz#sha256=8b97d404c652de7ebc481b4ccc22c5d837d2e1d0938efcb2ce47a4220784247a', version: '0.1.0' }, - { url: 'https://files.pythonhosted.org/packages/ac/78/83c3d46cdcf616bf64b60cc35bbcc2dc9504811516e07527a4ab3af6e0c7/01d61084_d29e_11e9_96d1_7c5cf84ffe8e-0.1.0-py3-none-any.whl#sha256=258f18753542f8bb6715fdfe5691313443c92fc80b2050e36eebac81a42ec3b4', version: '0.1.0' }, - { url: 'https://files.pythonhosted.org/packages/b0/e9/0bf97f93c7fe78b0983c5d375d670bebcdb3526e6f2e60c4c7e733021c27/021-1.0.tar.gz#sha256=6ff3159b4fe981c0702437a0c3004940c623ea6cdf4efd9ac74dac094e622160', version: '1.0' }, - { url: 'https://files.pythonhosted.org/packages/b0/81/b2cb9d8fdcffdbe1988009b7fef8ec0a29cf07c8016e66a02dd9941cfe62/02exercicio-1.0.0.tar.gz#sha256=71a5ffda2437ca70bb90069155fba43bfd8694eab65d9a7875286fd955cbe02d', version: '1.0.0' }, - { url: 'https://files.pythonhosted.org/packages/ec/65/c0116953c9a3f47de89e71964d6c7b0c783b01f29fa3390584dbf3046b4d/0805nexter-1.1.0.zip#sha256=52cd128ad3afe539478abc7440d4b043384295fbe6b0958a237cb6d926465035', version: '1.1.0' }, - { url: 'https://files.pythonhosted.org/packages/c4/a0/4562cda161dc4ecbbe9e2a11eb365400c0461845c5be70d73869786809c4/0805nexter-1.2.0.zip#sha256=49785c6ae39ea511b3c253d7621c0b1b6228be2f965aca8a491e6b84126d0709', version: '1.2.0' }, - { url: 'https://files.pythonhosted.org/packages/65/3a/33138bb0c82a08a50a427a067a26310b7d6c17b0fec5e286c5d72a4f7f98/090807040506030201testpip-0.1dev.tar.gz#sha256=e32ccda7c353012cfdbf038a2e38014813442c9fbff4fade4df1901ecd2fbe17', version: '0.1dev' }, - { url: 'https://files.pythonhosted.org/packages/d3/cb/91061d33b8991125641585251a5251ac054d3bc7606cd80a0968995430c7/0-core-client-1.1.0a3.tar.gz#sha256=d47d162505074abfaed298d5463ab40e804438c59bc1d5f165b03d257c1de0ff', version: '1.1.0a3' }, - { url: 'https://files.pythonhosted.org/packages/c3/82/c0ef77f86571d9d6bdc697424cfdc3b04f6a8db6a1497b851a0f4a862401/0_core_client-1.1.0a3-py3-none-any.whl#sha256=092c89c05104a59d11ac2604c5af10cb0106bbbb521b42844dee13dd2c80606b', version: '1.1.0a3' }, - { url: 'https://files.pythonhosted.org/packages/9b/16/0160f8c9dfafb8d59e0b2eac3b0264660e8cef16e4f7dcd2da34f4073f2d/0-core-client-1.1.0a4.tar.gz#sha256=601b69c5c93d4990399ddacd79d1a81e9af3570a44a3a55bb7edff315b7c084d', version: '1.1.0a4' }, + { url: 'https://files.pythonhosted.org/packages/01/d4/b73510e90eaace314156d4ffeddcdc32925e0ea93924c2f29266d55df475/0lever_utils-0.1.5-py3-none-any.whl#sha256=930cf8cf0edd37eb60fb0ca3760a23e5ad3c52a1295d01b73e489f2d3d0df511', version: '0.1.5' }, + { url: 'https://files.pythonhosted.org/packages/06/83/ed65c68212f5f145063ba6e3df8e8a58f724564db0f33224f3e4b567f78f/0-orchestrator-1.1.0a8.tar.gz#sha256=bf89940a3d3f3d1b8fac912cbc9b173f7ca0aa2aee623fa206771f230d0467dd', version: '1.1.0a8' }, + { url: 'https://files.pythonhosted.org/packages/08/13/1bce760f7456e598f7156d4488a29a65419b8cf72b1004de3db459c25ba8/0lever_utils-0.1.6-py2-none-any.whl#sha256=bcdd895c07615e93dd261db391807871e3ff9898ee6ada10c5ea88a55bf04264', version: '0.1.6' }, + { url: 'https://files.pythonhosted.org/packages/0c/a7/0bb4c480f4111c80400139261abef84fa8e178b03baf0e2ae21410b4ddac/0lever_so-1.0.8-py3-none-any.whl#sha256=4b36e040be49fe7ddc7ed9a5620d35525f4eebaef9113b787d8ac77c8b2a6b27', version: '1.0.8' }, + { url: 'https://files.pythonhosted.org/packages/0c/b5/20dbb950ab388c9d7b3e5099d8956d5098a8acb02497a010b5cc21d34c0a/0lever_utils-0.1.5-py2-none-any.whl#sha256=6d12dae3ee2608fa071ca5caf76f1c2bf18519e49c4afbffdef611847b8b6aba', version: '0.1.5' }, + { url: 'https://files.pythonhosted.org/packages/0d/9f/a24c516016770a80bb33dffd852762fe8e61a5127d94b4bdb290003a6b6a/0x01-letsencrypt-0.1.tar.gz#sha256=3b6786a2f24382ea7b42bbc543c2fce70c4fe4c0de49a24c1098cb41e271526e', version: '0.1' }, + { url: 'https://files.pythonhosted.org/packages/0d/ce/6e7c14ebc167f31a8bb9d0b48116359794c902a60c29e0c8d197b13e8bdd/0_orchestrator-1.1.0a7.post1-py3-none-any.whl#sha256=72f076dec0cbe098ebc085fa083b30e2671a310d8186620f1c52e73c220ab81f', version: '1.1.0a7.post1' }, + { url: 'https://files.pythonhosted.org/packages/0e/e7/2bc27a48170fc7d4f458fda9d9ff973f1780bf1b0fa2fd71de89124d7014/0x_contract_addresses-2.1.0-py3-none-any.whl#sha256=dd78dd0429bac1ff88e1d1bf5422f9f17d7738e1fa49da97755056792d9f5945', version: '2.1.0' }, + { url: 'https://files.pythonhosted.org/packages/14/19/93882065e97fe8d30b246ad47365b4a18c63846b1c8b5f294c4abcedba49/0-orchestrator-1.1.0a3.tar.gz#sha256=d9248bc9b55f645b6045f6bb4846ae0df0f7193e39633295d9967ba68665d177', version: '1.1.0a3' }, { url: 'https://files.pythonhosted.org/packages/15/cf/129954b87fcb2a093a16c2f926bbd7600d97676df577c56fc88c955322b6/0-core-client-1.1.0a5.tar.gz#sha256=4f7c6ea029298a0343d05c1a7a136930ea78f15ecfdb9004265b758486c3a0ca', version: '1.1.0a5' }, - { url: 'https://files.pythonhosted.org/packages/28/af/8f35eed98331dd634761917747b278b5705bea44d394784bd83c6074f869/0_core_client-1.1.0a5-py3-none-any.whl#sha256=1f58f5251752a21f9e2d52239ba61b160f7c38dfac45d5206fc41b877a6e3194', version: '1.1.0a5' }, - { url: 'https://files.pythonhosted.org/packages/f5/90/897a16f3cd9044fe18a238ecaa9c421f8b54531bd7ef34e7ec405c5a319a/0-core-client-1.1.0a7.tar.gz#sha256=2f45465e53f57b6f7570aa959d27f6ab5ea32ee395e210df8de23f1335b3bcc8', version: '1.1.0a7' }, + { url: 'https://files.pythonhosted.org/packages/19/91/69bcda2d03734913a26469f21868d32621c624aaa82762908e2febe98ca8/0lever_utils-0.0.3-py3-none-any.whl#sha256=db0849f8f05c04ae3f4745d00355c61280b627ffc520b7cc8aa904e4fd17e097', version: '0.0.3' }, + { url: 'https://files.pythonhosted.org/packages/1d/34/ba1fa03f9db5cd5267167fd6093bc478e92a3699ca1d2fc16f6950af89c5/0lever_utils-0.0.3-py2-none-any.whl#sha256=fb4684d2026ff6bc26df92c8cf6332fe9593e55b27a6c306a3aeda5fe07179d5', version: '0.0.3' }, + { url: 'https://files.pythonhosted.org/packages/1f/c8/32dd25d1e72229a37548eba24a873c63a368714382fc6bf18a041dd212b1/0lever_utils-0.1.0-py3-none-any.whl#sha256=3a4f2eadad572878b04b2f8fc9d6bcb31550bb742b95bed0d9c568d9cc7ae5f1', version: '0.1.0' }, + { url: 'https://files.pythonhosted.org/packages/21/53/f43b2f754284fe76436e06aac50c42ad984587dcfcb3e35c0999158223d5/0_orchestrator-1.1.0a8-py3-none-any.whl#sha256=5460255971955f78265894404032a33a14d3a6c93c1099d5c130b520e96d2cd9', version: '1.1.0a8' }, + { url: 'https://files.pythonhosted.org/packages/23/b0/55c18ecf8e093fb0c08024ad7d2559d4023639259692d9dd01e5ffcd30e3/0x_contract_addresses-2.0.0-py3-none-any.whl#sha256=f285f96d401eb13f572343dc4f658689b745642a66e0767ecea94e0d3be629ac', version: '2.0.0' }, { url: 'https://files.pythonhosted.org/packages/25/3e/d455e956af418f0632326604d19253b6d0558809ed582afffaed72200b0a/0_core_client-1.1.0a7-py3-none-any.whl#sha256=c81dfe9de503d0dc9770bf27f6177d8bf31626830b290ed5afbc0b3579f8fd2e', version: '1.1.0a7' }, - { url: 'https://files.pythonhosted.org/packages/cd/1c/52c3a1c88b2a2821ea7d2afc3c7883a8d73880dd4de4199b8d5e7d9773bd/0-core-client-1.1.0a8.tar.gz#sha256=663508e24643ad3a261b8b317e34ad6f096d2bae8997fb9155629e941b78986b', version: '1.1.0a8' }, - { url: 'https://files.pythonhosted.org/packages/66/fa/acc0e598ef7bc9af8dc67b76776fff86e163b702742c3a842d1ae7956203/0_core_client-1.1.0a8-py3-none-any.whl#sha256=3a5566dcb6d8c971c4ec74b3910b1d5b25b5e18ce6263161a1b7f9d41f3188e4', version: '1.1.0a8' }, - { url: 'https://files.pythonhosted.org/packages/78/62/2d4e6938f108aad2cf13a5b4900e371a041446402cbe8167e1900f6d1716/0lever_so-1.0.8-py2-none-any.whl#sha256=9151d51d191a66d5808269245afb8fa0c09313996d382eb320d64c53f079acb8', version: '1.0.8' }, - { url: 'https://files.pythonhosted.org/packages/0c/a7/0bb4c480f4111c80400139261abef84fa8e178b03baf0e2ae21410b4ddac/0lever_so-1.0.8-py3-none-any.whl#sha256=4b36e040be49fe7ddc7ed9a5620d35525f4eebaef9113b787d8ac77c8b2a6b27', version: '1.0.8' }, - { url: 'https://files.pythonhosted.org/packages/fd/ee/207c1511984df8cb7bb44b2de96c72b954618fe697c187eb4ef6fae1c7ad/0lever_so-1.0.9-py2-none-any.whl#sha256=abd147124d326cceb24b42eb88586ddbfbff7ff69a82380282a855a1ac30eca4', version: '1.0.9' }, - { url: 'https://files.pythonhosted.org/packages/70/ec/625463a29987be8d2c8d8d00951e66d975afb9b673b4da023f5362964096/0lever_so-1.0.9-py3-none-any.whl#sha256=f56846a01fb8e826e82a0a8e0d0ae5feec8da3f56f2f5e2069e340b25d49945a', version: '1.0.9' }, + { url: 'https://files.pythonhosted.org/packages/27/ee/23aee13ec331d77b4f7e4a14546ff0030a88c5f90c1ec5b1e4ed5545d426/0lever_so-1.1.2-py3-none-any.whl#sha256=43c51847b0a8b690203bf8658616e5b10cbf127865199f5def73f967708ef2cf', version: '1.1.2' }, + { url: 'https://files.pythonhosted.org/packages/28/77/b367493f392d23b5e91220a92ec87aa94ca0ef4ee82b7baacc13ca48c585/00print_lol-1.0.0.tar.gz#sha256=03a146dc09b0076f2e82d39563a5b8ba93c64536609d9806be7b5b3ea87a4162', version: '1.0.0' }, + { url: 'https://files.pythonhosted.org/packages/28/af/8f35eed98331dd634761917747b278b5705bea44d394784bd83c6074f869/0_core_client-1.1.0a5-py3-none-any.whl#sha256=1f58f5251752a21f9e2d52239ba61b160f7c38dfac45d5206fc41b877a6e3194', version: '1.1.0a5' }, + { url: 'https://files.pythonhosted.org/packages/2e/f3/e9e87d7d80bda76d4dacfcea880274c3bbd8f8c195b02348ecf07ee0179c/0lever_utils-0.0.2-py2-none-any.whl#sha256=1e91f3df348f5d1775d2f258503daf62d92fdfdf7f2678a50c775b64350eab4d', version: '0.0.2' }, + { url: 'https://files.pythonhosted.org/packages/31/94/3f5aead5e720ab41e7a6d6ecd247bb5f72f4ad0706d3b622c967474ddc64/0x-contract-addresses-2.0.0.tar.gz#sha256=5df5c618005262df882094d72af31c7a390ce21e8f9d235d008ccf2a311a8125', version: '2.0.0' }, + { url: 'https://files.pythonhosted.org/packages/33/c0/d82e190c0b6284b1d0bdd8493f11edf3a80ed601b92c44dacc0dd4b43648/0wdg9nbmpm-0.1.tar.gz#sha256=7130b1f19df69c3dc91b99fa3b31ebae873ef93b3d601285dbd3b3f97271d625', version: '0.1' }, + { url: 'https://files.pythonhosted.org/packages/34/fc/f4a8a1569c906c325d0b41d5b3ac6d115bb1fa860ec46362cf61cf649495/0x-0.1.tar.gz#sha256=4d3f4ad49c37166c79d33f8c58c92558d0f044336248f70296661a046a9b5f1b', version: '0.1' }, { url: 'https://files.pythonhosted.org/packages/39/04/27b147c0d0ce31e0163d6adc6e52f64733a393ec35407d502a8e84e377fe/0lever_so-1.1.0-py2-none-any.whl#sha256=202c1db424ac7ef180a442f37c7336d99678f1481de2f443614c558b03b5ed18', version: '1.1.0' }, - { url: 'https://files.pythonhosted.org/packages/eb/fe/3832155e33dc6ff60586a6552f21eaf3214fff816ac2cae5deffae730ef2/0lever_so-1.1.0-py3-none-any.whl#sha256=06851a36f3853530971b6c21b3db38360d72f6493738ad74351ce9fbaa97e8d6', version: '1.1.0' }, - { url: 'https://files.pythonhosted.org/packages/d1/bb/1f526e72697d8ccd77c7f513ba7d1b23e45642a0ed2bb2dd49f875310c13/0lever_so-1.1.1-py2-none-any.whl#sha256=ca2347e28940daf1cd780f767a4b4bc86ba2f1ac79194552221b98cc8425d25a', version: '1.1.1' }, - { url: 'https://files.pythonhosted.org/packages/c9/3d/947b2c7b6b18b94c524384463ba255db77e36756c800406f453eac69e5f4/0lever_so-1.1.1-py3-none-any.whl#sha256=2386ed3c8da48edf47bb884bc15d6b72666e2e9232d1b3b003852371aa4fe622', version: '1.1.1' }, + { url: 'https://files.pythonhosted.org/packages/39/8f/a57ca099de0406ea8567adb18ba8545bb2bdeda2073028ee74b658f841be/0lever_utils-0.0.1-py2-none-any.whl#sha256=377b2adb6e59373dfbfabdfbb90babf35d2cf761ec02e122994c20291f879691', version: '0.0.1' }, + { url: 'https://files.pythonhosted.org/packages/47/52/d189b2c6d2954effaf12960b8916b9d62fb8150083a42ef9b5e62462ac32/0x-contract-addresses-2.1.0.tar.gz#sha256=d1df84b35d9a35b73c1054c090942e31ff152526249d8d251c7b2fc684e045ab', version: '2.1.0' }, + { url: 'https://files.pythonhosted.org/packages/48/fa/2bfa40b043c9539b12aed4ff6fee834c8bbdeacf3e8388842d2fef0d1b84/0x-contract-addresses-3.0.0.tar.gz#sha256=677f7390d6505b85647af3dfa4765c307a26344d94716d263993c1f7efbf88d8', version: '3.0.0' }, + { url: 'https://files.pythonhosted.org/packages/4b/ab/1df6cee9478914fc9119e9f7fe0463d4a57e63149aa70c496cce48457c07/0x_contract_artifacts-2.0.0-py3-none-any.whl#sha256=44146561e762958fcae64b0202da3416b78a3780f0265a4b57f7e3b6af26b120', version: '2.0.0' }, + { url: 'https://files.pythonhosted.org/packages/4b/f7/90b5cf54de20704b5e09247594ed656e7511b8dea12ae6fea177ede9c700/0x_contract_addresses-3.0.0.dev1-py3-none-any.whl#sha256=1d045c6733b727a965470933e4184494636d3ab07675681c3e65ccef80eb721d', version: '3.0.0.dev1' }, { url: 'https://files.pythonhosted.org/packages/50/71/49ed67c436959dbf2d9acd36369932d8e5383a407cd1cb40b333707744b7/0lever_so-1.1.2-py2-none-any.whl#sha256=a5a0afbb41a24674259390bcdbf92a6bcd69314aa299de693fa97aa3f62b4fab', version: '1.1.2' }, - { url: 'https://files.pythonhosted.org/packages/27/ee/23aee13ec331d77b4f7e4a14546ff0030a88c5f90c1ec5b1e4ed5545d426/0lever_so-1.1.2-py3-none-any.whl#sha256=43c51847b0a8b690203bf8658616e5b10cbf127865199f5def73f967708ef2cf', version: '1.1.2' }, + { url: 'https://files.pythonhosted.org/packages/56/79/2f81c26461433b3036cd34d396325c38ade3a9aa64e6636540b67bc084d4/0x-contract-artifacts-2.0.0.tar.gz#sha256=7c1a0b4204cf08f46efad2b1a19d19e2d6189e1bea9e220e41caa0f145159316', version: '2.0.0' }, + { url: 'https://files.pythonhosted.org/packages/5c/c8/9d580a308885959eb79107c7286995fe30c2b1065a04a28b9e7746788718/0lever_utils-0.0.7-py2-none-any.whl#sha256=91a8683614eedb2b3e8877fb6690965f39ed6feb3aa27e5ea9bed949b36503be', version: '0.0.7' }, + { url: 'https://files.pythonhosted.org/packages/5d/be/460cab4688fa1025c65ecba1f3d56264faa0319ee3ad6e38475f8125aca1/0x_contract_addresses-3.0.0.dev3-py3-none-any.whl#sha256=63f47a7735e5bdf089a2d87c469540b58ce82f10bae4ae076fac25a5f5e9f02c', version: '3.0.0.dev3' }, + { url: 'https://files.pythonhosted.org/packages/5f/6e/0954156529b22e5b1193d7413a8cdc6ad88ec1a552238956dc2e93c043a8/0lever_utils-0.1.2-py2-none-any.whl#sha256=ae47664c69e2379882a8ef7058267aace7970bd1f9c45c24bc7500aaaaa25fa3', version: '0.1.2' }, + { url: 'https://files.pythonhosted.org/packages/61/cf/40bdc4ca91d23e7cc77e01e9084fdd62f38832e908175e04453863b60c8c/aangifte-3.tar.gz#sha256=009c5da775e74f0c8f22a5f15b031de7f7fc6f86c197c4844a1776e1d680c3e7', version: '3' }, + { url: 'https://files.pythonhosted.org/packages/65/3a/33138bb0c82a08a50a427a067a26310b7d6c17b0fec5e286c5d72a4f7f98/090807040506030201testpip-0.1dev.tar.gz#sha256=e32ccda7c353012cfdbf038a2e38014813442c9fbff4fade4df1901ecd2fbe17', version: '0.1dev' }, + { url: 'https://files.pythonhosted.org/packages/66/fa/acc0e598ef7bc9af8dc67b76776fff86e163b702742c3a842d1ae7956203/0_core_client-1.1.0a8-py3-none-any.whl#sha256=3a5566dcb6d8c971c4ec74b3910b1d5b25b5e18ce6263161a1b7f9d41f3188e4', version: '1.1.0a8' }, + { url: 'https://files.pythonhosted.org/packages/68/8b/bbed7b15b68637bb66fa28047b082fb5383f6ddb61ef8a723b3e46e5c4dd/0_orchestrator-1.1.0a3-py3-none-any.whl#sha256=237e32c255663a74cfc9b4f20cf69949ba10cfa52e5d3099194ad2ad35201b4c', version: '1.1.0a3' }, + { url: 'https://files.pythonhosted.org/packages/6a/c6/cedc13f810e7561247df40ba8ead02831ebf7eee2a12537c4f507e33ace1/0lever_utils-0.1.1-py2-none-any.whl#sha256=47dda1e5c1dee794bcc1ba4d5fefd6bca99cf26c11613243af77a19e40443341', version: '0.1.1' }, + { url: 'https://files.pythonhosted.org/packages/70/0f/f8459388d19c9cca20d86e6453afca76567fff7405feea80de0f8e003efc/0lever_utils-0.0.6-py3-none-any.whl#sha256=29206dab46a7405ac455b6b39b7501b37c3be6728051bf35b1487c27c943fb3b', version: '0.0.6' }, + { url: 'https://files.pythonhosted.org/packages/70/ec/625463a29987be8d2c8d8d00951e66d975afb9b673b4da023f5362964096/0lever_so-1.0.9-py3-none-any.whl#sha256=f56846a01fb8e826e82a0a8e0d0ae5feec8da3f56f2f5e2069e340b25d49945a', version: '1.0.9' }, + { url: 'https://files.pythonhosted.org/packages/74/77/2a5ccb2440d54b7a87e5716206c973ea329232c3a74f06860ad2fa979a67/0x-contract-addresses-3.0.0.dev2.tar.gz#sha256=6759639fcbcfc577a727145dbfa08faf5115d5729858cdb1e508510ed0dfdc87', version: '3.0.0.dev2' }, + { url: 'https://files.pythonhosted.org/packages/76/f7/c6971f37fe7890d8747f8e7de1c2613a75c154d3f05aca0f88fe7d0c0ff9/0x-contract-addresses-3.0.0.dev3.tar.gz#sha256=31fa7d3598fd9667a9d747287cc3c531e0f0fb5999e198903b6f681edbd8f270', version: '3.0.0.dev3' }, { url: 'https://files.pythonhosted.org/packages/78/21/a60c322d212bdf67b0fceabd48873040a1908b6ff56ac6047ac0f61dd502/0lever_so-1.1.3-py2-none-any.whl#sha256=475e9dc19597e247b510d62bf9e11a564a03678129095ae92c97c3ff4e1ba932', version: '1.1.3' }, - { url: 'https://files.pythonhosted.org/packages/ec/75/e1d501829ca2ceb2c678fff9ff37182da5c860d16d0702f4d82a8acf7f31/0lever_so-1.2.0-py2-none-any.whl#sha256=45fd5de96b0d8a3e83e160835f72f6233ca657fa627f0c87b61cc15f6f0f845a', version: '1.2.0' }, - { url: 'https://files.pythonhosted.org/packages/39/8f/a57ca099de0406ea8567adb18ba8545bb2bdeda2073028ee74b658f841be/0lever_utils-0.0.1-py2-none-any.whl#sha256=377b2adb6e59373dfbfabdfbb90babf35d2cf761ec02e122994c20291f879691', version: '0.0.1' }, - { url: 'https://files.pythonhosted.org/packages/2e/f3/e9e87d7d80bda76d4dacfcea880274c3bbd8f8c195b02348ecf07ee0179c/0lever_utils-0.0.2-py2-none-any.whl#sha256=1e91f3df348f5d1775d2f258503daf62d92fdfdf7f2678a50c775b64350eab4d', version: '0.0.2' }, - { url: 'https://files.pythonhosted.org/packages/f0/ae/24eb23ed53ea412ec6bbf4a3f38d53773eb0bf05a46f9aa05975abb01c02/0lever_utils-0.0.2-py3-none-any.whl#sha256=49dda99e024f5af08dde0a6602ee2725fdc6e0c8eaeebbb87582c334d19a4f7c', version: '0.0.2' }, - { url: 'https://files.pythonhosted.org/packages/1d/34/ba1fa03f9db5cd5267167fd6093bc478e92a3699ca1d2fc16f6950af89c5/0lever_utils-0.0.3-py2-none-any.whl#sha256=fb4684d2026ff6bc26df92c8cf6332fe9593e55b27a6c306a3aeda5fe07179d5', version: '0.0.3' }, - { url: 'https://files.pythonhosted.org/packages/19/91/69bcda2d03734913a26469f21868d32621c624aaa82762908e2febe98ca8/0lever_utils-0.0.3-py3-none-any.whl#sha256=db0849f8f05c04ae3f4745d00355c61280b627ffc520b7cc8aa904e4fd17e097', version: '0.0.3' }, - { url: 'https://files.pythonhosted.org/packages/ea/92/b711c82299975869648a8f79bce2b28c4120e2c6088482b896110d0c0397/0lever_utils-0.0.4-py2-none-any.whl#sha256=6042aff9fc2c31eda24a004dc1b70fcaea2eb9d5901ad90327e10b924e190cf0', version: '0.0.4' }, - { url: 'https://files.pythonhosted.org/packages/f5/32/6cc29ecda3cf752556247a39bcf34d440e236f817f458ff354e1f1d0521b/0lever_utils-0.0.4-py3-none-any.whl#sha256=ff1160a666afddb87892d3c50869bddb01f6e05c35ab62825414c86fe433acec', version: '0.0.4' }, - { url: 'https://files.pythonhosted.org/packages/fa/2a/ddb55bee3ebf13139eafa0a4dc5ba151561d318138508c5282f33578f74a/0lever_utils-0.0.5-py2-none-any.whl#sha256=5516c223f26b8dd3655619976a472e653bc1679cc1db02f506a7b17c138bd649', version: '0.0.5' }, - { url: 'https://files.pythonhosted.org/packages/c4/89/09009be8d127201e3541435ac84ff57c4e3cd2213f8ae7d97f0f32cea31c/0lever_utils-0.0.5-py3-none-any.whl#sha256=4eac2c9963216b58792e5a2f5fd5e37755d82c0dd6ba1454313d92790a61fbb7', version: '0.0.5' }, + { url: 'https://files.pythonhosted.org/packages/78/62/2d4e6938f108aad2cf13a5b4900e371a041446402cbe8167e1900f6d1716/0lever_so-1.0.8-py2-none-any.whl#sha256=9151d51d191a66d5808269245afb8fa0c09313996d382eb320d64c53f079acb8', version: '1.0.8' }, + { url: 'https://files.pythonhosted.org/packages/79/29/f31b78d51b59eafae5b7a876e5d18870c597ca8913436f0ab4b16bc3b9fa/007-0.0.1.tar.gz#sha256=570f9b3c06b04d1e53cc9304e2a3b127731e31e7c8636df5a02aba664e618a88', version: '0.0.1' }, { url: 'https://files.pythonhosted.org/packages/80/f5/61a6a5f709ca20158fed62b8b8755b8765e3320860f6368487dda143a772/0lever_utils-0.0.6-py2-none-any.whl#sha256=edcfc3a5243feb2c7db3d8a19dbc629d89c583784f21edd5410be3e65ddc2e06', version: '0.0.6' }, - { url: 'https://files.pythonhosted.org/packages/70/0f/f8459388d19c9cca20d86e6453afca76567fff7405feea80de0f8e003efc/0lever_utils-0.0.6-py3-none-any.whl#sha256=29206dab46a7405ac455b6b39b7501b37c3be6728051bf35b1487c27c943fb3b', version: '0.0.6' }, - { url: 'https://files.pythonhosted.org/packages/5c/c8/9d580a308885959eb79107c7286995fe30c2b1065a04a28b9e7746788718/0lever_utils-0.0.7-py2-none-any.whl#sha256=91a8683614eedb2b3e8877fb6690965f39ed6feb3aa27e5ea9bed949b36503be', version: '0.0.7' }, + { url: 'https://files.pythonhosted.org/packages/82/bb/a0c60cf1a52fdaabfee3172412137ffc11fe3d4f54be7d4b9c608d5f8b20/0-orchestrator-1.1.0a5.tar.gz#sha256=21edefac10907b2ce36f07c20b01c1abc1944ab0e32989c81ad853b9f3a8f99c', version: '1.1.0a5' }, + { url: 'https://files.pythonhosted.org/packages/84/f5/53e108fd0c64063620fac17858f359973e236c71b35729997287540aee1d/0x-contract-addresses-3.0.0.dev1.tar.gz#sha256=eed2f645e3f7990fd286ef73888b301d3413ca2efaada7e791bcd7100a58b9c2', version: '3.0.0.dev1' }, + { url: 'https://files.pythonhosted.org/packages/8c/e6/83748ba1e232167de61f2bf31ec53f4b7acdd1ced52bdf3ea3366ea48132/0-0.0.0-py2.py3-none-any.whl#sha256=d8c8aeb13d410f713ea132d4268ef3dc1e113be6ec3ef2c31420df5c44e8e634', version: '0.0.0' }, { url: 'https://files.pythonhosted.org/packages/94/65/133d48c0af2b1b7b55e5a15a5a787020d35df1046425e26b971bd35d7d52/0lever_utils-0.0.7-py3-none-any.whl#sha256=aef746f3855927e09e4090cfd16abc7d75230d2ea53c751699db073e64687ad5', version: '0.0.7' }, - { url: 'https://files.pythonhosted.org/packages/c4/9d/db08970b39a542c5f30f08aa35352174456881c60f80ec9f4b1770a5789e/0lever_utils-0.1.0-py2-none-any.whl#sha256=5a03ca33e6d9bad4ed42a6667d3d5c5fc3efef099a37ef750d34e5e5da6c49fb', version: '0.1.0' }, - { url: 'https://files.pythonhosted.org/packages/1f/c8/32dd25d1e72229a37548eba24a873c63a368714382fc6bf18a041dd212b1/0lever_utils-0.1.0-py3-none-any.whl#sha256=3a4f2eadad572878b04b2f8fc9d6bcb31550bb742b95bed0d9c568d9cc7ae5f1', version: '0.1.0' }, - { url: 'https://files.pythonhosted.org/packages/6a/c6/cedc13f810e7561247df40ba8ead02831ebf7eee2a12537c4f507e33ace1/0lever_utils-0.1.1-py2-none-any.whl#sha256=47dda1e5c1dee794bcc1ba4d5fefd6bca99cf26c11613243af77a19e40443341', version: '0.1.1' }, - { url: 'https://files.pythonhosted.org/packages/5f/6e/0954156529b22e5b1193d7413a8cdc6ad88ec1a552238956dc2e93c043a8/0lever_utils-0.1.2-py2-none-any.whl#sha256=ae47664c69e2379882a8ef7058267aace7970bd1f9c45c24bc7500aaaaa25fa3', version: '0.1.2' }, + { url: 'https://files.pythonhosted.org/packages/94/68/acdf5c33b26f88186bd3f40d912d7388a8b6a10437f33ec85c49deb3b550/0x-contract-artifacts-3.0.0.dev0.tar.gz#sha256=fd9a55411968b844a3a81bcae1167682f31dd304adbbc6f720d1c7b43aaf6acd', version: '3.0.0.dev0' }, + { url: 'https://files.pythonhosted.org/packages/95/47/2444989f005f7f3f892fc2bd375946072c23325becde4a5e2bae729579f3/01d61084-d29e-11e9-96d1-7c5cf84ffe8e-0.1.0.tar.gz#sha256=8b97d404c652de7ebc481b4ccc22c5d837d2e1d0938efcb2ce47a4220784247a', version: '0.1.0' }, + { url: 'https://files.pythonhosted.org/packages/99/b1/8329b44e81c794ebe8772531fbb94df3afb107102d183c1b0a17abb49471/0121-0.0.1.tar.gz#sha256=c340f511c652c50e67fac4e85528064f4253f5850446c9258949574a5d541f92', version: '0.0.1' }, + { url: 'https://files.pythonhosted.org/packages/9b/16/0160f8c9dfafb8d59e0b2eac3b0264660e8cef16e4f7dcd2da34f4073f2d/0-core-client-1.1.0a4.tar.gz#sha256=601b69c5c93d4990399ddacd79d1a81e9af3570a44a3a55bb7edff315b7c084d', version: '1.1.0a4' }, { url: 'https://files.pythonhosted.org/packages/a0/01/63afd94765200387f5e377697b64c2ae150c7bbf97579602c0e6b5723000/0lever_utils-0.1.3-py2-none-any.whl#sha256=64b20e6ccc6bf993e4ad5b217199c88c489cf2530cee3c70333b56fce057dccf', version: '0.1.3' }, - { url: 'https://files.pythonhosted.org/packages/fe/a6/3189d263fed5988920a18c090e9f182cc32a8ded0e8df3ac86956cf41ed2/0lever_utils-0.1.4-py2-none-any.whl#sha256=8174bb227226c068ebf6fd5e845ae4193502a6488cf2ac01a9482d579161e9c8', version: '0.1.4' }, - { url: 'https://files.pythonhosted.org/packages/0c/b5/20dbb950ab388c9d7b3e5099d8956d5098a8acb02497a010b5cc21d34c0a/0lever_utils-0.1.5-py2-none-any.whl#sha256=6d12dae3ee2608fa071ca5caf76f1c2bf18519e49c4afbffdef611847b8b6aba', version: '0.1.5' }, - { url: 'https://files.pythonhosted.org/packages/01/d4/b73510e90eaace314156d4ffeddcdc32925e0ea93924c2f29266d55df475/0lever_utils-0.1.5-py3-none-any.whl#sha256=930cf8cf0edd37eb60fb0ca3760a23e5ad3c52a1295d01b73e489f2d3d0df511', version: '0.1.5' }, - { url: 'https://files.pythonhosted.org/packages/08/13/1bce760f7456e598f7156d4488a29a65419b8cf72b1004de3db459c25ba8/0lever_utils-0.1.6-py2-none-any.whl#sha256=bcdd895c07615e93dd261db391807871e3ff9898ee6ada10c5ea88a55bf04264', version: '0.1.6' }, - { url: 'https://files.pythonhosted.org/packages/f8/f3/ae0893b39b5074047ca858a4f945339effdeeed3b9cb307548af2c900492/0lever_utils-0.1.6-py3-none-any.whl#sha256=e0b63d97eacaa571f4da3ce55846b09935060b1bf60bc60d5ea1bf9c336ea766', version: '0.1.6' }, - { url: 'https://files.pythonhosted.org/packages/de/0a/742998c97b906aee0a0d4878d20c5090141fd8110f72d83d52f4c1941f67/0-orchestrator-1.1.0a0.tar.gz#sha256=bef128cef7e57e648ef6a651379793b1a63df90b4da9ffc995dd688e62ddb6d7', version: '1.1.0a0' }, - { url: 'https://files.pythonhosted.org/packages/e6/e2/813b1755dccc504d2494e924ca3253a612674379d987be606581fb297289/0_orchestrator-1.1.0a0-py3-none-any.whl#sha256=a1ba77c79f65e71fe92fe1050fe89b4fe88b9faaa3c16fe324f5da4c7e2d14e9', version: '1.1.0a0' }, - { url: 'https://files.pythonhosted.org/packages/14/19/93882065e97fe8d30b246ad47365b4a18c63846b1c8b5f294c4abcedba49/0-orchestrator-1.1.0a3.tar.gz#sha256=d9248bc9b55f645b6045f6bb4846ae0df0f7193e39633295d9967ba68665d177', version: '1.1.0a3' }, - { url: 'https://files.pythonhosted.org/packages/68/8b/bbed7b15b68637bb66fa28047b082fb5383f6ddb61ef8a723b3e46e5c4dd/0_orchestrator-1.1.0a3-py3-none-any.whl#sha256=237e32c255663a74cfc9b4f20cf69949ba10cfa52e5d3099194ad2ad35201b4c', version: '1.1.0a3' }, - { url: 'https://files.pythonhosted.org/packages/f7/c2/89c3dd8686fd4e69871e11f69f87971dd090b769450c39a6d0f002a0fcb9/0-orchestrator-1.1.0a4.tar.gz#sha256=36e8fd4b8ccd29d4f144134a5624b835749ab6d15fc85e6db5c46a7082b5303f', version: '1.1.0a4' }, + { url: 'https://files.pythonhosted.org/packages/a3/b4/61ad204de90c962698982b0e4aac34d4db9737041396b2c6c6860276cdf0/0.0.1-0.0.1.tar.gz#sha256=b5ebdc3ae6be725b4e8c4959790022b431e183b275dfa673a7521c2acf851d40', version: '0.0.1' }, { url: 'https://files.pythonhosted.org/packages/aa/2d/a4193ef2473ec3b370e1f09beb57f161a24f7ca0fe96258f33759dda33b6/0_orchestrator-1.1.0a4-py3-none-any.whl#sha256=f3a74112dd8a2a0622c77b276ad59d483f62b6bdfce8697f1d6e0b2524860bfe', version: '1.1.0a4' }, - { url: 'https://files.pythonhosted.org/packages/82/bb/a0c60cf1a52fdaabfee3172412137ffc11fe3d4f54be7d4b9c608d5f8b20/0-orchestrator-1.1.0a5.tar.gz#sha256=21edefac10907b2ce36f07c20b01c1abc1944ab0e32989c81ad853b9f3a8f99c', version: '1.1.0a5' }, - { url: 'https://files.pythonhosted.org/packages/d4/75/06331e14b61541ac67afecb713ce6d0e3be5b52a513887c4cc74ef8bb568/0_orchestrator-1.1.0a5-py3-none-any.whl#sha256=581ee83684cb57ba5c55a0b7d3a8aa24f0ccca087b7e205d5c0ca22b47fea303', version: '1.1.0a5' }, - { url: 'https://files.pythonhosted.org/packages/f7/92/d10e965ef66b41fdad63a44899a7cb6084eaff81eb35de275ee48f10b9d5/0-orchestrator-1.1.0a7.tar.gz#sha256=2cfc80c8589f2f622db351c2aaf49136d3125318304463e9a127ad68902b9262', version: '1.1.0a7' }, - { url: 'https://files.pythonhosted.org/packages/eb/ae/8c0ce308eaed5419cc1e5b097e635c2f0d19fe94a71310e325413a58671a/0_orchestrator-1.1.0a7-py3-none-any.whl#sha256=b09acf91c50222fc64664095684c5945a8a3f9ed275739d713d4b01c8ae43746', version: '1.1.0a7' }, + { url: 'https://files.pythonhosted.org/packages/ab/c1/3962bef93118a862cb38f3fc3b1f9e6d3acfb8e1fff64879d2c54463b258/0x-contract-addresses-3.0.0.dev0.tar.gz#sha256=5a9a21d2c76ff6a10cbb9573d239a487e8e4cb90620d6e6806f72f6e6bf6a12a', version: '3.0.0.dev0' }, + { url: 'https://files.pythonhosted.org/packages/ac/78/83c3d46cdcf616bf64b60cc35bbcc2dc9504811516e07527a4ab3af6e0c7/01d61084_d29e_11e9_96d1_7c5cf84ffe8e-0.1.0-py3-none-any.whl#sha256=258f18753542f8bb6715fdfe5691313443c92fc80b2050e36eebac81a42ec3b4', version: '0.1.0' }, + { url: 'https://files.pythonhosted.org/packages/b0/81/b2cb9d8fdcffdbe1988009b7fef8ec0a29cf07c8016e66a02dd9941cfe62/02exercicio-1.0.0.tar.gz#sha256=71a5ffda2437ca70bb90069155fba43bfd8694eab65d9a7875286fd955cbe02d', version: '1.0.0' }, + { url: 'https://files.pythonhosted.org/packages/b0/e9/0bf97f93c7fe78b0983c5d375d670bebcdb3526e6f2e60c4c7e733021c27/021-1.0.tar.gz#sha256=6ff3159b4fe981c0702437a0c3004940c623ea6cdf4efd9ac74dac094e622160', version: '1.0' }, + { url: 'https://files.pythonhosted.org/packages/b9/24/6526bbe0e479f4272887998feb7e801f10d37a3e325fd129da448f795211/0x10c-asm-0.0.1.tar.gz#sha256=6d4c95c53b4c989d9a26d16b21d643bff1c40c9e1b213d6a800616d04eee0d18', version: '0.0.1' }, + { url: 'https://files.pythonhosted.org/packages/ba/a1/568bdbb82f1ae8a283f147c31deca9cea2e9cc7d47e4227681d71c55dda4/0x_contract_addresses-3.0.0-py3-none-any.whl#sha256=7ca9f02bfc9fb1ea7368f929dd9f90bef2baaa996642de45ab2304f7c914bec0', version: '3.0.0' }, + { url: 'https://files.pythonhosted.org/packages/c3/72/441451eb853fca52c8630b3d0cd6c555e135621ae07810fd688ee9d05b2b/0x-contract-addresses-2.0.1.tar.gz#sha256=df8280ebf1abaa0e62ea8872c1ca93b7329b117df930ab32be478405712b4630', version: '2.0.1' }, + { url: 'https://files.pythonhosted.org/packages/c3/82/c0ef77f86571d9d6bdc697424cfdc3b04f6a8db6a1497b851a0f4a862401/0_core_client-1.1.0a3-py3-none-any.whl#sha256=092c89c05104a59d11ac2604c5af10cb0106bbbb521b42844dee13dd2c80606b', version: '1.1.0a3' }, + { url: 'https://files.pythonhosted.org/packages/c4/89/09009be8d127201e3541435ac84ff57c4e3cd2213f8ae7d97f0f32cea31c/0lever_utils-0.0.5-py3-none-any.whl#sha256=4eac2c9963216b58792e5a2f5fd5e37755d82c0dd6ba1454313d92790a61fbb7', version: '0.0.5' }, + { url: 'https://files.pythonhosted.org/packages/c4/9d/db08970b39a542c5f30f08aa35352174456881c60f80ec9f4b1770a5789e/0lever_utils-0.1.0-py2-none-any.whl#sha256=5a03ca33e6d9bad4ed42a6667d3d5c5fc3efef099a37ef750d34e5e5da6c49fb', version: '0.1.0' }, + { url: 'https://files.pythonhosted.org/packages/c4/a0/4562cda161dc4ecbbe9e2a11eb365400c0461845c5be70d73869786809c4/0805nexter-1.2.0.zip#sha256=49785c6ae39ea511b3c253d7621c0b1b6228be2f965aca8a491e6b84126d0709', version: '1.2.0' }, + { url: 'https://files.pythonhosted.org/packages/c6/ab/4a317ae0d0c7c911f1c77719c553fc46a12d981899ceb5d47220fc3d535c/00print_lol-1.1.0.tar.gz#sha256=c452b0cc78f3a5edecbc6d160d2fa14c012d78403b0206558bcf1444eb5d1e2e', version: '1.1.0' }, + { url: 'https://files.pythonhosted.org/packages/c9/3d/947b2c7b6b18b94c524384463ba255db77e36756c800406f453eac69e5f4/0lever_so-1.1.1-py3-none-any.whl#sha256=2386ed3c8da48edf47bb884bc15d6b72666e2e9232d1b3b003852371aa4fe622', version: '1.1.1' }, + { url: 'https://files.pythonhosted.org/packages/cd/1c/52c3a1c88b2a2821ea7d2afc3c7883a8d73880dd4de4199b8d5e7d9773bd/0-core-client-1.1.0a8.tar.gz#sha256=663508e24643ad3a261b8b317e34ad6f096d2bae8997fb9155629e941b78986b', version: '1.1.0a8' }, + { url: 'https://files.pythonhosted.org/packages/d1/bb/1f526e72697d8ccd77c7f513ba7d1b23e45642a0ed2bb2dd49f875310c13/0lever_so-1.1.1-py2-none-any.whl#sha256=ca2347e28940daf1cd780f767a4b4bc86ba2f1ac79194552221b98cc8425d25a', version: '1.1.1' }, { url: 'https://files.pythonhosted.org/packages/d2/5b/92b1be5d9ff54b2409b4f77d85e90f2e3bf6488d040f6f3269de0ed3aa0e/0-orchestrator-1.1.0-alpha-7-1.tar.gz#sha256=7789ed84a06a08f072ed92dfba91e46c2aab6616df80afdbdb570c017ea4852f', version: '1.1.0-alpha-7-1' }, - { url: 'https://files.pythonhosted.org/packages/0d/ce/6e7c14ebc167f31a8bb9d0b48116359794c902a60c29e0c8d197b13e8bdd/0_orchestrator-1.1.0a7.post1-py3-none-any.whl#sha256=72f076dec0cbe098ebc085fa083b30e2671a310d8186620f1c52e73c220ab81f', version: '1.1.0a7.post1' }, - { url: 'https://files.pythonhosted.org/packages/06/83/ed65c68212f5f145063ba6e3df8e8a58f724564db0f33224f3e4b567f78f/0-orchestrator-1.1.0a8.tar.gz#sha256=bf89940a3d3f3d1b8fac912cbc9b173f7ca0aa2aee623fa206771f230d0467dd', version: '1.1.0a8' }, - { url: 'https://files.pythonhosted.org/packages/21/53/f43b2f754284fe76436e06aac50c42ad984587dcfcb3e35c0999158223d5/0_orchestrator-1.1.0a8-py3-none-any.whl#sha256=5460255971955f78265894404032a33a14d3a6c93c1099d5c130b520e96d2cd9', version: '1.1.0a8' }, - { url: 'https://files.pythonhosted.org/packages/33/c0/d82e190c0b6284b1d0bdd8493f11edf3a80ed601b92c44dacc0dd4b43648/0wdg9nbmpm-0.1.tar.gz#sha256=7130b1f19df69c3dc91b99fa3b31ebae873ef93b3d601285dbd3b3f97271d625', version: '0.1' }, - { url: 'https://files.pythonhosted.org/packages/34/fc/f4a8a1569c906c325d0b41d5b3ac6d115bb1fa860ec46362cf61cf649495/0x-0.1.tar.gz#sha256=4d3f4ad49c37166c79d33f8c58c92558d0f044336248f70296661a046a9b5f1b', version: '0.1' }, + { url: 'https://files.pythonhosted.org/packages/d2/5b/92b1be5d9ff54b2409b4f77d85e90f2e3bf6488d040f6f3269de0ed3aa0e/0-orchestrator-1.1.0-alpha-7-1.tar.gz#sha256=7789ed84a06a08f072ed92dfba91e46c2aab6616df80afdbdb570c017ea4852f', version: '1.1.0-alpha-7-1' }, + { url: 'https://files.pythonhosted.org/packages/d3/cb/91061d33b8991125641585251a5251ac054d3bc7606cd80a0968995430c7/0-core-client-1.1.0a3.tar.gz#sha256=d47d162505074abfaed298d5463ab40e804438c59bc1d5f165b03d257c1de0ff', version: '1.1.0a3' }, + { url: 'https://files.pythonhosted.org/packages/d4/75/06331e14b61541ac67afecb713ce6d0e3be5b52a513887c4cc74ef8bb568/0_orchestrator-1.1.0a5-py3-none-any.whl#sha256=581ee83684cb57ba5c55a0b7d3a8aa24f0ccca087b7e205d5c0ca22b47fea303', version: '1.1.0a5' }, + { url: 'https://files.pythonhosted.org/packages/d9/f0/151d0f3bb569e3496ff6edbe8705ce077ac765aea80f8922f16c5d8376c4/0x_contract_addresses-3.0.0.dev2-py3-none-any.whl#sha256=001df466ee9c04c2379357f361c6ac55ec155dcf0da2e89c91a4d58b1fce481d', version: '3.0.0.dev2' }, + { url: 'https://files.pythonhosted.org/packages/de/0a/742998c97b906aee0a0d4878d20c5090141fd8110f72d83d52f4c1941f67/0-orchestrator-1.1.0a0.tar.gz#sha256=bef128cef7e57e648ef6a651379793b1a63df90b4da9ffc995dd688e62ddb6d7', version: '1.1.0a0' }, { url: 'https://files.pythonhosted.org/packages/df/4a/170d68a650f57aea9bda4a814642301504f750385891f56ed0d9d2c46cc7/0x01-autocert-dns-aliyun-0.1.tar.gz#sha256=f3ceaa3f0b8c3ffe10705b890f2a96dabc64e2923debbaa4908eb939efd49499', version: '0.1' }, - { url: 'https://files.pythonhosted.org/packages/0d/9f/a24c516016770a80bb33dffd852762fe8e61a5127d94b4bdb290003a6b6a/0x01-letsencrypt-0.1.tar.gz#sha256=3b6786a2f24382ea7b42bbc543c2fce70c4fe4c0de49a24c1098cb41e271526e', version: '0.1' }, - { url: 'https://files.pythonhosted.org/packages/b9/24/6526bbe0e479f4272887998feb7e801f10d37a3e325fd129da448f795211/0x10c-asm-0.0.1.tar.gz#sha256=6d4c95c53b4c989d9a26d16b21d643bff1c40c9e1b213d6a800616d04eee0d18', version: '0.0.1' }, { url: 'https://files.pythonhosted.org/packages/e1/3a/6588c9c52a06e64a903314bc810ca712c3fc6c27b86779c057e23e7512b6/0x10c-asm-0.0.2.tar.gz#sha256=e4703f8bd0a44c473469ce6b57d4dde3c7acbf7e6c2df75d83570ae94fb08d6f', version: '0.0.2' }, - { url: 'https://files.pythonhosted.org/packages/31/94/3f5aead5e720ab41e7a6d6ecd247bb5f72f4ad0706d3b622c967474ddc64/0x-contract-addresses-2.0.0.tar.gz#sha256=5df5c618005262df882094d72af31c7a390ce21e8f9d235d008ccf2a311a8125', version: '2.0.0' }, - { url: 'https://files.pythonhosted.org/packages/23/b0/55c18ecf8e093fb0c08024ad7d2559d4023639259692d9dd01e5ffcd30e3/0x_contract_addresses-2.0.0-py3-none-any.whl#sha256=f285f96d401eb13f572343dc4f658689b745642a66e0767ecea94e0d3be629ac', version: '2.0.0' }, - { url: 'https://files.pythonhosted.org/packages/c3/72/441451eb853fca52c8630b3d0cd6c555e135621ae07810fd688ee9d05b2b/0x-contract-addresses-2.0.1.tar.gz#sha256=df8280ebf1abaa0e62ea8872c1ca93b7329b117df930ab32be478405712b4630', version: '2.0.1' }, - { url: 'https://files.pythonhosted.org/packages/fe/ec/0c4b906147bfdb09ede4deff7489ea33267daf14f6d8c9706ed1b1ac3597/0x_contract_addresses-2.0.1-py3-none-any.whl#sha256=0514f73c92694bbeee2704374fcd2f0eefbe8bbdfc43dd95dc0ab6c262d4c058', version: '2.0.1' }, - { url: 'https://files.pythonhosted.org/packages/47/52/d189b2c6d2954effaf12960b8916b9d62fb8150083a42ef9b5e62462ac32/0x-contract-addresses-2.1.0.tar.gz#sha256=d1df84b35d9a35b73c1054c090942e31ff152526249d8d251c7b2fc684e045ab', version: '2.1.0' }, - { url: 'https://files.pythonhosted.org/packages/0e/e7/2bc27a48170fc7d4f458fda9d9ff973f1780bf1b0fa2fd71de89124d7014/0x_contract_addresses-2.1.0-py3-none-any.whl#sha256=dd78dd0429bac1ff88e1d1bf5422f9f17d7738e1fa49da97755056792d9f5945', version: '2.1.0' }, + { url: 'https://files.pythonhosted.org/packages/e6/e2/813b1755dccc504d2494e924ca3253a612674379d987be606581fb297289/0_orchestrator-1.1.0a0-py3-none-any.whl#sha256=a1ba77c79f65e71fe92fe1050fe89b4fe88b9faaa3c16fe324f5da4c7e2d14e9', version: '1.1.0a0' }, + { url: 'https://files.pythonhosted.org/packages/ea/92/b711c82299975869648a8f79bce2b28c4120e2c6088482b896110d0c0397/0lever_utils-0.0.4-py2-none-any.whl#sha256=6042aff9fc2c31eda24a004dc1b70fcaea2eb9d5901ad90327e10b924e190cf0', version: '0.0.4' }, + { url: 'https://files.pythonhosted.org/packages/eb/ae/8c0ce308eaed5419cc1e5b097e635c2f0d19fe94a71310e325413a58671a/0_orchestrator-1.1.0a7-py3-none-any.whl#sha256=b09acf91c50222fc64664095684c5945a8a3f9ed275739d713d4b01c8ae43746', version: '1.1.0a7' }, + { url: 'https://files.pythonhosted.org/packages/eb/fe/3832155e33dc6ff60586a6552f21eaf3214fff816ac2cae5deffae730ef2/0lever_so-1.1.0-py3-none-any.whl#sha256=06851a36f3853530971b6c21b3db38360d72f6493738ad74351ce9fbaa97e8d6', version: '1.1.0' }, + { url: 'https://files.pythonhosted.org/packages/ec/65/c0116953c9a3f47de89e71964d6c7b0c783b01f29fa3390584dbf3046b4d/0805nexter-1.1.0.zip#sha256=52cd128ad3afe539478abc7440d4b043384295fbe6b0958a237cb6d926465035', version: '1.1.0' }, + { url: 'https://files.pythonhosted.org/packages/ec/75/e1d501829ca2ceb2c678fff9ff37182da5c860d16d0702f4d82a8acf7f31/0lever_so-1.2.0-py2-none-any.whl#sha256=45fd5de96b0d8a3e83e160835f72f6233ca657fa627f0c87b61cc15f6f0f845a', version: '1.2.0' }, { url: 'https://files.pythonhosted.org/packages/ed/e2/23a769ee1845baa615fcfa20f540844b95193111c8c9317f3840ecf764de/0x-contract-addresses-2.2.0.tar.gz#sha256=b9cc6fc7210e8c2e0bb3154d0cdd65fa747145ceb3a388a0146a781b029f6617', version: '2.2.0' }, + { url: 'https://files.pythonhosted.org/packages/f0/ae/24eb23ed53ea412ec6bbf4a3f38d53773eb0bf05a46f9aa05975abb01c02/0lever_utils-0.0.2-py3-none-any.whl#sha256=49dda99e024f5af08dde0a6602ee2725fdc6e0c8eaeebbb87582c334d19a4f7c', version: '0.0.2' }, + { url: 'https://files.pythonhosted.org/packages/f5/32/6cc29ecda3cf752556247a39bcf34d440e236f817f458ff354e1f1d0521b/0lever_utils-0.0.4-py3-none-any.whl#sha256=ff1160a666afddb87892d3c50869bddb01f6e05c35ab62825414c86fe433acec', version: '0.0.4' }, + { url: 'https://files.pythonhosted.org/packages/f5/90/897a16f3cd9044fe18a238ecaa9c421f8b54531bd7ef34e7ec405c5a319a/0-core-client-1.1.0a7.tar.gz#sha256=2f45465e53f57b6f7570aa959d27f6ab5ea32ee395e210df8de23f1335b3bcc8', version: '1.1.0a7' }, + { url: 'https://files.pythonhosted.org/packages/f7/92/d10e965ef66b41fdad63a44899a7cb6084eaff81eb35de275ee48f10b9d5/0-orchestrator-1.1.0a7.tar.gz#sha256=2cfc80c8589f2f622db351c2aaf49136d3125318304463e9a127ad68902b9262', version: '1.1.0a7' }, + { url: 'https://files.pythonhosted.org/packages/f7/c2/89c3dd8686fd4e69871e11f69f87971dd090b769450c39a6d0f002a0fcb9/0-orchestrator-1.1.0a4.tar.gz#sha256=36e8fd4b8ccd29d4f144134a5624b835749ab6d15fc85e6db5c46a7082b5303f', version: '1.1.0a4' }, + { url: 'https://files.pythonhosted.org/packages/f8/f3/ae0893b39b5074047ca858a4f945339effdeeed3b9cb307548af2c900492/0lever_utils-0.1.6-py3-none-any.whl#sha256=e0b63d97eacaa571f4da3ce55846b09935060b1bf60bc60d5ea1bf9c336ea766', version: '0.1.6' }, + { url: 'https://files.pythonhosted.org/packages/fa/2a/ddb55bee3ebf13139eafa0a4dc5ba151561d318138508c5282f33578f74a/0lever_utils-0.0.5-py2-none-any.whl#sha256=5516c223f26b8dd3655619976a472e653bc1679cc1db02f506a7b17c138bd649', version: '0.0.5' }, { url: 'https://files.pythonhosted.org/packages/fa/f5/7a29cb2377058c738d29bb9232168fdea17d94801fbace3e90054e2139de/0x_contract_addresses-2.2.0-py3-none-any.whl#sha256=4cc518ee16bd06cc8bfc531fd54b3da905dc17ac59b66d52b66e27ccbdb151cc', version: '2.2.0' }, - { url: 'https://files.pythonhosted.org/packages/ab/c1/3962bef93118a862cb38f3fc3b1f9e6d3acfb8e1fff64879d2c54463b258/0x-contract-addresses-3.0.0.dev0.tar.gz#sha256=5a9a21d2c76ff6a10cbb9573d239a487e8e4cb90620d6e6806f72f6e6bf6a12a', version: '3.0.0.dev0' }, + { url: 'https://files.pythonhosted.org/packages/fd/49/c01735a9c8d028f22356f8e3086b412530a2f288b072945e0c079ef29bd6/007-0.0.2.tar.gz#sha256=a5f7fe73035bcd3944ac30843a595dc47a0e5d20110d70c9998f0396d104ee6c', version: '0.0.2' }, { url: 'https://files.pythonhosted.org/packages/fd/51/a7a8468a4bc226a4e96fda87acfb36bde1582b04c4435d4fb56dce2cd0d6/0x_contract_addresses-3.0.0.dev0-py3-none-any.whl#sha256=cbe05e7827fe3e6b44e237fccbed3803bf881f4bfaf195043d2b472606dbd148', version: '3.0.0.dev0' }, - { url: 'https://files.pythonhosted.org/packages/84/f5/53e108fd0c64063620fac17858f359973e236c71b35729997287540aee1d/0x-contract-addresses-3.0.0.dev1.tar.gz#sha256=eed2f645e3f7990fd286ef73888b301d3413ca2efaada7e791bcd7100a58b9c2', version: '3.0.0.dev1' }, - { url: 'https://files.pythonhosted.org/packages/4b/f7/90b5cf54de20704b5e09247594ed656e7511b8dea12ae6fea177ede9c700/0x_contract_addresses-3.0.0.dev1-py3-none-any.whl#sha256=1d045c6733b727a965470933e4184494636d3ab07675681c3e65ccef80eb721d', version: '3.0.0.dev1' }, - { url: 'https://files.pythonhosted.org/packages/74/77/2a5ccb2440d54b7a87e5716206c973ea329232c3a74f06860ad2fa979a67/0x-contract-addresses-3.0.0.dev2.tar.gz#sha256=6759639fcbcfc577a727145dbfa08faf5115d5729858cdb1e508510ed0dfdc87', version: '3.0.0.dev2' }, - { url: 'https://files.pythonhosted.org/packages/d9/f0/151d0f3bb569e3496ff6edbe8705ce077ac765aea80f8922f16c5d8376c4/0x_contract_addresses-3.0.0.dev2-py3-none-any.whl#sha256=001df466ee9c04c2379357f361c6ac55ec155dcf0da2e89c91a4d58b1fce481d', version: '3.0.0.dev2' }, - { url: 'https://files.pythonhosted.org/packages/76/f7/c6971f37fe7890d8747f8e7de1c2613a75c154d3f05aca0f88fe7d0c0ff9/0x-contract-addresses-3.0.0.dev3.tar.gz#sha256=31fa7d3598fd9667a9d747287cc3c531e0f0fb5999e198903b6f681edbd8f270', version: '3.0.0.dev3' }, - { url: 'https://files.pythonhosted.org/packages/5d/be/460cab4688fa1025c65ecba1f3d56264faa0319ee3ad6e38475f8125aca1/0x_contract_addresses-3.0.0.dev3-py3-none-any.whl#sha256=63f47a7735e5bdf089a2d87c469540b58ce82f10bae4ae076fac25a5f5e9f02c', version: '3.0.0.dev3' }, - { url: 'https://files.pythonhosted.org/packages/48/fa/2bfa40b043c9539b12aed4ff6fee834c8bbdeacf3e8388842d2fef0d1b84/0x-contract-addresses-3.0.0.tar.gz#sha256=677f7390d6505b85647af3dfa4765c307a26344d94716d263993c1f7efbf88d8', version: '3.0.0' }, - { url: 'https://files.pythonhosted.org/packages/ba/a1/568bdbb82f1ae8a283f147c31deca9cea2e9cc7d47e4227681d71c55dda4/0x_contract_addresses-3.0.0-py3-none-any.whl#sha256=7ca9f02bfc9fb1ea7368f929dd9f90bef2baaa996642de45ab2304f7c914bec0', version: '3.0.0' }, - { url: 'https://files.pythonhosted.org/packages/56/79/2f81c26461433b3036cd34d396325c38ade3a9aa64e6636540b67bc084d4/0x-contract-artifacts-2.0.0.tar.gz#sha256=7c1a0b4204cf08f46efad2b1a19d19e2d6189e1bea9e220e41caa0f145159316', version: '2.0.0' }, - { url: 'https://files.pythonhosted.org/packages/4b/ab/1df6cee9478914fc9119e9f7fe0463d4a57e63149aa70c496cce48457c07/0x_contract_artifacts-2.0.0-py3-none-any.whl#sha256=44146561e762958fcae64b0202da3416b78a3780f0265a4b57f7e3b6af26b120', version: '2.0.0' }, - { url: 'https://files.pythonhosted.org/packages/94/68/acdf5c33b26f88186bd3f40d912d7388a8b6a10437f33ec85c49deb3b550/0x-contract-artifacts-3.0.0.dev0.tar.gz#sha256=fd9a55411968b844a3a81bcae1167682f31dd304adbbc6f720d1c7b43aaf6acd', version: '3.0.0.dev0' }, - { url: 'https://files.pythonhosted.org/packages/d2/5b/92b1be5d9ff54b2409b4f77d85e90f2e3bf6488d040f6f3269de0ed3aa0e/0-orchestrator-1.1.0-alpha-7-1.tar.gz#sha256=7789ed84a06a08f072ed92dfba91e46c2aab6616df80afdbdb570c017ea4852f', version: '1.1.0-alpha-7-1' }, + { url: 'https://files.pythonhosted.org/packages/fd/ee/207c1511984df8cb7bb44b2de96c72b954618fe697c187eb4ef6fae1c7ad/0lever_so-1.0.9-py2-none-any.whl#sha256=abd147124d326cceb24b42eb88586ddbfbff7ff69a82380282a855a1ac30eca4', version: '1.0.9' }, + { url: 'https://files.pythonhosted.org/packages/fe/a6/3189d263fed5988920a18c090e9f182cc32a8ded0e8df3ac86956cf41ed2/0lever_utils-0.1.4-py2-none-any.whl#sha256=8174bb227226c068ebf6fd5e845ae4193502a6488cf2ac01a9482d579161e9c8', version: '0.1.4' }, + { url: 'https://files.pythonhosted.org/packages/fe/ec/0c4b906147bfdb09ede4deff7489ea33267daf14f6d8c9706ed1b1ac3597/0x_contract_addresses-2.0.1-py3-none-any.whl#sha256=0514f73c92694bbeee2704374fcd2f0eefbe8bbdfc43dd95dc0ab6c262d4c058', version: '2.0.1' }, + { url: 'https://files.pythonhosted.org/packages/ff/b9/6246538b88db7272f62d4eb0bd1afbb5ec402b24866be95059cc037d6970/00000a-0.0.2.tar.gz#sha256=3c1a3cdcc6cd2ca9a8dd44009509039dfa84928a4293069a74d5fc5c39e4b7a1', version: '0.0.2' }, ].each do |item| specify { expect(subject.version_from(item[:url])).to eql(item[:version]) } end diff --git a/spec/unit/ruby/parsers/gemfile_lock_spec.rb b/spec/unit/ruby/parsers/gemfile_lock_spec.rb index 3d3f442..321aeab 100644 --- a/spec/unit/ruby/parsers/gemfile_lock_spec.rb +++ b/spec/unit/ruby/parsers/gemfile_lock_spec.rb @@ -39,7 +39,7 @@ RSpec.describe Spandx::Ruby::Parsers::GemfileLock do specify do expect(subject).to match_array([ build('addressable', '2.7.0', path), - build('ast', '2.4.0', path), + build('ast', '2.4.1', path), build('benchmark-ips', '2.8.2', path), build('benchmark-malloc', '0.2.0', path), build('benchmark-perf', '0.6.0', path), @@ -51,22 +51,23 @@ RSpec.describe Spandx::Ruby::Parsers::GemfileLock do build('dotenv', '2.7.5', path), build('faraday', '1.0.1', path), build('hashdiff', '1.0.1', path), - build('licensed', '2.10.0', path), + build('licensed', '2.11.1', path), build('licensee', '9.14.0', path), build('mini_portile2', '2.4.0', path), build('multipart-post', '2.1.1', path), - build('nanospinner', '1.0.0', path), build('net-hippie', '0.3.2', path), build('nokogiri', '1.10.9', path), build('octokit', '4.18.0', path), + build('oj', '3.10.6', path), build('parallel', '1.19.1', path), - build('parser', '2.7.1.2', path), + build('parser', '2.7.1.3', path), build('parslet', '2.0.0', path), build('pathname-common_prefix', '0.0.1', path), build('public_suffix', '4.0.5', path), build('rainbow', '3.0.0', path), build('rake', '13.0.1', path), build('rake-compiler', '1.1.0', path), + build('regexp_parser', '1.7.1', path), build('reverse_markdown', '1.4.0', path), build('rexml', '3.2.4', path), build('rspec', '3.9.0', path), @@ -75,8 +76,9 @@ RSpec.describe Spandx::Ruby::Parsers::GemfileLock do build('rspec-expectations', '3.9.2', path), build('rspec-mocks', '3.9.1', path), build('rspec-support', '3.9.3', path), - build('rubocop', '0.83.0', path), - build('rubocop-rspec', '1.39.0', path), + build('rubocop', '0.85.1', path), + build('rubocop-ast', '0.0.3', path), + build('rubocop-rspec', '1.40.0', path), build('ruby-prof', '1.4.1', path), build('ruby-progressbar', '1.10.1', path), build('ruby-xxHash', '0.4.0.1', path), @@ -87,9 +89,10 @@ RSpec.describe Spandx::Ruby::Parsers::GemfileLock do build('terminal-table', '1.8.0', path), build('thor', '0.20.3', path), build('tomlrb', '1.3.0', path), - build('tty-screen', '0.7.1', path), + build('tty-cursor', '0.7.1', path), + build('tty-spinner', '0.9.3', path), build('unicode-display_width', '1.7.0', path), - build('vcr', '5.1.0', path), + build('vcr', '6.0.0', path), build('webmock', '3.8.3', path), build('zeitwerk', '2.3.0', path), ]) |
